diff --git a/docs/docs/fundamentals/installation.md b/docs/docs/fundamentals/installation.md index 409aac4bd5f..ce55451b9c0 100644 --- a/docs/docs/fundamentals/installation.md +++ b/docs/docs/fundamentals/installation.md @@ -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. diff --git a/plugin.js b/plugin.js index aa8d6315078..09f9cfc407f 100644 --- a/plugin.js +++ b/plugin.js @@ -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. @@ -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', @@ -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})`; } } @@ -490,7 +496,7 @@ function makeWorklet(t, fun, fileName) { t.identifier('__location'), false ), - t.stringLiteral(fileName) + t.stringLiteral(location) ) ), ]; @@ -518,7 +524,7 @@ 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. @@ -526,7 +532,7 @@ function processWorkletFunction(t, fun, fileName) { return; } - const newFun = makeWorklet(t, fun, fileName); + const newFun = makeWorklet(t, fun, state); const replacement = t.callExpression(newFun, []); @@ -546,14 +552,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), @@ -563,7 +569,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; @@ -581,14 +587,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()` or similar, but skips `something.onEnd()`. // Supports method chaining as well, e.g. `Gesture.Tap().onStart().onUpdate().onEnd()`. @@ -641,7 +647,7 @@ function processIfGestureHandlerEventCallbackFunctionNode(t, fun, fileName) { t.isCallExpression(fun.parent) && isGestureObjectEventCallbackMethod(t, fun.parent.callee) ) { - processWorkletFunction(t, fun, fileName); + processWorkletFunction(t, fun, state); } } @@ -697,7 +703,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 @@ -709,17 +715,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); }); } } @@ -764,14 +770,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); }, }, },