Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add opts for relative source location #3141

Merged
merged 1 commit into from Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/docs/fundamentals/installation.md
Expand Up @@ -30,6 +30,22 @@ Add Reanimated's babel plugin to your `babel.config.js`:
};
```

By default, Reanimated plugin generate source location using absolute path. You can configure to use relative path:

```js {5}
module.exports = {
...
plugins: [
...
[
'react-native-reanimated/plugin', {
relativeSourceLocation: true,
},
]
],
};
```

:::caution

Reanimated plugin has to be listed last.
Expand Down
45 changes: 25 additions & 20 deletions plugin.js
Expand Up @@ -331,7 +331,7 @@ function makeWorkletName(t, fun) {
return '_f'; // fallback for ArrowFunctionExpression and unnamed FunctionExpression
}

function makeWorklet(t, fun, fileName) {
function makeWorklet(t, fun, state) {
// Returns a new FunctionExpression which is a workletized version of provided
// FunctionDeclaration, FunctionExpression, ArrowFunctionExpression or ObjectMethod.

Expand All @@ -358,7 +358,7 @@ function makeWorklet(t, fun, fileName) {
'\n(' + (t.isObjectMethod(fun) ? 'function ' : '') + fun.toString() + '\n)';

const transformed = transformSync(code, {
filename: fileName,
filename: state.file.opts.filename,
presets: ['@babel/preset-typescript'],
plugins: [
'@babel/plugin-transform-shorthand-properties',
Expand Down Expand Up @@ -445,11 +445,17 @@ function makeWorklet(t, fun, fileName) {
);
const workletHash = hash(funString);

let location = state.file.opts.filename;
if (state.opts.relativeSourceLocation) {
const path = require('path');
location = path.relative(state.cwd, location);
}

const loc = fun && fun.node && fun.node.loc && fun.node.loc.start;
if (loc) {
const { line, column } = loc;
if (typeof line === 'number' && typeof column === 'number') {
fileName = `${fileName} (${line}:${column})`;
location = `${location} (${line}:${column})`;
}
}

Expand Down Expand Up @@ -490,7 +496,7 @@ function makeWorklet(t, fun, fileName) {
t.identifier('__location'),
false
),
t.stringLiteral(fileName)
t.stringLiteral(location)
)
),
];
Expand Down Expand Up @@ -530,15 +536,15 @@ function makeWorklet(t, fun, fileName) {
return newFun;
}

function processWorkletFunction(t, fun, fileName) {
function processWorkletFunction(t, fun, state) {
// Replaces FunctionDeclaration, FunctionExpression or ArrowFunctionExpression
// with a workletized version of itself.

if (!t.isFunctionParent(fun)) {
return;
}

const newFun = makeWorklet(t, fun, fileName);
const newFun = makeWorklet(t, fun, state);

const replacement = t.callExpression(newFun, []);

Expand All @@ -558,14 +564,14 @@ function processWorkletFunction(t, fun, fileName) {
);
}

function processWorkletObjectMethod(t, path, fileName) {
function processWorkletObjectMethod(t, path, state) {
// Replaces ObjectMethod with a workletized version of itself.

if (!t.isFunctionParent(path)) {
return;
}

const newFun = makeWorklet(t, path, fileName);
const newFun = makeWorklet(t, path, state);

const replacement = t.objectProperty(
t.identifier(path.node.key.name),
Expand All @@ -575,7 +581,7 @@ function processWorkletObjectMethod(t, path, fileName) {
path.replaceWith(replacement);
}

function processIfWorkletNode(t, fun, fileName) {
function processIfWorkletNode(t, fun, state) {
fun.traverse({
DirectiveLiteral(path) {
const value = path.node.value;
Expand All @@ -593,14 +599,14 @@ function processIfWorkletNode(t, fun, fileName) {
directive.value.value === 'worklet'
)
) {
processWorkletFunction(t, fun, fileName);
processWorkletFunction(t, fun, state);
}
}
},
});
}

function processIfGestureHandlerEventCallbackFunctionNode(t, fun, fileName) {
function processIfGestureHandlerEventCallbackFunctionNode(t, fun, state) {
// Auto-workletizes React Native Gesture Handler callback functions.
// Detects `Gesture.Tap().onEnd(<fun>)` or similar, but skips `something.onEnd(<fun>)`.
// Supports method chaining as well, e.g. `Gesture.Tap().onStart(<fun1>).onUpdate(<fun2>).onEnd(<fun3>)`.
Expand Down Expand Up @@ -653,7 +659,7 @@ function processIfGestureHandlerEventCallbackFunctionNode(t, fun, fileName) {
t.isCallExpression(fun.parent) &&
isGestureObjectEventCallbackMethod(t, fun.parent.callee)
) {
processWorkletFunction(t, fun, fileName);
processWorkletFunction(t, fun, state);
}
}

Expand Down Expand Up @@ -709,7 +715,7 @@ function isGestureObject(t, node) {
);
}

function processWorklets(t, path, fileName) {
function processWorklets(t, path, state) {
const name =
path.node.callee.type === 'MemberExpression'
? path.node.callee.property.name
Expand All @@ -721,17 +727,17 @@ function processWorklets(t, path, fileName) {
const properties = path.get('arguments.0.properties');
for (const property of properties) {
if (t.isObjectMethod(property)) {
processWorkletObjectMethod(t, property, fileName);
processWorkletObjectMethod(t, property, state);
} else {
const value = property.get('value');
processWorkletFunction(t, value, fileName);
processWorkletFunction(t, value, state);
}
}
} else {
const indexes = functionArgsToWorkletize.get(name);
if (Array.isArray(indexes)) {
indexes.forEach((index) => {
processWorkletFunction(t, path.get(`arguments.${index}`), fileName);
processWorkletFunction(t, path.get(`arguments.${index}`), state);
});
}
}
Expand Down Expand Up @@ -776,14 +782,13 @@ module.exports = function ({ types: t }) {
visitor: {
CallExpression: {
enter(path, state) {
processWorklets(t, path, state.file.opts.filename);
processWorklets(t, path, state);
},
},
'FunctionDeclaration|FunctionExpression|ArrowFunctionExpression': {
enter(path, state) {
const fileName = state.file.opts.filename;
processIfWorkletNode(t, path, fileName);
processIfGestureHandlerEventCallbackFunctionNode(t, path, fileName);
processIfWorkletNode(t, path, state);
processIfGestureHandlerEventCallbackFunctionNode(t, path, state);
},
},
},
Expand Down