diff --git a/packages/react-native-worklets/__tests__/__snapshots__/plugin.test.ts.snap b/packages/react-native-worklets/__tests__/__snapshots__/plugin.test.ts.snap index be3a9d6ca94f..168e4ef2bfe8 100644 --- a/packages/react-native-worklets/__tests__/__snapshots__/plugin.test.ts.snap +++ b/packages/react-native-worklets/__tests__/__snapshots__/plugin.test.ts.snap @@ -2384,9 +2384,11 @@ const animatedStyle = useAnimatedStyle(function null1Factory({ _worklet_1392490775014_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({ - width: 50 - }); + const null1 = function () { + return { + width: 50 + }; + }; null1.__closure = {}; null1.__workletHash = 1392490775014; null1.__pluginVersion = "x.y.z"; @@ -2863,6 +2865,42 @@ useAnimatedScrollHandler({ });" `; +exports[`babel plugin for react-compiler adds worklet directives to functions before react-compiler outlines them 1`] = ` +"import { c as _c } from "react/compiler-runtime"; +const TestComponent = t0 => { + const $ = _c(1); + if ($[0] !== "334946d229dc920aaf28bb8fd0705f10807290a3162fa05fe7deecf7dce3a2a2") { + for (let $i = 0; $i < 1; $i += 1) { + $[$i] = Symbol.for("react.memo_cache_sentinel"); + } + $[0] = "334946d229dc920aaf28bb8fd0705f10807290a3162fa05fe7deecf7dce3a2a2"; + } + useDerivedValue(_temp); + return null; +}; +const _worklet_16591647617375_init_data = { + code: "function _temp_null1(){return[1,2,3].map(function(){return null;});}", + location: "/dev/null", + sourceMap: "\\"mock source map\\"" +}; +const _temp = function _temp_null1Factory({ + _worklet_16591647617375_init_data +}) { + const _e = [new global.Error(), 1, -27]; + const _temp = function () { + return [1, 2, 3].map(() => null); + }; + _temp.__closure = {}; + _temp.__workletHash = 16591647617375; + _temp.__pluginVersion = "x.y.z"; + _temp.__initData = _worklet_16591647617375_init_data; + _temp.__stackDetails = _e; + return _temp; +}({ + _worklet_16591647617375_init_data +});" +`; + exports[`babel plugin for react-native-gesture-handler doesn't transform chained methods of objects containing Gesture property 1`] = ` "const foo = Something.Gesture.Tap().onEnd(() => { console.log('onEnd'); @@ -3067,8 +3105,8 @@ const foo = useTapGesture({ `; exports[`babel plugin for react-native-gesture-handler workletizes possibly chained gesture object callback functions automatically 1`] = ` -"const _worklet_2359797567586_init_data = { - code: "function null1(_event,_success){console.log('onEnd');}", +"const _worklet_13539781966089_init_data = { + code: "function null1(){console.log('onBegin');}", location: "/dev/null", sourceMap: "\\"mock source map\\"" }; @@ -3077,26 +3115,26 @@ const _worklet_16446448315454_init_data = { location: "/dev/null", sourceMap: "\\"mock source map\\"" }; -const _worklet_13974752356811_init_data = { - code: "function null3(){console.log('onBegin');}", +const _worklet_16462958026656_init_data = { + code: "function null3(_event,_success){console.log('onEnd');}", location: "/dev/null", sourceMap: "\\"mock source map\\"" }; -const foo = Gesture.Tap().numberOfTaps(2).onBegin(function null3Factory({ - _worklet_13974752356811_init_data +const foo = Gesture.Tap().numberOfTaps(2).onBegin(function null1Factory({ + _worklet_13539781966089_init_data }) { const _e = [new global.Error(), 1, -27]; - const null3 = function () { + const null1 = function () { console.log('onBegin'); }; - null3.__closure = {}; - null3.__workletHash = 13974752356811; - null3.__pluginVersion = "x.y.z"; - null3.__initData = _worklet_13974752356811_init_data; - null3.__stackDetails = _e; - return null3; + null1.__closure = {}; + null1.__workletHash = 13539781966089; + null1.__pluginVersion = "x.y.z"; + null1.__initData = _worklet_13539781966089_init_data; + null1.__stackDetails = _e; + return null1; }({ - _worklet_13974752356811_init_data + _worklet_13539781966089_init_data })).onStart(function null2Factory({ _worklet_16446448315454_init_data }) { @@ -3112,21 +3150,21 @@ const foo = Gesture.Tap().numberOfTaps(2).onBegin(function null3Factory({ return null2; }({ _worklet_16446448315454_init_data -})).onEnd(function null1Factory({ - _worklet_2359797567586_init_data +})).onEnd(function null3Factory({ + _worklet_16462958026656_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = function (_event, _success) { + const null3 = function (_event, _success) { console.log('onEnd'); }; - null1.__closure = {}; - null1.__workletHash = 2359797567586; - null1.__pluginVersion = "x.y.z"; - null1.__initData = _worklet_2359797567586_init_data; - null1.__stackDetails = _e; - return null1; + null3.__closure = {}; + null3.__workletHash = 16462958026656; + null3.__pluginVersion = "x.y.z"; + null3.__initData = _worklet_16462958026656_init_data; + null3.__stackDetails = _e; + return null3; }({ - _worklet_2359797567586_init_data + _worklet_16462958026656_init_data }));" `; @@ -3220,7 +3258,9 @@ styleFactory = function null1Factory({ _worklet_11678593259064_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => 'AssignmentExpression'; + const null1 = function () { + return 'AssignmentExpression'; + }; null1.__closure = {}; null1.__workletHash = 11678593259064; null1.__pluginVersion = "x.y.z"; @@ -3270,7 +3310,9 @@ styleFactory = function null1Factory({ _worklet_11855919716831_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({}); + const null1 = function () { + return {}; + }; null1.__closure = {}; null1.__workletHash = 11855919716831; null1.__pluginVersion = "x.y.z"; @@ -3293,7 +3335,9 @@ let styleFactory = function null1Factory({ _worklet_11855919716831_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({}); + const null1 = function () { + return {}; + }; null1.__closure = {}; null1.__workletHash = 11855919716831; null1.__pluginVersion = "x.y.z"; @@ -3318,7 +3362,9 @@ styleFactory = function null1Factory({ _worklet_11678593259064_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => 'AssignmentExpression'; + const null1 = function () { + return 'AssignmentExpression'; + }; null1.__closure = {}; null1.__workletHash = 11678593259064; null1.__pluginVersion = "x.y.z"; @@ -3502,7 +3548,9 @@ handler = { _worklet_11678593259064_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => 'AssignmentExpression'; + const null1 = function () { + return 'AssignmentExpression'; + }; null1.__closure = {}; null1.__workletHash = 11678593259064; null1.__pluginVersion = "x.y.z"; @@ -3552,7 +3600,9 @@ let styleFactory = function null1Factory({ _worklet_11855919716831_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({}); + const null1 = function () { + return {}; + }; null1.__closure = {}; null1.__workletHash = 11855919716831; null1.__pluginVersion = "x.y.z"; @@ -3576,7 +3626,9 @@ function outerScope() { _worklet_11855919716831_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({}); + const null1 = function () { + return {}; + }; null1.__closure = {}; null1.__workletHash = 11855919716831; null1.__pluginVersion = "x.y.z"; @@ -3602,7 +3654,9 @@ const secondReference = function null1Factory({ _worklet_11855919716831_init_data }) { const _e = [new global.Error(), 1, -27]; - const null1 = () => ({}); + const null1 = function () { + return {}; + }; null1.__closure = {}; null1.__workletHash = 11855919716831; null1.__pluginVersion = "x.y.z"; @@ -5279,82 +5333,88 @@ runOnUI(function null2Factory({ `; exports[`babel plugin for worklet nesting transpiles nested worklets embedded in runOnUI in runOnJS in runOnUI 1`] = ` -"const _worklet_7185083753711_init_data = { - code: "function null1(){const{runOnUI}=this.__closure;console.log('Hello from JS thread');runOnUI(function(){console.log('Hello from UI thread again');})();}", +"const _worklet_16631003901641_init_data = { + code: "function null1(){console.log('Hello from UI thread again');}", location: "/dev/null", sourceMap: "\\"mock source map\\"" }; -const _worklet_9142654516624_init_data = { - code: "function null2(){const{runOnJS,_worklet_7185083753711_init_data,runOnUI}=this.__closure;console.log('Hello from UI thread');runOnJS(function null1Factory({_worklet_7185083753711_init_data:_worklet_7185083753711_init_data,runOnUI:runOnUI}){const _e=[new global.Error(),-2,-27];const null1=function(){console.log('Hello from JS thread');runOnUI(function(){console.log('Hello from UI thread again');})();};null1.__closure={runOnUI:runOnUI};null1.__workletHash=7185083753711;null1.__pluginVersion=\\"x.y.z\\";null1.__initData=_worklet_7185083753711_init_data;null1.__stackDetails=_e;return null1;}({_worklet_7185083753711_init_data:_worklet_7185083753711_init_data,runOnUI:runOnUI}))();}", +const _worklet_1470601962314_init_data = { + code: "function null2(){const{runOnUI,_worklet_16631003901641_init_data}=this.__closure;console.log('Hello from JS thread');runOnUI(function null1Factory({_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}){const _e=[new global.Error(),1,-27];const null1=function(){console.log('Hello from UI thread again');};null1.__closure={};null1.__workletHash=16631003901641;null1.__pluginVersion=\\"x.y.z\\";null1.__initData=_worklet_16631003901641_init_data;null1.__stackDetails=_e;return null1;}({_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}))();}", location: "/dev/null", sourceMap: "\\"mock source map\\"" }; -const _worklet_2520605269387_init_data = { - code: "function null3(){console.log('Hello from UI thread again');}", +const _worklet_1411469776712_init_data = { + code: "function null3(){const{runOnJS,_worklet_1470601962314_init_data,runOnUI,_worklet_16631003901641_init_data}=this.__closure;console.log('Hello from UI thread');runOnJS(function null2Factory({_worklet_1470601962314_init_data:_worklet_1470601962314_init_data,runOnUI:runOnUI,_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}){const _e=[new global.Error(),-3,-27];const null2=function(){console.log('Hello from JS thread');runOnUI(function null1Factory({_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}){const _e=[new global.Error(),1,-27];const null1=function(){console.log('Hello from UI thread again');};null1.__closure={};null1.__workletHash=16631003901641;null1.__pluginVersion=\\"x.y.z\\";null1.__initData=_worklet_16631003901641_init_data;null1.__stackDetails=_e;return null1;}({_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}))();};null2.__closure={runOnUI:runOnUI,_worklet_16631003901641_init_data:_worklet_16631003901641_init_data};null2.__workletHash=1470601962314;null2.__pluginVersion=\\"x.y.z\\";null2.__initData=_worklet_1470601962314_init_data;null2.__stackDetails=_e;return null2;}({_worklet_1470601962314_init_data:_worklet_1470601962314_init_data,runOnUI:runOnUI,_worklet_16631003901641_init_data:_worklet_16631003901641_init_data}))();}", location: "/dev/null", sourceMap: "\\"mock source map\\"" }; -runOnUI(function null2Factory({ - _worklet_9142654516624_init_data, +runOnUI(function null3Factory({ + _worklet_1411469776712_init_data, runOnJS, - _worklet_7185083753711_init_data, - runOnUI + _worklet_1470601962314_init_data, + runOnUI, + _worklet_16631003901641_init_data }) { - const _e = [new global.Error(), -4, -27]; - const null2 = function () { + const _e = [new global.Error(), -5, -27]; + const null3 = function () { console.log('Hello from UI thread'); - runOnJS(function null1Factory({ - _worklet_7185083753711_init_data, - runOnUI + runOnJS(function null2Factory({ + _worklet_1470601962314_init_data, + runOnUI, + _worklet_16631003901641_init_data }) { - const _e = [new global.Error(), -2, -27]; - const null1 = function () { + const _e = [new global.Error(), -3, -27]; + const null2 = function () { console.log('Hello from JS thread'); - runOnUI(function null3Factory({ - _worklet_2520605269387_init_data + runOnUI(function null1Factory({ + _worklet_16631003901641_init_data }) { const _e = [new global.Error(), 1, -27]; - const null3 = function () { + const null1 = function () { console.log('Hello from UI thread again'); }; - null3.__closure = {}; - null3.__workletHash = 2520605269387; - null3.__pluginVersion = "x.y.z"; - null3.__initData = _worklet_2520605269387_init_data; - null3.__stackDetails = _e; - return null3; + null1.__closure = {}; + null1.__workletHash = 16631003901641; + null1.__pluginVersion = "x.y.z"; + null1.__initData = _worklet_16631003901641_init_data; + null1.__stackDetails = _e; + return null1; }({ - _worklet_2520605269387_init_data + _worklet_16631003901641_init_data }))(); }; - null1.__closure = { - runOnUI + null2.__closure = { + runOnUI, + _worklet_16631003901641_init_data }; - null1.__workletHash = 7185083753711; - null1.__pluginVersion = "x.y.z"; - null1.__initData = _worklet_7185083753711_init_data; - null1.__stackDetails = _e; - return null1; + null2.__workletHash = 1470601962314; + null2.__pluginVersion = "x.y.z"; + null2.__initData = _worklet_1470601962314_init_data; + null2.__stackDetails = _e; + return null2; }({ - _worklet_7185083753711_init_data, - runOnUI + _worklet_1470601962314_init_data, + runOnUI, + _worklet_16631003901641_init_data }))(); }; - null2.__closure = { + null3.__closure = { runOnJS, - _worklet_7185083753711_init_data, - runOnUI + _worklet_1470601962314_init_data, + runOnUI, + _worklet_16631003901641_init_data }; - null2.__workletHash = 9142654516624; - null2.__pluginVersion = "x.y.z"; - null2.__initData = _worklet_9142654516624_init_data; - null2.__stackDetails = _e; - return null2; + null3.__workletHash = 1411469776712; + null3.__pluginVersion = "x.y.z"; + null3.__initData = _worklet_1411469776712_init_data; + null3.__stackDetails = _e; + return null3; }({ - _worklet_9142654516624_init_data, + _worklet_1411469776712_init_data, runOnJS, - _worklet_7185083753711_init_data, - runOnUI + _worklet_1470601962314_init_data, + runOnUI, + _worklet_16631003901641_init_data }))();" `; diff --git a/packages/react-native-worklets/__tests__/plugin.test.ts b/packages/react-native-worklets/__tests__/plugin.test.ts index 868f29af34ac..6a88b8b26e0b 100644 --- a/packages/react-native-worklets/__tests__/plugin.test.ts +++ b/packages/react-native-worklets/__tests__/plugin.test.ts @@ -2781,4 +2781,22 @@ describe('babel plugin', () => { expect(code).toMatchSnapshot(); }); }); + + describe('for react-compiler', () => { + test('adds worklet directives to functions before react-compiler outlines them', () => { + const input = html``; + + const { code } = runPlugin(input, { + plugins: ['babel-plugin-react-compiler'], + }); + expect(code).toHaveWorkletData(1); + expect(code).toMatchSnapshot(); + }); + }); }); diff --git a/packages/react-native-worklets/plugin/index.js b/packages/react-native-worklets/plugin/index.js index 1eb7f4025505..47b4e00e911e 100644 --- a/packages/react-native-worklets/plugin/index.js +++ b/packages/react-native-worklets/plugin/index.js @@ -25,228 +25,33 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge mod )); -// lib/gestureHandlerAutoworkletization.js -var require_gestureHandlerAutoworkletization = __commonJS({ - "lib/gestureHandlerAutoworkletization.js"(exports2) { +// lib/contextObject.js +var require_contextObject = __commonJS({ + "lib/contextObject.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.gestureHandlerObjectHooks = exports2.gestureHandlerBuilderMethods = void 0; - exports2.isGestureHandlerEventCallback = isGestureHandlerEventCallback; - exports2.isGestureObjectEventCallbackMethod = isGestureObjectEventCallbackMethod; + exports2.contextObjectMarker = void 0; + exports2.processIfWorkletContextObject = processIfWorkletContextObject; + exports2.isContextObject = isContextObject; var types_12 = require("@babel/types"); - var gestureHandlerGestureObjects = /* @__PURE__ */ new Set([ - "Tap", - "Pan", - "Pinch", - "Rotation", - "Fling", - "LongPress", - "ForceTouch", - "Native", - "Manual", - "Race", - "Simultaneous", - "Exclusive", - "Hover" - ]); - exports2.gestureHandlerBuilderMethods = /* @__PURE__ */ new Set([ - "onBegin", - "onStart", - "onEnd", - "onFinalize", - "onUpdate", - "onChange", - "onTouchesDown", - "onTouchesMove", - "onTouchesUp", - "onTouchesCancelled" - ]); - exports2.gestureHandlerObjectHooks = /* @__PURE__ */ new Set([ - "useTapGesture", - "usePanGesture", - "usePinchGesture", - "useRotationGesture", - "useFlingGesture", - "useLongPressGesture", - "useNativeGesture", - "useManualGesture", - "useHoverGesture" - ]); - function isGestureHandlerEventCallback(path) { - return (0, types_12.isCallExpression)(path.parent) && (0, types_12.isExpression)(path.parent.callee) && isGestureObjectEventCallbackMethod(path.parent.callee); - } - function isGestureObjectEventCallbackMethod(exp) { - return (0, types_12.isMemberExpression)(exp) && (0, types_12.isIdentifier)(exp.property) && exports2.gestureHandlerBuilderMethods.has(exp.property.name) && containsGestureObject(exp.object); - } - function containsGestureObject(exp) { - if (isGestureObject(exp)) { - return true; - } - if ((0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && containsGestureObject(exp.callee.object)) { - return true; + exports2.contextObjectMarker = "__workletContextObject"; + function processIfWorkletContextObject(path, _state) { + if (!isContextObject(path.node)) { + return false; } - return false; - } - function isGestureObject(exp) { - return (0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && (0, types_12.isIdentifier)(exp.callee.object) && exp.callee.object.name === "Gesture" && (0, types_12.isIdentifier)(exp.callee.property) && gestureHandlerGestureObjects.has(exp.callee.property.name); + removeContextObjectMarker(path.node); + processWorkletContextObject(path.node); + return true; } - } -}); - -// lib/layoutAnimationAutoworkletization.js -var require_layoutAnimationAutoworkletization = __commonJS({ - "lib/layoutAnimationAutoworkletization.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.isLayoutAnimationCallback = isLayoutAnimationCallback; - var types_12 = require("@babel/types"); - var EntryExitAnimations = /* @__PURE__ */ new Set([ - "BounceIn", - "BounceInDown", - "BounceInLeft", - "BounceInRight", - "BounceInUp", - "BounceOut", - "BounceOutDown", - "BounceOutLeft", - "BounceOutRight", - "BounceOutUp", - "FadeIn", - "FadeInDown", - "FadeInLeft", - "FadeInRight", - "FadeInUp", - "FadeOut", - "FadeOutDown", - "FadeOutLeft", - "FadeOutRight", - "FadeOutUp", - "FlipInEasyX", - "FlipInEasyY", - "FlipInXDown", - "FlipInXUp", - "FlipInYLeft", - "FlipInYRight", - "FlipOutEasyX", - "FlipOutEasyY", - "FlipOutXDown", - "FlipOutXUp", - "FlipOutYLeft", - "FlipOutYRight", - "LightSpeedInLeft", - "LightSpeedInRight", - "LightSpeedOutLeft", - "LightSpeedOutRight", - "PinwheelIn", - "PinwheelOut", - "RollInLeft", - "RollInRight", - "RollOutLeft", - "RollOutRight", - "RotateInDownLeft", - "RotateInDownRight", - "RotateInUpLeft", - "RotateInUpRight", - "RotateOutDownLeft", - "RotateOutDownRight", - "RotateOutUpLeft", - "RotateOutUpRight", - "SlideInDown", - "SlideInLeft", - "SlideInRight", - "SlideInUp", - "SlideOutDown", - "SlideOutLeft", - "SlideOutRight", - "SlideOutUp", - "StretchInX", - "StretchInY", - "StretchOutX", - "StretchOutY", - "ZoomIn", - "ZoomInDown", - "ZoomInEasyDown", - "ZoomInEasyUp", - "ZoomInLeft", - "ZoomInRight", - "ZoomInRotate", - "ZoomInUp", - "ZoomOut", - "ZoomOutDown", - "ZoomOutEasyDown", - "ZoomOutEasyUp", - "ZoomOutLeft", - "ZoomOutRight", - "ZoomOutRotate", - "ZoomOutUp" - ]); - var LayoutTransitions = /* @__PURE__ */ new Set([ - "Layout", - "LinearTransition", - "SequencedTransition", - "FadingTransition", - "JumpingTransition", - "CurvedTransition", - "EntryExitTransition" - ]); - var LayoutAnimations = /* @__PURE__ */ new Set([ - ...EntryExitAnimations, - ...LayoutTransitions - ]); - var BaseAnimationsChainableMethods = /* @__PURE__ */ new Set([ - "build", - "duration", - "delay", - "getDuration", - "randomDelay", - "getDelay", - "getDelayFunction" - ]); - var ComplexAnimationsChainableMethods = /* @__PURE__ */ new Set([ - "easing", - "rotate", - "springify", - "damping", - "mass", - "stiffness", - "overshootClamping", - "energyThreshold", - "restDisplacementThreshold", - "restSpeedThreshold", - "withInitialValues", - "getAnimationAndConfig" - ]); - var DefaultTransitionChainableMethods = /* @__PURE__ */ new Set([ - "easingX", - "easingY", - "easingWidth", - "easingHeight", - "entering", - "exiting", - "reverse" - ]); - var LayoutAnimationsChainableMethods = /* @__PURE__ */ new Set([ - ...BaseAnimationsChainableMethods, - ...ComplexAnimationsChainableMethods, - ...DefaultTransitionChainableMethods - ]); - var LayoutAnimationsCallbacks = /* @__PURE__ */ new Set(["withCallback"]); - function isLayoutAnimationCallback(path) { - return (0, types_12.isCallExpression)(path.parent) && (0, types_12.isExpression)(path.parent.callee) && isLayoutAnimationCallbackMethod(path.parent.callee); + function isContextObject(objectExpression) { + return objectExpression.properties.some((property) => (0, types_12.isObjectProperty)(property) && (0, types_12.isIdentifier)(property.key) && property.key.name === exports2.contextObjectMarker); } - function isLayoutAnimationCallbackMethod(exp) { - return (0, types_12.isMemberExpression)(exp) && (0, types_12.isIdentifier)(exp.property) && LayoutAnimationsCallbacks.has(exp.property.name) && isLayoutAnimationsChainableOrNewOperator(exp.object); + function processWorkletContextObject(objectExpression) { + const workletObjectFactory = (0, types_12.functionExpression)(null, [], (0, types_12.blockStatement)([(0, types_12.returnStatement)((0, types_12.cloneNode)(objectExpression))], [(0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))])); + objectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)(`${exports2.contextObjectMarker}Factory`), workletObjectFactory)); } - function isLayoutAnimationsChainableOrNewOperator(exp) { - if ((0, types_12.isIdentifier)(exp) && LayoutAnimations.has(exp.name)) { - return true; - } else if ((0, types_12.isNewExpression)(exp) && (0, types_12.isIdentifier)(exp.callee) && LayoutAnimations.has(exp.callee.name)) { - return true; - } - if ((0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && (0, types_12.isIdentifier)(exp.callee.property) && LayoutAnimationsChainableMethods.has(exp.callee.property.name) && isLayoutAnimationsChainableOrNewOperator(exp.callee.object)) { - return true; - } - return false; + function removeContextObjectMarker(objectExpression) { + objectExpression.properties = objectExpression.properties.filter((property) => !((0, types_12.isObjectProperty)(property) && (0, types_12.isIdentifier)(property.key) && property.key.name === exports2.contextObjectMarker)); } } }); @@ -281,23 +86,162 @@ var require_types = __commonJS({ } }); -// lib/referencedWorklets.js -var require_referencedWorklets = __commonJS({ - "lib/referencedWorklets.js"(exports2) { +// lib/file.js +var require_file = __commonJS({ + "lib/file.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.findReferencedWorklet = findReferencedWorklet; + exports2.processIfWorkletFile = processIfWorkletFile; + exports2.replaceImplicitReturnWithBlock = replaceImplicitReturnWithBlock; + exports2.appendWorkletDirective = appendWorkletDirective; + exports2.isImplicitContextObject = isImplicitContextObject; var types_12 = require("@babel/types"); + var contextObject_12 = require_contextObject(); var types_2 = require_types(); - function findReferencedWorklet(workletIdentifier, acceptWorkletizableFunction, acceptObject, state) { - const workletName = workletIdentifier.node.name; - const scope = workletIdentifier.scope; - const workletBinding = scope.getBinding(workletName); - if (!workletBinding) { - return void 0; + function processIfWorkletFile(path, state) { + if (!path.node.directives.some((functionDirective) => functionDirective.value.value === "worklet")) { + return false; } - if (state.opts.bundleMode && bindingIsWorklet(workletBinding)) { - return void 0; + path.node.directives = path.node.directives.filter((functionDirective) => functionDirective.value.value !== "worklet"); + processWorkletFile(path, state); + return true; + } + function processWorkletFile(programPath, state) { + const statements = programPath.get("body"); + dehoistCommonJSExports(programPath.node); + statements.forEach((statement) => { + const candidatePath = getCandidate(statement); + processWorkletizableEntity(candidatePath, state); + }); + } + function getCandidate(statementPath) { + if (statementPath.isExportNamedDeclaration() || statementPath.isExportDefaultDeclaration()) { + return statementPath.get("declaration"); + } else { + return statementPath; + } + } + function processWorkletizableEntity(nodePath, state) { + var _a; + if ((0, types_2.isWorkletizableFunctionPath)(nodePath)) { + if (nodePath.isArrowFunctionExpression()) { + replaceImplicitReturnWithBlock(nodePath.node); + } + appendWorkletDirective(nodePath.node.body); + } else if ((0, types_2.isWorkletizableObjectPath)(nodePath)) { + if (isImplicitContextObject(nodePath)) { + appendWorkletContextObjectMarker(nodePath.node); + } else { + processWorkletAggregator(nodePath, state); + } + } else if (nodePath.isVariableDeclaration()) { + processVariableDeclaration(nodePath, state); + } else if (nodePath.isClassDeclaration()) { + appendWorkletClassMarker(nodePath.node.body); + if ((_a = nodePath.node.id) === null || _a === void 0 ? void 0 : _a.name) { + state.classesToWorkletize.push({ + node: nodePath.node, + name: nodePath.node.id.name + }); + } + } + } + function processVariableDeclaration(variableDeclarationPath, state) { + const declarations = variableDeclarationPath.get("declarations"); + declarations.forEach((declaration) => { + const initPath = declaration.get("init"); + if (initPath.isExpression()) { + processWorkletizableEntity(initPath, state); + } + }); + } + function processWorkletAggregator(objectPath, state) { + const properties = objectPath.get("properties"); + properties.forEach((property) => { + if (property.isObjectMethod()) { + appendWorkletDirective(property.node.body); + } else if (property.isObjectProperty()) { + const valuePath = property.get("value"); + processWorkletizableEntity(valuePath, state); + } + }); + } + function replaceImplicitReturnWithBlock(path) { + if (!(0, types_12.isBlockStatement)(path.body)) { + path.body = (0, types_12.blockStatement)([(0, types_12.returnStatement)(path.body)]); + } + } + function appendWorkletDirective(node) { + if (!node.directives.some((functionDirective) => functionDirective.value.value === "worklet")) { + node.directives.push((0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))); + } + } + function appendWorkletContextObjectMarker(objectExpression) { + if (objectExpression.properties.some((value) => (0, types_12.isObjectProperty)(value) && (0, types_12.isIdentifier)(value.key) && value.key.name === contextObject_12.contextObjectMarker)) { + return; + } + objectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)(`${contextObject_12.contextObjectMarker}`), (0, types_12.booleanLiteral)(true))); + } + function isImplicitContextObject(path) { + const propertyPaths = path.get("properties"); + return propertyPaths.some((propertyPath) => { + if (!propertyPath.isObjectMethod()) { + return false; + } + return hasThisExpression(propertyPath); + }); + } + function hasThisExpression(path) { + let result = false; + path.traverse({ + ThisExpression(thisPath) { + result = true; + thisPath.stop(); + } + }); + return result; + } + function appendWorkletClassMarker(classBody) { + classBody.body.push((0, types_12.classProperty)((0, types_12.identifier)("__workletClass"), (0, types_12.booleanLiteral)(true))); + } + function dehoistCommonJSExports(program) { + const statements = program.body; + let end = statements.length; + let current = 0; + while (current < end) { + const statement = statements[current]; + if (!isCommonJSExport(statement)) { + current++; + continue; + } + const exportStatement = statements.splice(current, 1); + statements.push(...exportStatement); + end--; + } + } + function isCommonJSExport(statement) { + return (0, types_12.isExpressionStatement)(statement) && (0, types_12.isAssignmentExpression)(statement.expression) && (0, types_12.isMemberExpression)(statement.expression.left) && (0, types_12.isIdentifier)(statement.expression.left.object) && statement.expression.left.object.name === "exports"; + } + } +}); + +// lib/referencedWorklets.js +var require_referencedWorklets = __commonJS({ + "lib/referencedWorklets.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.findReferencedWorklet = findReferencedWorklet; + var types_12 = require("@babel/types"); + var types_2 = require_types(); + function findReferencedWorklet(workletIdentifier, acceptWorkletizableFunction, acceptObject, state) { + const workletName = workletIdentifier.node.name; + const scope = workletIdentifier.scope; + const workletBinding = scope.getBinding(workletName); + if (!workletBinding) { + return void 0; + } + if (state.opts.bundleMode && bindingIsWorklet(workletBinding)) { + return void 0; } if (acceptWorkletizableFunction && workletBinding.path.isFunctionDeclaration()) { return workletBinding.path; @@ -372,325 +316,395 @@ var require_findWorklet = __commonJS({ } }); -// lib/utils.js -var require_utils = __commonJS({ - "lib/utils.js"(exports2) { +// lib/gestureHandlerAutoworkletization.js +var require_gestureHandlerAutoworkletization = __commonJS({ + "lib/gestureHandlerAutoworkletization.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.isRelease = isRelease; - exports2.replaceWithFactoryCall = replaceWithFactoryCall; + exports2.gestureHandlerObjectHooks = exports2.gestureHandlerBuilderMethods = void 0; + exports2.isGestureHandlerEventCallback = isGestureHandlerEventCallback; + exports2.isGestureObjectEventCallbackMethod = isGestureObjectEventCallbackMethod; var types_12 = require("@babel/types"); - function isRelease() { - var _a, _b; - const pattern = /(prod|release|stag[ei])/i; - return !!(((_a = process.env.BABEL_ENV) === null || _a === void 0 ? void 0 : _a.match(pattern)) || ((_b = process.env.NODE_ENV) === null || _b === void 0 ? void 0 : _b.match(pattern))); + var gestureHandlerGestureObjects = /* @__PURE__ */ new Set([ + "Tap", + "Pan", + "Pinch", + "Rotation", + "Fling", + "LongPress", + "ForceTouch", + "Native", + "Manual", + "Race", + "Simultaneous", + "Exclusive", + "Hover" + ]); + exports2.gestureHandlerBuilderMethods = /* @__PURE__ */ new Set([ + "onBegin", + "onStart", + "onEnd", + "onFinalize", + "onUpdate", + "onChange", + "onTouchesDown", + "onTouchesMove", + "onTouchesUp", + "onTouchesCancelled" + ]); + exports2.gestureHandlerObjectHooks = /* @__PURE__ */ new Set([ + "useTapGesture", + "usePanGesture", + "usePinchGesture", + "useRotationGesture", + "useFlingGesture", + "useLongPressGesture", + "useNativeGesture", + "useManualGesture", + "useHoverGesture" + ]); + function isGestureHandlerEventCallback(path) { + return (0, types_12.isCallExpression)(path.parent) && (0, types_12.isExpression)(path.parent.callee) && isGestureObjectEventCallbackMethod(path.parent.callee); } - function replaceWithFactoryCall(toReplace, name, factoryCall) { - if (!name || !needsDeclaration(toReplace)) { - toReplace.replaceWith(factoryCall); - } else { - const replacement = (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(name), factoryCall) - ]); - toReplace.replaceWith(replacement); + function isGestureObjectEventCallbackMethod(exp) { + return (0, types_12.isMemberExpression)(exp) && (0, types_12.isIdentifier)(exp.property) && exports2.gestureHandlerBuilderMethods.has(exp.property.name) && containsGestureObject(exp.object); + } + function containsGestureObject(exp) { + if (isGestureObject(exp)) { + return true; + } + if ((0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && containsGestureObject(exp.callee.object)) { + return true; } + return false; } - function needsDeclaration(nodePath) { - return (0, types_12.isScopable)(nodePath.parent) || (0, types_12.isExportNamedDeclaration)(nodePath.parent); + function isGestureObject(exp) { + return (0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && (0, types_12.isIdentifier)(exp.callee.object) && exp.callee.object.name === "Gesture" && (0, types_12.isIdentifier)(exp.callee.property) && gestureHandlerGestureObjects.has(exp.callee.property.name); } } }); -// lib/globals.js -var require_globals = __commonJS({ - "lib/globals.js"(exports2) { +// lib/layoutAnimationAutoworkletization.js +var require_layoutAnimationAutoworkletization = __commonJS({ + "lib/layoutAnimationAutoworkletization.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.globals = exports2.defaultGlobals = exports2.internalBindingsToCaptureFromGlobalScope = exports2.outsideBindingsToCaptureFromGlobalScope = void 0; - exports2.initializeState = initializeState; - exports2.initializeGlobals = initializeGlobals; - exports2.addCustomGlobals = addCustomGlobals; - var notCapturedIdentifiers = [ - // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects - // Note that objects' properties don't need to be listed since we always only capture the whole object, - // e.g. `global.__ErrorUtils` or `Intl.DateTimeFormat`. - // Value properties - "globalThis", - "Infinity", - "NaN", - "undefined", - // Function properties - "eval", - "isFinite", - "isNaN", - "parseFloat", - "parseInt", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "unescape", - // Fundamental objects - "Object", - "Function", - "Boolean", - "Symbol", - // Error objects - "Error", - "AggregateError", - "EvalError", - "RangeError", - "ReferenceError", - "SyntaxError", - "TypeError", - "URIError", - "InternalError", - // Numbers and dates - "Number", - "BigInt", - "Math", - "Date", - // Text processing - "String", - "RegExp", - // Indexed collections - "Array", - "Int8Array", - "Uint8Array", - "Uint8ClampedArray", - "Int16Array", - "Uint16Array", - "Int32Array", - "Uint32Array", - "BigInt64Array", - "BigUint64Array", - "Float32Array", - "Float64Array", - // Keyed collections - "Map", - "Set", - "WeakMap", - "WeakSet", - // Structured data - "ArrayBuffer", - "SharedArrayBuffer", - "DataView", - "Atomics", - "JSON", - // Managing memory - "WeakRef", - "FinalizationRegistry", - // Control abstraction objects - "Iterator", - "AsyncIterator", - "Promise", - "GeneratorFunction", - "AsyncGeneratorFunction", - "Generator", - "AsyncGenerator", - "AsyncFunction", - // Reflection - "Reflect", - "Proxy", - // Internationalization - "Intl", - // Other stuff - "null", - "this", - "global", - "window", - "globalThis", - "self", - "console", - "performance", - "arguments", - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments - "require", - "fetch", - "XMLHttpRequest", - "WebSocket", - // Run loop - "queueMicrotask", - "requestAnimationFrame", - "cancelAnimationFrame", - "setTimeout", - "clearTimeout", - "setImmediate", - "clearImmediate", - "setInterval", - "clearInterval", - // Hermes - "HermesInternal", - // Worklets - "_WORKLET" - ]; - exports2.outsideBindingsToCaptureFromGlobalScope = /* @__PURE__ */ new Set([ - "ReanimatedError" + exports2.isLayoutAnimationCallback = isLayoutAnimationCallback; + var types_12 = require("@babel/types"); + var EntryExitAnimations = /* @__PURE__ */ new Set([ + "BounceIn", + "BounceInDown", + "BounceInLeft", + "BounceInRight", + "BounceInUp", + "BounceOut", + "BounceOutDown", + "BounceOutLeft", + "BounceOutRight", + "BounceOutUp", + "FadeIn", + "FadeInDown", + "FadeInLeft", + "FadeInRight", + "FadeInUp", + "FadeOut", + "FadeOutDown", + "FadeOutLeft", + "FadeOutRight", + "FadeOutUp", + "FlipInEasyX", + "FlipInEasyY", + "FlipInXDown", + "FlipInXUp", + "FlipInYLeft", + "FlipInYRight", + "FlipOutEasyX", + "FlipOutEasyY", + "FlipOutXDown", + "FlipOutXUp", + "FlipOutYLeft", + "FlipOutYRight", + "LightSpeedInLeft", + "LightSpeedInRight", + "LightSpeedOutLeft", + "LightSpeedOutRight", + "PinwheelIn", + "PinwheelOut", + "RollInLeft", + "RollInRight", + "RollOutLeft", + "RollOutRight", + "RotateInDownLeft", + "RotateInDownRight", + "RotateInUpLeft", + "RotateInUpRight", + "RotateOutDownLeft", + "RotateOutDownRight", + "RotateOutUpLeft", + "RotateOutUpRight", + "SlideInDown", + "SlideInLeft", + "SlideInRight", + "SlideInUp", + "SlideOutDown", + "SlideOutLeft", + "SlideOutRight", + "SlideOutUp", + "StretchInX", + "StretchInY", + "StretchOutX", + "StretchOutY", + "ZoomIn", + "ZoomInDown", + "ZoomInEasyDown", + "ZoomInEasyUp", + "ZoomInLeft", + "ZoomInRight", + "ZoomInRotate", + "ZoomInUp", + "ZoomOut", + "ZoomOutDown", + "ZoomOutEasyDown", + "ZoomOutEasyUp", + "ZoomOutLeft", + "ZoomOutRight", + "ZoomOutRotate", + "ZoomOutUp" ]); - exports2.internalBindingsToCaptureFromGlobalScope = /* @__PURE__ */ new Set([ - "WorkletsError" + var LayoutTransitions = /* @__PURE__ */ new Set([ + "Layout", + "LinearTransition", + "SequencedTransition", + "FadingTransition", + "JumpingTransition", + "CurvedTransition", + "EntryExitTransition" ]); - var notCapturedIdentifiers_DEPRECATED = ["_IS_FABRIC"]; - function initializeState(state) { - state.workletNumber = 1; - state.classesToWorkletize = []; - if (!state.opts.strictGlobal) { - initializeGlobals(); - addCustomGlobals(state); - } + var LayoutAnimations = /* @__PURE__ */ new Set([ + ...EntryExitAnimations, + ...LayoutTransitions + ]); + var BaseAnimationsChainableMethods = /* @__PURE__ */ new Set([ + "build", + "duration", + "delay", + "getDuration", + "randomDelay", + "getDelay", + "getDelayFunction" + ]); + var ComplexAnimationsChainableMethods = /* @__PURE__ */ new Set([ + "easing", + "rotate", + "springify", + "damping", + "mass", + "stiffness", + "overshootClamping", + "energyThreshold", + "restDisplacementThreshold", + "restSpeedThreshold", + "withInitialValues", + "getAnimationAndConfig" + ]); + var DefaultTransitionChainableMethods = /* @__PURE__ */ new Set([ + "easingX", + "easingY", + "easingWidth", + "easingHeight", + "entering", + "exiting", + "reverse" + ]); + var LayoutAnimationsChainableMethods = /* @__PURE__ */ new Set([ + ...BaseAnimationsChainableMethods, + ...ComplexAnimationsChainableMethods, + ...DefaultTransitionChainableMethods + ]); + var LayoutAnimationsCallbacks = /* @__PURE__ */ new Set(["withCallback"]); + function isLayoutAnimationCallback(path) { + return (0, types_12.isCallExpression)(path.parent) && (0, types_12.isExpression)(path.parent.callee) && isLayoutAnimationCallbackMethod(path.parent.callee); } - exports2.defaultGlobals = new Set(notCapturedIdentifiers.concat(notCapturedIdentifiers_DEPRECATED)); - function initializeGlobals() { - exports2.globals = new Set(exports2.defaultGlobals); + function isLayoutAnimationCallbackMethod(exp) { + return (0, types_12.isMemberExpression)(exp) && (0, types_12.isIdentifier)(exp.property) && LayoutAnimationsCallbacks.has(exp.property.name) && isLayoutAnimationsChainableOrNewOperator(exp.object); } - function addCustomGlobals(state) { - if (state.opts && Array.isArray(state.opts.globals)) { - state.opts.globals.forEach((name) => { - exports2.globals.add(name); - }); + function isLayoutAnimationsChainableOrNewOperator(exp) { + if ((0, types_12.isIdentifier)(exp) && LayoutAnimations.has(exp.name)) { + return true; + } else if ((0, types_12.isNewExpression)(exp) && (0, types_12.isIdentifier)(exp.callee) && LayoutAnimations.has(exp.callee.name)) { + return true; + } + if ((0, types_12.isCallExpression)(exp) && (0, types_12.isMemberExpression)(exp.callee) && (0, types_12.isIdentifier)(exp.callee.property) && LayoutAnimationsChainableMethods.has(exp.callee.property.name) && isLayoutAnimationsChainableOrNewOperator(exp.callee.object)) { + return true; } + return false; } } }); -// lib/closure.js -var require_closure = __commonJS({ - "lib/closure.js"(exports2) { +// lib/autoworkletization.js +var require_autoworkletization = __commonJS({ + "lib/autoworkletization.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.getClosure = getClosure; + exports2.addWorkletDirectiveToKnownCallback = addWorkletDirectiveToKnownCallback; + exports2.addWorkletDirectivesToCallbacks = addWorkletDirectivesToCallbacks; var types_12 = require("@babel/types"); - var globals_12 = require_globals(); - function getClosure(funPath, state) { - const capturedNames = /* @__PURE__ */ new Set(); - const closureVariables = new Array(); - const libraryBindingsToImport = /* @__PURE__ */ new Set(); - const relativeBindingsToImport = /* @__PURE__ */ new Set(); - let recrawled = false; - funPath.traverse({ - "TSType|TSTypeAliasDeclaration|TSInterfaceDeclaration"(typePath) { - typePath.skip(); - }, - ReferencedIdentifier(idPath) { - if (idPath.isJSXIdentifier()) { - return; - } - const name = idPath.node.name; - if (capturedNames.has(name)) { - return; - } - let binding = idPath.scope.getBinding(name); - if (!binding && !recrawled) { - recrawled = true; - idPath.scope.crawl(); - binding = idPath.scope.getBinding(name); - } - if (!binding) { - if (state.opts.strictGlobal || globals_12.globals.has(name)) { - return; - } - capturedNames.add(name); - closureVariables.push((0, types_12.cloneNode)(idPath.node, true)); - return; - } - if (globals_12.outsideBindingsToCaptureFromGlobalScope.has(name) || !state.opts.bundleMode && globals_12.internalBindingsToCaptureFromGlobalScope.has(name)) { - return; - } - if ("id" in funPath.node) { - const id = idPath.scope.getBindingIdentifier(name); - if (id && id === funPath.node.id) { - return; - } - } - let scope = idPath.scope; - while (scope !== funPath.scope.parent) { - if (scope.hasOwnBinding(name)) { - return; - } - scope = scope.parent; - } - if (state.opts.bundleMode && isImport(binding)) { - if (isImportRelative(binding) && isAllowedForRelativeImports(state.filename, state.opts.workletizableModules)) { - capturedNames.add(name); - relativeBindingsToImport.add(binding); - return; - } - const source = binding.path.parentPath.node.source.value; - if (isWorkletizableModule(source, state.opts.workletizableModules)) { - capturedNames.add(name); - libraryBindingsToImport.add(binding); - return; - } - } - capturedNames.add(name); - closureVariables.push((0, types_12.cloneNode)(idPath.node, true)); - } - }, state); - return { - closureVariables, - libraryBindingsToImport, - relativeBindingsToImport - }; + var file_12 = require_file(); + var findWorklet_1 = require_findWorklet(); + var gestureHandlerAutoworkletization_1 = require_gestureHandlerAutoworkletization(); + var layoutAnimationAutoworkletization_1 = require_layoutAnimationAutoworkletization(); + var types_2 = require_types(); + var reanimatedObjectHooks = /* @__PURE__ */ new Set([ + "useAnimatedScrollHandler", + ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerObjectHooks) + ]); + var reanimatedFunctionHooks = /* @__PURE__ */ new Set([ + "useFrameCallback", + "useAnimatedStyle", + "useAnimatedProps", + "createAnimatedPropAdapter", + "useDerivedValue", + "useAnimatedScrollHandler", + "useAnimatedReaction", + // animations' callbacks + "withTiming", + "withSpring", + "withDecay", + "withRepeat", + // scheduling functions + "runOnUI", + "executeOnUIRuntimeSync", + "scheduleOnUI", + "runOnUISync", + "runOnUIAsync", + "runOnRuntime", + "runOnRuntimeSync", + "runOnRuntimeAsync", + "scheduleOnRuntime", + "runOnRuntimeSyncWithId", + "scheduleOnRuntimeWithId" + ]); + var reanimatedFunctionArgsToWorkletize = new Map([ + ["useFrameCallback", [0]], + ["useAnimatedStyle", [0]], + ["useAnimatedProps", [0]], + ["createAnimatedPropAdapter", [0]], + ["useDerivedValue", [0]], + ["useAnimatedScrollHandler", [0]], + ["useAnimatedReaction", [0, 1]], + ["withTiming", [2]], + ["withSpring", [2]], + ["withDecay", [1]], + ["withRepeat", [3]], + ["runOnUI", [0]], + ["executeOnUIRuntimeSync", [0]], + ["scheduleOnUI", [0]], + ["runOnUISync", [0]], + ["runOnUIAsync", [0]], + ["runOnRuntime", [1]], + ["runOnRuntimeSync", [1]], + ["runOnRuntimeAsync", [1]], + ["scheduleOnRuntime", [1]], + ["runOnRuntimeSyncWithId", [1]], + ["scheduleOnRuntimeWithId", [1]], + ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerObjectHooks).map((name) => [name, [0]]), + ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerBuilderMethods).map((name) => [name, [0]]) + ]); + function addWorkletDirectiveToKnownCallback(path) { + if ((0, gestureHandlerAutoworkletization_1.isGestureHandlerEventCallback)(path) || (0, layoutAnimationAutoworkletization_1.isLayoutAnimationCallback)(path)) { + addWorkletDirective(path); + } } - function isImport(binding) { - return binding.kind === "module" && binding.constant && (binding.path.isImportSpecifier() || binding.path.isImportDefaultSpecifier()) && binding.path.parentPath.isImportDeclaration(); + function addWorkletDirectivesToCallbacks(path, state) { + const callee = (0, types_12.isSequenceExpression)(path.node.callee) ? path.node.callee.expressions[path.node.callee.expressions.length - 1] : path.node.callee; + const name = "name" in callee ? callee.name : "property" in callee && "name" in callee.property ? callee.property.name : void 0; + if (name === void 0) { + return; + } + if (reanimatedFunctionHooks.has(name) || reanimatedObjectHooks.has(name)) { + const acceptWorkletizableFunction = reanimatedFunctionHooks.has(name); + const acceptObject = reanimatedObjectHooks.has(name); + const argIndices = reanimatedFunctionArgsToWorkletize.get(name); + const args = path.get("arguments").filter((_, index) => argIndices.includes(index)); + addWorkletDirectiveToArgs(args, state, acceptWorkletizableFunction, acceptObject); + } else if (!(0, types_12.isV8IntrinsicIdentifier)(callee) && (0, gestureHandlerAutoworkletization_1.isGestureObjectEventCallbackMethod)(callee)) { + const args = path.get("arguments"); + addWorkletDirectiveToArgs(args, state, true, true); + } } - function isImportRelative(imported) { - return imported.path.parentPath.node.source.value.startsWith("."); + function addWorkletDirectiveToArgs(args, state, acceptWorkletizableFunction, acceptObject) { + args.forEach((arg) => { + addWorkletDirectiveToNode(arg, state, acceptWorkletizableFunction, acceptObject); + }); } - function isAllowedForRelativeImports(filename, workletizableModules) { - return !!filename && (alwaysAllowed.some((module3) => filename.includes(module3)) || !!(workletizableModules === null || workletizableModules === void 0 ? void 0 : workletizableModules.some((module3) => filename.includes(module3)))); + function addWorkletDirectiveToNode(arg, state, acceptWorkletizableFunction, acceptObject) { + const maybeWorklet = (0, findWorklet_1.findWorklet)(arg, state, acceptWorkletizableFunction, acceptObject); + if (!maybeWorklet) { + return; + } + if ((0, types_2.isWorkletizableFunctionPath)(maybeWorklet)) { + addWorkletDirective(maybeWorklet); + } else if ((0, types_2.isWorkletizableObjectPath)(maybeWorklet)) { + addWorkletDirectiveToMethods(maybeWorklet, state); + } } - function isWorkletizableModule(source, workletizableModules) { - return alwaysAllowed.some((module3) => source.startsWith(module3)) || !!(workletizableModules === null || workletizableModules === void 0 ? void 0 : workletizableModules.some((module3) => source.startsWith(module3))); + function addWorkletDirectiveToMethods(path, state) { + const properties = path.get("properties"); + for (const property of properties) { + if (property.isObjectMethod()) { + addWorkletDirective(property); + } else if (property.isObjectProperty()) { + const value = property.get("value"); + addWorkletDirectiveToNode( + value, + state, + true, + // acceptWorkletizableFunction + false + // acceptObject + ); + } else { + throw new Error(`[Reanimated] '${property.type}' as to-be workletized argument is not supported for object hooks.`); + } + } + } + function addWorkletDirective(path) { + if (path.isArrowFunctionExpression()) { + (0, file_12.replaceImplicitReturnWithBlock)(path.node); + } + (0, file_12.appendWorkletDirective)(path.node.body); } - var alwaysAllowed = [ - "react-native-worklets", - "react-native/Libraries/Core/setUpXHR" - // for networking - ]; } }); -// lib/generate.js -var require_generate = __commonJS({ - "lib/generate.js"(exports2) { +// lib/bundleMode.js +var require_bundleMode = __commonJS({ + "lib/bundleMode.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.generateWorkletFile = generateWorkletFile; - var core_1 = require("@babel/core"); + exports2.toggleBundleMode = toggleBundleMode; var types_12 = require("@babel/types"); - var assert_1 = __importDefault(require("assert")); - var fs_1 = require("fs"); - var path_1 = require("path"); - var types_2 = require_types(); - function generateWorkletFile(libraryBindingsToImport, relativeBindingsToImport, factory, workletHash, state) { + function toggleBundleMode(path, state) { var _a; - const libraryImports = Array.from(libraryBindingsToImport).filter((binding) => (binding.path.isImportSpecifier() || binding.path.isImportDefaultSpecifier()) && binding.path.parentPath.isImportDeclaration()).map((binding) => (0, types_12.importDeclaration)([(0, types_12.cloneNode)(binding.path.node, true)], (0, types_12.stringLiteral)(binding.path.parentPath.node.source.value))); - const filesDirPath = (0, path_1.resolve)((0, path_1.dirname)(require.resolve("react-native-worklets/package.json")), types_2.generatedWorkletsDir); - const relativeImports = Array.from(relativeBindingsToImport).filter((binding) => binding.path.isImportSpecifier() && binding.path.parentPath.isImportDeclaration()).map((binding) => { - const resolved = (0, path_1.resolve)((0, path_1.dirname)(state.file.opts.filename), binding.path.parentPath.node.source.value); - const importPath = (0, path_1.relative)(filesDirPath, resolved); - return (0, types_12.importDeclaration)([(0, types_12.cloneNode)(binding.path.node, true)], (0, types_12.stringLiteral)(importPath)); - }); - const imports = [...libraryImports, ...relativeImports]; - const newProg = (0, types_12.program)([...imports, (0, types_12.exportDefaultDeclaration)(factory)]); - const transformedProg = (_a = (0, core_1.transformFromAstSync)(newProg, void 0, { - filename: state.file.opts.filename, - presets: ["@babel/preset-typescript"], - plugins: [], - ast: false, - babelrc: false, - configFile: false, - comments: false - })) === null || _a === void 0 ? void 0 : _a.code; - (0, assert_1.default)(transformedProg, "[Worklets] `transformedProg` is undefined."); - const dedicatedFilePath = (0, path_1.resolve)(filesDirPath, `${workletHash}.js`); - (0, fs_1.writeFileSync)(dedicatedFilePath, transformedProg); + if (!state.opts.bundleMode || !((_a = state.filename) === null || _a === void 0 ? void 0 : _a.includes("workletRuntimeEntry"))) { + return; + } + const expressionPath = path.get("expression"); + if (!expressionPath.isAssignmentExpression()) { + return; + } + const left = expressionPath.get("left"); + if (!left.isMemberExpression()) { + return; + } + const object = left.get("object"); + const property = left.get("property"); + if (!object.isIdentifier() || object.node.name !== "globalThis" || !property.isIdentifier() || property.node.name !== "_WORKLETS_BUNDLE_MODE_ENABLED") { + return; + } + const right = expressionPath.get("right"); + right.replaceWith((0, types_12.booleanLiteral)(true)); } } }); @@ -724,1104 +738,1084 @@ var require_transform = __commonJS({ } }); -// lib/workletStringCode.js -var require_workletStringCode = __commonJS({ - "lib/workletStringCode.js"(exports2) { +// lib/utils.js +var require_utils = __commonJS({ + "lib/utils.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.isRelease = isRelease; + exports2.replaceWithFactoryCall = replaceWithFactoryCall; + var types_12 = require("@babel/types"); + function isRelease() { + var _a, _b; + const pattern = /(prod|release|stag[ei])/i; + return !!(((_a = process.env.BABEL_ENV) === null || _a === void 0 ? void 0 : _a.match(pattern)) || ((_b = process.env.NODE_ENV) === null || _b === void 0 ? void 0 : _b.match(pattern))); + } + function replaceWithFactoryCall(toReplace, name, factoryCall) { + if (!name || !needsDeclaration(toReplace)) { + toReplace.replaceWith(factoryCall); + } else { + const replacement = (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(name), factoryCall) + ]); + toReplace.replaceWith(replacement); + } + } + function needsDeclaration(nodePath) { + return (0, types_12.isScopable)(nodePath.parent) || (0, types_12.isExportNamedDeclaration)(nodePath.parent); + } + } +}); + +// lib/class.js +var require_class = __commonJS({ + "lib/class.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m[k]; - } }; - } - Object.defineProperty(o, k2, desc); - }) : (function(o, m, k, k2) { - if (k2 === void 0) k2 = k; - o[k2] = m[k]; - })); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - }) : function(o, v) { - o["default"] = v; - }); - var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function(o2) { - var ar = []; - for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - } - __setModuleDefault(result, mod); - return result; - }; - })(); var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.buildWorkletString = buildWorkletString; - var core_1 = require("@babel/core"); + exports2.processIfWorkletClass = processIfWorkletClass; var generator_1 = __importDefault(require("@babel/generator")); + var traverse_1 = __importDefault(require("@babel/traverse")); var types_12 = require("@babel/types"); var assert_1 = require("assert"); - var convertSourceMap = __importStar(require("convert-source-map")); - var fs = __importStar(require("fs")); var transform_1 = require_transform(); var types_2 = require_types(); var utils_1 = require_utils(); - var MOCK_SOURCE_MAP = "mock source map"; - function buildWorkletString(fun, state, closureVariables, workletName, inputMap) { - var _a; - restoreRecursiveCalls(fun, workletName); - const draftExpression = fun.program.body.find((obj) => (0, types_12.isFunctionDeclaration)(obj)) || fun.program.body.find((obj) => (0, types_12.isExpressionStatement)(obj)); - (0, assert_1.strict)(draftExpression, "[Reanimated] `draftExpression` is undefined."); - const expression = (0, types_12.isFunctionDeclaration)(draftExpression) ? draftExpression : draftExpression.expression; - (0, assert_1.strict)("params" in expression, "'params' property is undefined in 'expression'"); - (0, assert_1.strict)((0, types_12.isBlockStatement)(expression.body), "[Reanimated] `expression.body` is not a `BlockStatement`"); - const parsedClasses = /* @__PURE__ */ new Set(); - if (!state.opts.disableWorkletClasses) { - (0, core_1.traverse)(fun, { - NewExpression(path) { - if (!(0, types_12.isIdentifier)(path.node.callee)) { - return; - } - const constructorName = path.node.callee.name; - if (!closureVariables.some((variable) => variable.name === constructorName) || parsedClasses.has(constructorName)) { - return; - } - const index = closureVariables.findIndex((variable) => variable.name === constructorName); - closureVariables.splice(index, 1); - const workletClassFactoryName = constructorName + types_2.workletClassFactorySuffix; - closureVariables.push((0, types_12.identifier)(workletClassFactoryName)); - (0, types_12.assertBlockStatement)(expression.body); - expression.body.body.unshift((0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(constructorName), (0, types_12.callExpression)((0, types_12.identifier)(workletClassFactoryName), [])) - ])); - parsedClasses.add(constructorName); - } - }); - } - const workletFunction = (0, types_12.functionExpression)((0, types_12.identifier)(workletName), expression.params, expression.body, expression.generator, expression.async); - const code = (0, generator_1.default)(workletFunction).code; - (0, assert_1.strict)(inputMap, "[Reanimated] `inputMap` is undefined."); - const includeSourceMap = !((0, utils_1.isRelease)() || state.opts.disableSourceMaps); - if (includeSourceMap) { - inputMap.sourcesContent = []; - for (const sourceFile of inputMap.sources) { - inputMap.sourcesContent.push(fs.readFileSync(sourceFile).toString("utf-8")); - } + var classWorkletMarker = "__workletClass"; + function processIfWorkletClass(classPath, state) { + if (!isWorkletizableClass(classPath, state) || state.opts.bundleMode) { + return false; } - const transformed = (0, transform_1.workletTransformSync)(code, { - filename: state.file.opts.filename, + removeWorkletClassMarker(classPath.node.body); + processClass(classPath, state); + return true; + } + function processClass(classPath, state) { + (0, assert_1.strict)(classPath.node.id); + const className = classPath.node.id.name; + const polyfilledClassAst = getPolyfilledAst(classPath.node, state); + sortPolyfills(polyfilledClassAst); + appendWorkletDirectiveToPolyfills(polyfilledClassAst.program.body); + replaceClassDeclarationWithFactoryAndCall(polyfilledClassAst.program.body, className); + polyfilledClassAst.program.body.push((0, types_12.returnStatement)((0, types_12.identifier)(className))); + const factoryFactory = (0, types_12.functionExpression)(null, [], (0, types_12.blockStatement)([...polyfilledClassAst.program.body])); + const factoryCall = (0, types_12.callExpression)(factoryFactory, []); + (0, utils_1.replaceWithFactoryCall)(classPath, className, factoryCall); + } + function getPolyfilledAst(classNode, state) { + var _a; + const classCode = (0, generator_1.default)(classNode).code; + const classWithPolyfills = (0, transform_1.workletTransformSync)(classCode, { extraPlugins: [ - getClosurePlugin(closureVariables), + "@babel/plugin-transform-class-properties", + "@babel/plugin-transform-classes", + "@babel/plugin-transform-unicode-regex", ...(_a = state.opts.extraPlugins) !== null && _a !== void 0 ? _a : [] ], extraPresets: state.opts.extraPresets, - compact: true, - sourceMaps: includeSourceMap, - inputSourceMap: inputMap, - ast: false, + filename: state.file.opts.filename, + ast: true, babelrc: false, - configFile: false, - comments: false + configFile: false }); - (0, assert_1.strict)(transformed, "[Reanimated] `transformed` is null."); - let sourceMap; - if (includeSourceMap) { - if (shouldMockSourceMap()) { - sourceMap = MOCK_SOURCE_MAP; - } else { - sourceMap = convertSourceMap.fromObject(transformed.map).toObject(); - delete sourceMap.sourcesContent; + (0, assert_1.strict)(classWithPolyfills && classWithPolyfills.ast); + return classWithPolyfills.ast; + } + function appendWorkletDirectiveToPolyfills(statements) { + statements.forEach((statement) => { + if ((0, types_12.isFunctionDeclaration)(statement)) { + const workletDirective = (0, types_12.directive)((0, types_12.directiveLiteral)("worklet")); + statement.body.directives.push(workletDirective); } + }); + } + function replaceClassDeclarationWithFactoryAndCall(statements, className) { + const classFactoryName = className + types_2.workletClassFactorySuffix; + const classDeclarationIndex = getPolyfilledClassDeclarationIndex(statements, className); + const classDeclarationToReplace = statements[classDeclarationIndex]; + const classDeclarationInit = classDeclarationToReplace.declarations[0].init; + const classFactoryDeclaration = (0, types_12.functionDeclaration)((0, types_12.identifier)(classFactoryName), [], (0, types_12.blockStatement)([ + (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(className), classDeclarationInit) + ]), + (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(className), (0, types_12.identifier)(classFactoryName)), (0, types_12.identifier)(classFactoryName))), + (0, types_12.returnStatement)((0, types_12.identifier)(className)) + ], [(0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))])); + const newClassDeclaration = (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(className), (0, types_12.callExpression)((0, types_12.identifier)(classFactoryName), [])) + ]); + statements.splice(classDeclarationIndex, 1, classFactoryDeclaration, newClassDeclaration); + } + function getPolyfilledClassDeclarationIndex(statements, className) { + const index = statements.findIndex((statement) => (0, types_12.isVariableDeclaration)(statement) && statement.declarations.some((declaration) => (0, types_12.isIdentifier)(declaration.id) && declaration.id.name === className)); + (0, assert_1.strict)(index >= 0); + return index; + } + function hasWorkletClassMarker(classBody) { + return classBody.body.some((statement) => (0, types_12.isClassProperty)(statement) && (0, types_12.isIdentifier)(statement.key) && statement.key.name === classWorkletMarker); + } + function removeWorkletClassMarker(classBody) { + classBody.body = classBody.body.filter((statement) => !(0, types_12.isClassProperty)(statement) || !(0, types_12.isIdentifier)(statement.key) || statement.key.name !== classWorkletMarker); + } + function sortPolyfills(ast) { + const toSort = getPolyfillsToSort(ast); + const sorted = topoSort(toSort); + const toSortIndices = toSort.map((element) => element.index); + const sortedIndices = sorted.map((element) => element.index); + const statements = ast.program.body; + const oldStatements = [...statements]; + for (let i = 0; i < toSort.length; i++) { + const sourceIndex = sortedIndices[i]; + const targetIndex = toSortIndices[i]; + const source = oldStatements[sourceIndex]; + statements[targetIndex] = source; } - return [transformed.code, JSON.stringify(sourceMap)]; } - function restoreRecursiveCalls(file, newName) { - (0, core_1.traverse)(file, { - FunctionExpression(path) { - if (!path.node.id) { - path.stop(); - return; + function getPolyfillsToSort(ast) { + const polyfills = []; + (0, traverse_1.default)(ast, { + Program: { + enter: (functionPath) => { + const statements = functionPath.get("body"); + statements.forEach((statement, index) => { + var _a; + const bindingIdentifiers = statement.getBindingIdentifiers(); + if (!statement.isFunctionDeclaration() || !((_a = statement.node.id) === null || _a === void 0 ? void 0 : _a.name)) { + return; + } + const element = { + name: statement.node.id.name, + index, + dependencies: /* @__PURE__ */ new Set() + }; + polyfills.push(element); + statement.traverse({ + Identifier(path) { + if (isOutsideDependency(path, bindingIdentifiers, statement)) { + element.dependencies.add(path.node.name); + } + } + }); + }); } - const oldName = path.node.id.name; - const scope = path.scope; - scope.rename(oldName, newName); } }); + return polyfills; } - function shouldMockSourceMap() { - return process.env.REANIMATED_JEST_SHOULD_MOCK_SOURCE_MAP === "1"; + function topoSort(toSort) { + const sorted = []; + const stack = /* @__PURE__ */ new Set(); + for (const element of toSort) { + recursiveTopoSort(element, toSort, sorted, stack); + } + return sorted; } - function prependClosure(path, closureVariables, closureDeclaration) { - if (closureVariables.length === 0 || !(0, types_12.isProgram)(path.parent)) { + function recursiveTopoSort(current, toSort, sorted, stack) { + if (stack.has(current.name)) { + throw new Error("Cycle detected. This should never happen."); + } + if (sorted.find((element) => element.name === current.name)) { return; } - if (!(0, types_12.isExpression)(path.node.body)) { - path.node.body.body.unshift(closureDeclaration); + stack.add(current.name); + for (const dependency of current.dependencies) { + if (!sorted.find((element) => element.name === dependency)) { + const next = toSort.find((element) => element.name === dependency); + (0, assert_1.strict)(next); + recursiveTopoSort(next, toSort, sorted, stack); + } } + sorted.push(current); + stack.delete(current.name); } - function prependRecursiveDeclaration(path) { + function isOutsideDependency(identifierPath, bindingIdentifiers, functionPath) { + return ( + // We don't care about identifiers that were just declared. + identifierPath.isReferencedIdentifier() && // We don't care about identifiers that are bound in the scope. + !(identifierPath.node.name in bindingIdentifiers) && // This I don't exactly understand, but the function identifier itself isn't in `bindingIdentifiers`, + // but it return true on `hasOwnBinding`. + !functionPath.scope.hasOwnBinding(identifierPath.node.name) && // `hasReference` returns true for global identifiers, like `Object`, + // we don't want to include those. + functionPath.scope.hasReference(identifierPath.node.name) + ); + } + function isWorkletizableClass(classPath, state) { var _a; - if ((0, types_12.isProgram)(path.parent) && !(0, types_12.isArrowFunctionExpression)(path.node) && !(0, types_12.isObjectMethod)(path.node) && path.node.id && path.scope.parent) { - const hasRecursiveCalls = ((_a = path.scope.parent.bindings[path.node.id.name]) === null || _a === void 0 ? void 0 : _a.references) > 0; - if (hasRecursiveCalls) { - path.node.body.body.unshift((0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(path.node.id.name), (0, types_12.memberExpression)((0, types_12.thisExpression)(), (0, types_12.identifier)("_recur"))) - ])); - } + const className = (_a = classPath.node.id) === null || _a === void 0 ? void 0 : _a.name; + const classNode = classPath.node; + if (!className) { + return false; } - } - function getClosurePlugin(closureVariables) { - const closureDeclaration = (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.objectPattern)(closureVariables.map((variable) => (0, types_12.objectProperty)((0, types_12.identifier)(variable.name), (0, types_12.identifier)(variable.name), false, true))), (0, types_12.memberExpression)((0, types_12.thisExpression)(), (0, types_12.identifier)("__closure"))) - ]); - return { - visitor: { - "FunctionDeclaration|FunctionExpression|ArrowFunctionExpression|ObjectMethod": (path) => { - prependClosure(path, closureVariables, closureDeclaration); - prependRecursiveDeclaration(path); - } - } - }; + const isMarked = hasWorkletClassMarker(classNode.body); + const isMemoizedNode = state.classesToWorkletize.some((record) => record.node === classNode); + const isTopLevelMemoizedName = classPath.parentPath.isProgram() && state.classesToWorkletize.some((record) => record.name === className); + state.classesToWorkletize = state.classesToWorkletize.filter((record) => record.node !== classNode && record.name !== className); + const result = isMarked || isMemoizedNode || isTopLevelMemoizedName; + return result; } } }); -// lib/workletFactory.js -var require_workletFactory = __commonJS({ - "lib/workletFactory.js"(exports2) { +// lib/globals.js +var require_globals = __commonJS({ + "lib/globals.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.makeWorkletFactory = makeWorkletFactory; - var generator_1 = __importDefault(require("@babel/generator")); - var types_12 = require("@babel/types"); - var assert_1 = require("assert"); - var path_1 = require("path"); - var closure_1 = require_closure(); - var generate_1 = require_generate(); - var transform_1 = require_transform(); - var types_2 = require_types(); - var utils_1 = require_utils(); - var workletStringCode_1 = require_workletStringCode(); - var REAL_VERSION = require("../package.json").version; - var MOCK_VERSION = "x.y.z"; - function makeWorkletFactory(fun, state) { - var _a; - removeWorkletDirective(fun); - (0, assert_1.strict)(state.file.opts.filename, "[Reanimated] `state.file.opts.filename` is undefined."); - const codeObject = (0, generator_1.default)(fun.node, { - sourceMaps: true, - sourceFileName: state.file.opts.filename - }); - codeObject.code = "(" + (fun.isObjectMethod() ? "function " : "") + codeObject.code + "\n)"; - const transformed = (0, transform_1.workletTransformSync)(codeObject.code, { - extraPlugins: [...extraPlugins, ...(_a = state.opts.extraPlugins) !== null && _a !== void 0 ? _a : []], - extraPresets: state.opts.extraPresets, - filename: state.file.opts.filename, - ast: true, - babelrc: false, - configFile: false, - inputSourceMap: codeObject.map - }); - (0, assert_1.strict)(transformed, "[Reanimated] `transformed` is undefined."); - (0, assert_1.strict)(transformed.ast, "[Reanimated] `transformed.ast` is undefined."); - const { closureVariables, libraryBindingsToImport, relativeBindingsToImport } = (0, closure_1.getClosure)(fun, state); - const clone = (0, types_12.cloneNode)(fun.node); - const funExpression = (0, types_12.isBlockStatement)(clone.body) ? (0, types_12.functionExpression)(null, clone.params, clone.body, clone.generator, clone.async) : clone; - const { workletName, reactName } = makeWorkletName(fun, state); - let mutatedClosureVariables; - if (state.opts.bundleMode) { - mutatedClosureVariables = closureVariables.map((variable) => (0, types_12.cloneNode)(variable, true)); - } else { - mutatedClosureVariables = closureVariables; - } - let [funString, sourceMapString] = (0, workletStringCode_1.buildWorkletString)(transformed.ast, state, mutatedClosureVariables, workletName, transformed.map); - (0, assert_1.strict)(funString, "[Reanimated] `funString` is undefined."); - const workletHash = hash(funString); - let lineOffset = 1; - if (closureVariables.length > 0) { - lineOffset -= closureVariables.length + 2; - } - const pathForStringDefinitions = fun.parentPath.isProgram() ? fun : fun.findParent((path) => { - var _a2, _b; - return (_b = (_a2 = path.parentPath) === null || _a2 === void 0 ? void 0 : _a2.isProgram()) !== null && _b !== void 0 ? _b : false; - }); - (0, assert_1.strict)(pathForStringDefinitions, "[Reanimated] `pathForStringDefinitions` is null."); - (0, assert_1.strict)(pathForStringDefinitions.parentPath, "[Reanimated] `pathForStringDefinitions.parentPath` is null."); - const initDataId = pathForStringDefinitions.parentPath.scope.generateUidIdentifier(`worklet_${workletHash}_init_data`); - const initDataObjectExpression = (0, types_12.objectExpression)([ - (0, types_12.objectProperty)((0, types_12.identifier)("code"), (0, types_12.stringLiteral)(funString)) - ]); - const shouldInjectLocation = !(0, utils_1.isRelease)(); - if (shouldInjectLocation) { - let location = state.file.opts.filename; - if (state.opts.relativeSourceLocation) { - location = (0, path_1.relative)(state.cwd, location); - sourceMapString = sourceMapString === null || sourceMapString === void 0 ? void 0 : sourceMapString.replace(state.file.opts.filename, location); - } - initDataObjectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)("location"), (0, types_12.stringLiteral)(location))); - } - if (sourceMapString) { - initDataObjectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)("sourceMap"), (0, types_12.stringLiteral)(sourceMapString))); - } - const shouldIncludeInitData = !state.opts.omitNativeOnlyData; - if (shouldIncludeInitData && !state.opts.bundleMode) { - const initDataDeclaration = (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)(initDataId, initDataObjectExpression) - ]); - if (state.opts.limitInitDataHoisting) { - fun.getFunctionParent().node.body.body.unshift(initDataDeclaration); - } else { - pathForStringDefinitions.insertBefore(initDataDeclaration); - } - } - (0, assert_1.strict)(!(0, types_12.isFunctionDeclaration)(funExpression), "[Reanimated] `funExpression` is a `FunctionDeclaration`."); - (0, assert_1.strict)(!(0, types_12.isObjectMethod)(funExpression), "[Reanimated] `funExpression` is an `ObjectMethod`."); - const statements = [ - (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(reactName), funExpression) - ]), - (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__closure"), false), (0, types_12.objectExpression)(closureVariables.map((variable) => !state.opts.bundleMode && variable.name.endsWith(types_2.workletClassFactorySuffix) ? (0, types_12.objectProperty)((0, types_12.identifier)(variable.name), (0, types_12.memberExpression)((0, types_12.identifier)(variable.name.slice(0, variable.name.length - types_2.workletClassFactorySuffix.length)), (0, types_12.identifier)(variable.name))) : (0, types_12.objectProperty)((0, types_12.cloneNode)(variable, true), (0, types_12.cloneNode)(variable, true), false, true))))), - (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__workletHash"), false), (0, types_12.numericLiteral)(workletHash))) - ]; - const shouldInjectVersion = !(0, utils_1.isRelease)(); - if (shouldInjectVersion) { - statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__pluginVersion")), (0, types_12.stringLiteral)(shouldMockVersion() ? MOCK_VERSION : REAL_VERSION)))); - } - if (shouldIncludeInitData && !state.opts.bundleMode) { - statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__initData"), false), (0, types_12.cloneNode)(initDataId, true)))); - } - if (!(0, utils_1.isRelease)()) { - statements.unshift((0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)("_e"), (0, types_12.arrayExpression)([ - (0, types_12.newExpression)((0, types_12.memberExpression)((0, types_12.identifier)("global"), (0, types_12.identifier)("Error")), []), - (0, types_12.numericLiteral)(lineOffset), - (0, types_12.numericLiteral)(-27) - // the placement of opening bracket after Exception in line that defined '_e' variable - ])) - ])); - statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__stackDetails"), false), (0, types_12.identifier)("_e")))); - } - statements.push((0, types_12.returnStatement)((0, types_12.identifier)(reactName))); - const factoryParams = closureVariables.map((variableId) => { - const clonedId = (0, types_12.cloneNode)(variableId, true); - if (!state.opts.bundleMode && clonedId.name.endsWith(types_2.workletClassFactorySuffix)) { - clonedId.name = clonedId.name.slice(0, clonedId.name.length - types_2.workletClassFactorySuffix.length); - } - return clonedId; - }); - if (shouldIncludeInitData && !state.opts.bundleMode) { - factoryParams.unshift((0, types_12.cloneNode)(initDataId, true)); - } - const factoryParamObjectPattern = (0, types_12.objectPattern)(factoryParams.map((param) => (0, types_12.objectProperty)((0, types_12.cloneNode)(param, true), (0, types_12.cloneNode)(param, true), false, true))); - const factory = (0, types_12.functionExpression)((0, types_12.identifier)(workletName + "Factory"), [factoryParamObjectPattern], (0, types_12.blockStatement)(statements)); - const factoryCallArgs = factoryParams.map((param) => (0, types_12.cloneNode)(param, true)); - const factoryCallParamPack = (0, types_12.objectExpression)(factoryCallArgs.map((param) => (0, types_12.objectProperty)((0, types_12.cloneNode)(param, true), (0, types_12.cloneNode)(param, true), false, true))); - if (state.opts.bundleMode) { - (0, generate_1.generateWorkletFile)(libraryBindingsToImport, relativeBindingsToImport, factory, workletHash, state); + exports2.globals = exports2.defaultGlobals = exports2.internalBindingsToCaptureFromGlobalScope = exports2.outsideBindingsToCaptureFromGlobalScope = void 0; + exports2.initializeState = initializeState; + exports2.initializeGlobals = initializeGlobals; + exports2.addCustomGlobals = addCustomGlobals; + var notCapturedIdentifiers = [ + // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects + // Note that objects' properties don't need to be listed since we always only capture the whole object, + // e.g. `global.__ErrorUtils` or `Intl.DateTimeFormat`. + // Value properties + "globalThis", + "Infinity", + "NaN", + "undefined", + // Function properties + "eval", + "isFinite", + "isNaN", + "parseFloat", + "parseInt", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "escape", + "unescape", + // Fundamental objects + "Object", + "Function", + "Boolean", + "Symbol", + // Error objects + "Error", + "AggregateError", + "EvalError", + "RangeError", + "ReferenceError", + "SyntaxError", + "TypeError", + "URIError", + "InternalError", + // Numbers and dates + "Number", + "BigInt", + "Math", + "Date", + // Text processing + "String", + "RegExp", + // Indexed collections + "Array", + "Int8Array", + "Uint8Array", + "Uint8ClampedArray", + "Int16Array", + "Uint16Array", + "Int32Array", + "Uint32Array", + "BigInt64Array", + "BigUint64Array", + "Float32Array", + "Float64Array", + // Keyed collections + "Map", + "Set", + "WeakMap", + "WeakSet", + // Structured data + "ArrayBuffer", + "SharedArrayBuffer", + "DataView", + "Atomics", + "JSON", + // Managing memory + "WeakRef", + "FinalizationRegistry", + // Control abstraction objects + "Iterator", + "AsyncIterator", + "Promise", + "GeneratorFunction", + "AsyncGeneratorFunction", + "Generator", + "AsyncGenerator", + "AsyncFunction", + // Reflection + "Reflect", + "Proxy", + // Internationalization + "Intl", + // Other stuff + "null", + "this", + "global", + "window", + "globalThis", + "self", + "console", + "performance", + "arguments", + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments + "require", + "fetch", + "XMLHttpRequest", + "WebSocket", + // Run loop + "queueMicrotask", + "requestAnimationFrame", + "cancelAnimationFrame", + "setTimeout", + "clearTimeout", + "setImmediate", + "clearImmediate", + "setInterval", + "clearInterval", + // Hermes + "HermesInternal", + // Worklets + "_WORKLET" + ]; + exports2.outsideBindingsToCaptureFromGlobalScope = /* @__PURE__ */ new Set([ + "ReanimatedError" + ]); + exports2.internalBindingsToCaptureFromGlobalScope = /* @__PURE__ */ new Set([ + "WorkletsError" + ]); + var notCapturedIdentifiers_DEPRECATED = ["_IS_FABRIC"]; + function initializeState(state) { + state.workletNumber = 1; + state.classesToWorkletize = []; + if (!state.opts.strictGlobal) { + initializeGlobals(); + addCustomGlobals(state); } - factory.workletized = true; - return { factory, factoryCallParamPack, workletHash }; - } - function removeWorkletDirective(fun) { - fun.traverse({ - DirectiveLiteral(nodePath) { - if (nodePath.node.value === "worklet" && nodePath.getFunctionParent() === fun) { - nodePath.parentPath.remove(); - } - } - }); } - function shouldMockVersion() { - return process.env.REANIMATED_JEST_SHOULD_MOCK_VERSION === "1"; - } - function hash(str) { - let i = str.length; - let hash1 = 5381; - let hash2 = 52711; - while (i--) { - const char = str.charCodeAt(i); - hash1 = hash1 * 33 ^ char; - hash2 = hash2 * 33 ^ char; - } - return (hash1 >>> 0) * 4096 + (hash2 >>> 0); + exports2.defaultGlobals = new Set(notCapturedIdentifiers.concat(notCapturedIdentifiers_DEPRECATED)); + function initializeGlobals() { + exports2.globals = new Set(exports2.defaultGlobals); } - function makeWorkletName(fun, state) { - let source = "unknownFile"; - if (state.file.opts.filename) { - const filepath = state.file.opts.filename; - source = (0, path_1.basename)(filepath); - const splitFilepath = filepath.split("/"); - const nodeModulesIndex = splitFilepath.indexOf("node_modules"); - if (nodeModulesIndex !== -1) { - const libraryName = splitFilepath[nodeModulesIndex + 1]; - source = `${libraryName}_${source}`; - } - } - const suffix = `${source}${state.workletNumber++}`; - let reactName = ""; - if ((0, types_12.isObjectMethod)(fun.node) && (0, types_12.isIdentifier)(fun.node.key)) { - reactName = fun.node.key.name; - } else if (((0, types_12.isFunctionDeclaration)(fun.node) || (0, types_12.isFunctionExpression)(fun.node)) && (0, types_12.isIdentifier)(fun.node.id)) { - reactName = fun.node.id.name; + function addCustomGlobals(state) { + if (state.opts && Array.isArray(state.opts.globals)) { + state.opts.globals.forEach((name) => { + exports2.globals.add(name); + }); } - const workletName = reactName ? (0, types_12.toIdentifier)(`${reactName}_${suffix}`) : (0, types_12.toIdentifier)(suffix); - reactName = reactName || (0, types_12.toIdentifier)(suffix); - return { workletName, reactName }; } - var extraPlugins = [ - require.resolve("@babel/plugin-transform-shorthand-properties"), - require.resolve("@babel/plugin-transform-arrow-functions"), - require.resolve("@babel/plugin-transform-optional-chaining"), - require.resolve("@babel/plugin-transform-nullish-coalescing-operator"), - [ - require.resolve("@babel/plugin-transform-template-literals"), - { loose: true } - ] - ]; } }); -// lib/workletFactoryCall.js -var require_workletFactoryCall = __commonJS({ - "lib/workletFactoryCall.js"(exports2) { +// lib/inlineStylesWarning.js +var require_inlineStylesWarning = __commonJS({ + "lib/inlineStylesWarning.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.makeWorkletFactoryCall = makeWorkletFactoryCall; + exports2.processInlineStylesWarning = processInlineStylesWarning; var types_12 = require("@babel/types"); - var types_2 = require_types(); - var workletFactory_1 = require_workletFactory(); - function makeWorkletFactoryCall(path, state) { - const { factory, factoryCallParamPack, workletHash } = (0, workletFactory_1.makeWorkletFactory)(path, state); - let factoryCall; - if (state.opts.bundleMode) { - factoryCall = (0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.callExpression)((0, types_12.identifier)("require"), [ - (0, types_12.stringLiteral)(`react-native-worklets/${types_2.generatedWorkletsDir}/${workletHash}.js`) - ]), (0, types_12.identifier)("default")), [factoryCallParamPack]); - } else { - factoryCall = (0, types_12.callExpression)(factory, [factoryCallParamPack]); - } - addStackTraceDataToWorkletFactory(path, factoryCall); - const replacement = factoryCall; - return replacement; + var assert_1 = require("assert"); + var utils_1 = require_utils(); + function generateInlineStylesWarning(path) { + return (0, types_12.callExpression)((0, types_12.arrowFunctionExpression)([], (0, types_12.blockStatement)([ + (0, types_12.expressionStatement)((0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.identifier)("console"), (0, types_12.identifier)("warn")), [ + (0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.callExpression)((0, types_12.identifier)("require"), [ + (0, types_12.stringLiteral)("react-native-reanimated") + ]), (0, types_12.identifier)("getUseOfValueInStyleWarning")), []) + ])), + (0, types_12.returnStatement)(path.node) + ])), []); } - function addStackTraceDataToWorkletFactory(path, workletFactoryCall) { - const originalWorkletLocation = path.node.loc; - if (originalWorkletLocation) { - workletFactoryCall.callee.loc = { - filename: originalWorkletLocation.filename, - identifierName: originalWorkletLocation.identifierName, - start: originalWorkletLocation.start, - end: originalWorkletLocation.start - }; + function processPropertyValueForInlineStylesWarning(path) { + if (path.isMemberExpression() && (0, types_12.isIdentifier)(path.node.property)) { + if (!path.node.computed && path.node.property.name === "value") { + path.replaceWith(generateInlineStylesWarning(path)); + } } } - } -}); - -// lib/workletSubstitution.js -var require_workletSubstitution = __commonJS({ - "lib/workletSubstitution.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.processIfWithWorkletDirective = processIfWithWorkletDirective; - exports2.processWorklet = processWorklet; - exports2.substituteObjectMethodWithObjectProperty = substituteObjectMethodWithObjectProperty; - var types_12 = require("@babel/types"); - var types_2 = require_types(); - var utils_1 = require_utils(); - var workletFactoryCall_1 = require_workletFactoryCall(); - function processIfWithWorkletDirective(path, state) { - if (!(0, types_12.isBlockStatement)(path.node.body)) { - return false; - } - if (!hasWorkletDirective(path.node.body.directives)) { - return false; + function processTransformPropertyForInlineStylesWarning(path) { + if ((0, types_12.isArrayExpression)(path.node)) { + const elements = path.get("elements"); + (0, assert_1.strict)(Array.isArray(elements), "[Reanimated] `elements` should be an array."); + for (const element of elements) { + if (element.isObjectExpression()) { + processStyleObjectForInlineStylesWarning(element); + } + } } - processWorklet(path, state); - return true; } - function processWorklet(path, state) { - path.traverse({ - // @ts-expect-error TypeScript doesn't like this syntax here. - [types_2.WorkletizableFunction](subPath, passedState) { - processIfWithWorkletDirective(subPath, passedState); + function processStyleObjectForInlineStylesWarning(path) { + const properties = path.get("properties"); + for (const property of properties) { + if (property.isObjectProperty()) { + const value = property.get("value"); + if ((0, types_12.isIdentifier)(property.node.key) && property.node.key.name === "transform") { + processTransformPropertyForInlineStylesWarning(value); + } else { + processPropertyValueForInlineStylesWarning(value); + } } - }, state); - const workletFactoryCall = (0, workletFactoryCall_1.makeWorkletFactoryCall)(path, state); - substituteWorkletWithWorkletFactoryCall(path, workletFactoryCall); - path.scope.getProgramParent().crawl(); - } - function hasWorkletDirective(directives) { - return directives.some((directive) => (0, types_12.isDirectiveLiteral)(directive.value) && directive.value.value === "worklet"); - } - function substituteWorkletWithWorkletFactoryCall(path, workletFactoryCall) { - var _a; - if (path.isObjectMethod()) { - substituteObjectMethodWithObjectProperty(path, workletFactoryCall); - } else { - const name = "id" in path.node ? (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name : void 0; - (0, utils_1.replaceWithFactoryCall)(path, name, workletFactoryCall); } } - function substituteObjectMethodWithObjectProperty(path, workletFactoryCall) { - const replacement = (0, types_12.objectProperty)(path.node.key, workletFactoryCall); - path.replaceWith(replacement); - } - } -}); - -// lib/objectWorklets.js -var require_objectWorklets = __commonJS({ - "lib/objectWorklets.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.tryProcessingNode = tryProcessingNode; - exports2.processWorkletizableObject = processWorkletizableObject; - var findWorklet_1 = require_findWorklet(); - var types_12 = require_types(); - var workletSubstitution_12 = require_workletSubstitution(); - function tryProcessingNode(arg, state, acceptWorkletizableFunction, acceptObject) { - var _a; - const maybeWorklet = (0, findWorklet_1.findWorklet)(arg, state, acceptWorkletizableFunction, acceptObject); - if (!maybeWorklet || ((_a = maybeWorklet.getFunctionParent()) === null || _a === void 0 ? void 0 : _a.node.workletized)) { + function processInlineStylesWarning(path, state) { + if ((0, utils_1.isRelease)()) { return; } - if ((0, types_12.isWorkletizableFunctionPath)(maybeWorklet)) { - (0, workletSubstitution_12.processWorklet)(maybeWorklet, state); - } else if ((0, types_12.isWorkletizableObjectPath)(maybeWorklet)) { - processWorkletizableObject(maybeWorklet, state); + if (state.opts.disableInlineStylesWarning) { + return; } - } - function processWorkletizableObject(path, state) { - const properties = path.get("properties"); - for (const property of properties) { - if (property.isObjectMethod()) { - (0, workletSubstitution_12.processWorklet)(property, state); - } else if (property.isObjectProperty()) { - const value = property.get("value"); - tryProcessingNode( - value, - state, - true, - // acceptWorkletizableFunction - false - // acceptObject - ); - } else { - throw new Error(`[Reanimated] '${property.type}' as to-be workletized argument is not supported for object hooks.`); + if (path.node.name.name !== "style") { + return; + } + if (!(0, types_12.isJSXExpressionContainer)(path.node.value)) { + return; + } + const expression = path.get("value").get("expression"); + (0, assert_1.strict)(!Array.isArray(expression), "[Reanimated] `expression` should not be an array."); + if (expression.isArrayExpression()) { + const elements = expression.get("elements"); + (0, assert_1.strict)(Array.isArray(elements), "[Reanimated] `elements` should be an array."); + for (const element of elements) { + if (element.isObjectExpression()) { + processStyleObjectForInlineStylesWarning(element); + } } + } else if (expression.isObjectExpression()) { + processStyleObjectForInlineStylesWarning(expression); } } } }); -// lib/autoworkletization.js -var require_autoworkletization = __commonJS({ - "lib/autoworkletization.js"(exports2) { +// lib/webOptimization.js +var require_webOptimization = __commonJS({ + "lib/webOptimization.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.processIfAutoworkletizableCallback = processIfAutoworkletizableCallback; - exports2.processCalleesAutoworkletizableCallbacks = processCalleesAutoworkletizableCallbacks; + exports2.substituteWebCallExpression = substituteWebCallExpression; var types_12 = require("@babel/types"); - var gestureHandlerAutoworkletization_1 = require_gestureHandlerAutoworkletization(); - var layoutAnimationAutoworkletization_1 = require_layoutAnimationAutoworkletization(); - var objectWorklets_1 = require_objectWorklets(); - var workletSubstitution_12 = require_workletSubstitution(); - var reanimatedObjectHooks = /* @__PURE__ */ new Set([ - "useAnimatedScrollHandler", - ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerObjectHooks) - ]); - var reanimatedFunctionHooks = /* @__PURE__ */ new Set([ - "useFrameCallback", - "useAnimatedStyle", - "useAnimatedProps", - "createAnimatedPropAdapter", - "useDerivedValue", - "useAnimatedScrollHandler", - "useAnimatedReaction", - // animations' callbacks - "withTiming", - "withSpring", - "withDecay", - "withRepeat", - // scheduling functions - "runOnUI", - "executeOnUIRuntimeSync", - "scheduleOnUI", - "runOnUISync", - "runOnUIAsync", - "runOnRuntime", - "runOnRuntimeSync", - "runOnRuntimeAsync", - "scheduleOnRuntime", - "runOnRuntimeSyncWithId", - "scheduleOnRuntimeWithId" - ]); - var reanimatedFunctionArgsToWorkletize = new Map([ - ["useFrameCallback", [0]], - ["useAnimatedStyle", [0]], - ["useAnimatedProps", [0]], - ["createAnimatedPropAdapter", [0]], - ["useDerivedValue", [0]], - ["useAnimatedScrollHandler", [0]], - ["useAnimatedReaction", [0, 1]], - ["withTiming", [2]], - ["withSpring", [2]], - ["withDecay", [1]], - ["withRepeat", [3]], - ["runOnUI", [0]], - ["executeOnUIRuntimeSync", [0]], - ["scheduleOnUI", [0]], - ["runOnUISync", [0]], - ["runOnUIAsync", [0]], - ["runOnRuntime", [1]], - ["runOnRuntimeSync", [1]], - ["runOnRuntimeAsync", [1]], - ["scheduleOnRuntime", [1]], - ["runOnRuntimeSyncWithId", [1]], - ["scheduleOnRuntimeWithId", [1]], - ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerObjectHooks).map((name) => [name, [0]]), - ...Array.from(gestureHandlerAutoworkletization_1.gestureHandlerBuilderMethods).map((name) => [name, [0]]) - ]); - function processIfAutoworkletizableCallback(path, state) { - if ((0, gestureHandlerAutoworkletization_1.isGestureHandlerEventCallback)(path) || (0, layoutAnimationAutoworkletization_1.isLayoutAnimationCallback)(path)) { - (0, workletSubstitution_12.processWorklet)(path, state); - return true; + function substituteWebCallExpression(path) { + const callee = path.node.callee; + if ((0, types_12.isIdentifier)(callee)) { + const name = callee.name; + if (name === "isWeb" || name === "shouldBeUseWeb") { + path.replaceWith((0, types_12.booleanLiteral)(true)); + } } - return false; } - function processCalleesAutoworkletizableCallbacks(path, state) { - const callee = (0, types_12.isSequenceExpression)(path.node.callee) ? path.node.callee.expressions[path.node.callee.expressions.length - 1] : path.node.callee; - const name = "name" in callee ? callee.name : "property" in callee && "name" in callee.property ? callee.property.name : void 0; - if (name === void 0) { - return; - } - if (reanimatedFunctionHooks.has(name) || reanimatedObjectHooks.has(name)) { - const acceptWorkletizableFunction = reanimatedFunctionHooks.has(name); - const acceptObject = reanimatedObjectHooks.has(name); - const argIndices = reanimatedFunctionArgsToWorkletize.get(name); - const args = path.get("arguments").filter((_, index) => argIndices.includes(index)); - processArgs(args, state, acceptWorkletizableFunction, acceptObject); - } else if (!(0, types_12.isV8IntrinsicIdentifier)(callee) && (0, gestureHandlerAutoworkletization_1.isGestureObjectEventCallbackMethod)(callee)) { - const args = path.get("arguments"); - processArgs(args, state, true, true); - } + } +}); + +// lib/closure.js +var require_closure = __commonJS({ + "lib/closure.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.getClosure = getClosure; + var types_12 = require("@babel/types"); + var globals_12 = require_globals(); + function getClosure(funPath, state) { + const capturedNames = /* @__PURE__ */ new Set(); + const closureVariables = new Array(); + const libraryBindingsToImport = /* @__PURE__ */ new Set(); + const relativeBindingsToImport = /* @__PURE__ */ new Set(); + let recrawled = false; + funPath.traverse({ + "TSType|TSTypeAliasDeclaration|TSInterfaceDeclaration"(typePath) { + typePath.skip(); + }, + ReferencedIdentifier(idPath) { + if (idPath.isJSXIdentifier()) { + return; + } + const name = idPath.node.name; + if (capturedNames.has(name)) { + return; + } + let binding = idPath.scope.getBinding(name); + if (!binding && !recrawled) { + recrawled = true; + idPath.scope.crawl(); + binding = idPath.scope.getBinding(name); + } + if (!binding) { + if (state.opts.strictGlobal || globals_12.globals.has(name)) { + return; + } + capturedNames.add(name); + closureVariables.push((0, types_12.cloneNode)(idPath.node, true)); + return; + } + if (globals_12.outsideBindingsToCaptureFromGlobalScope.has(name) || !state.opts.bundleMode && globals_12.internalBindingsToCaptureFromGlobalScope.has(name)) { + return; + } + if ("id" in funPath.node) { + const id = idPath.scope.getBindingIdentifier(name); + if (id && id === funPath.node.id) { + return; + } + } + let scope = idPath.scope; + while (scope !== funPath.scope.parent) { + if (scope.hasOwnBinding(name)) { + return; + } + scope = scope.parent; + } + if (state.opts.bundleMode && isImport(binding)) { + if (isImportRelative(binding) && isAllowedForRelativeImports(state.filename, state.opts.workletizableModules)) { + capturedNames.add(name); + relativeBindingsToImport.add(binding); + return; + } + const source = binding.path.parentPath.node.source.value; + if (isWorkletizableModule(source, state.opts.workletizableModules)) { + capturedNames.add(name); + libraryBindingsToImport.add(binding); + return; + } + } + capturedNames.add(name); + closureVariables.push((0, types_12.cloneNode)(idPath.node, true)); + } + }, state); + return { + closureVariables, + libraryBindingsToImport, + relativeBindingsToImport + }; } - function processArgs(args, state, acceptWorkletizableFunction, acceptObject) { - args.forEach((arg) => { - (0, objectWorklets_1.tryProcessingNode)(arg, state, acceptWorkletizableFunction, acceptObject); - }); + function isImport(binding) { + return binding.kind === "module" && binding.constant && (binding.path.isImportSpecifier() || binding.path.isImportDefaultSpecifier()) && binding.path.parentPath.isImportDeclaration(); + } + function isImportRelative(imported) { + return imported.path.parentPath.node.source.value.startsWith("."); + } + function isAllowedForRelativeImports(filename, workletizableModules) { + return !!filename && (alwaysAllowed.some((module3) => filename.includes(module3)) || !!(workletizableModules === null || workletizableModules === void 0 ? void 0 : workletizableModules.some((module3) => filename.includes(module3)))); + } + function isWorkletizableModule(source, workletizableModules) { + return alwaysAllowed.some((module3) => source.startsWith(module3)) || !!(workletizableModules === null || workletizableModules === void 0 ? void 0 : workletizableModules.some((module3) => source.startsWith(module3))); } + var alwaysAllowed = [ + "react-native-worklets", + "react-native/Libraries/Core/setUpXHR" + // for networking + ]; } }); -// lib/bundleMode.js -var require_bundleMode = __commonJS({ - "lib/bundleMode.js"(exports2) { +// lib/generate.js +var require_generate = __commonJS({ + "lib/generate.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.toggleBundleMode = toggleBundleMode; + exports2.generateWorkletFile = generateWorkletFile; + var core_1 = require("@babel/core"); var types_12 = require("@babel/types"); - function toggleBundleMode(path, state) { + var assert_1 = __importDefault(require("assert")); + var fs_1 = require("fs"); + var path_1 = require("path"); + var types_2 = require_types(); + function generateWorkletFile(libraryBindingsToImport, relativeBindingsToImport, factory, workletHash, state) { var _a; - if (!state.opts.bundleMode || !((_a = state.filename) === null || _a === void 0 ? void 0 : _a.includes("workletRuntimeEntry"))) { - return; - } - const expressionPath = path.get("expression"); - if (!expressionPath.isAssignmentExpression()) { - return; - } - const left = expressionPath.get("left"); - if (!left.isMemberExpression()) { - return; - } - const object = left.get("object"); - const property = left.get("property"); - if (!object.isIdentifier() || object.node.name !== "globalThis" || !property.isIdentifier() || property.node.name !== "_WORKLETS_BUNDLE_MODE_ENABLED") { - return; - } - const right = expressionPath.get("right"); - right.replaceWith((0, types_12.booleanLiteral)(true)); + const libraryImports = Array.from(libraryBindingsToImport).filter((binding) => (binding.path.isImportSpecifier() || binding.path.isImportDefaultSpecifier()) && binding.path.parentPath.isImportDeclaration()).map((binding) => (0, types_12.importDeclaration)([(0, types_12.cloneNode)(binding.path.node, true)], (0, types_12.stringLiteral)(binding.path.parentPath.node.source.value))); + const filesDirPath = (0, path_1.resolve)((0, path_1.dirname)(require.resolve("react-native-worklets/package.json")), types_2.generatedWorkletsDir); + const relativeImports = Array.from(relativeBindingsToImport).filter((binding) => binding.path.isImportSpecifier() && binding.path.parentPath.isImportDeclaration()).map((binding) => { + const resolved = (0, path_1.resolve)((0, path_1.dirname)(state.file.opts.filename), binding.path.parentPath.node.source.value); + const importPath = (0, path_1.relative)(filesDirPath, resolved); + return (0, types_12.importDeclaration)([(0, types_12.cloneNode)(binding.path.node, true)], (0, types_12.stringLiteral)(importPath)); + }); + const imports = [...libraryImports, ...relativeImports]; + const newProg = (0, types_12.program)([...imports, (0, types_12.exportDefaultDeclaration)(factory)]); + const transformedProg = (_a = (0, core_1.transformFromAstSync)(newProg, void 0, { + filename: state.file.opts.filename, + presets: ["@babel/preset-typescript"], + plugins: [], + ast: false, + babelrc: false, + configFile: false, + comments: false + })) === null || _a === void 0 ? void 0 : _a.code; + (0, assert_1.default)(transformedProg, "[Worklets] `transformedProg` is undefined."); + const dedicatedFilePath = (0, path_1.resolve)(filesDirPath, `${workletHash}.js`); + (0, fs_1.writeFileSync)(dedicatedFilePath, transformedProg); } } }); -// lib/class.js -var require_class = __commonJS({ - "lib/class.js"(exports2) { +// lib/workletStringCode.js +var require_workletStringCode = __commonJS({ + "lib/workletStringCode.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === void 0) k2 = k; + o[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function(o2) { + var ar = []; + for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + } + __setModuleDefault(result, mod); + return result; + }; + })(); var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.processIfWorkletClass = processIfWorkletClass; + exports2.buildWorkletString = buildWorkletString; + var core_1 = require("@babel/core"); var generator_1 = __importDefault(require("@babel/generator")); - var traverse_1 = __importDefault(require("@babel/traverse")); var types_12 = require("@babel/types"); var assert_1 = require("assert"); + var convertSourceMap = __importStar(require("convert-source-map")); + var fs = __importStar(require("fs")); var transform_1 = require_transform(); var types_2 = require_types(); var utils_1 = require_utils(); - var classWorkletMarker = "__workletClass"; - function processIfWorkletClass(classPath, state) { - if (!isWorkletizableClass(classPath, state) || state.opts.bundleMode) { - return false; - } - removeWorkletClassMarker(classPath.node.body); - processClass(classPath, state); - return true; - } - function processClass(classPath, state) { - (0, assert_1.strict)(classPath.node.id); - const className = classPath.node.id.name; - const polyfilledClassAst = getPolyfilledAst(classPath.node, state); - sortPolyfills(polyfilledClassAst); - appendWorkletDirectiveToPolyfills(polyfilledClassAst.program.body); - replaceClassDeclarationWithFactoryAndCall(polyfilledClassAst.program.body, className); - polyfilledClassAst.program.body.push((0, types_12.returnStatement)((0, types_12.identifier)(className))); - const factoryFactory = (0, types_12.functionExpression)(null, [], (0, types_12.blockStatement)([...polyfilledClassAst.program.body])); - const factoryCall = (0, types_12.callExpression)(factoryFactory, []); - (0, utils_1.replaceWithFactoryCall)(classPath, className, factoryCall); - } - function getPolyfilledAst(classNode, state) { + var MOCK_SOURCE_MAP = "mock source map"; + function buildWorkletString(fun, state, closureVariables, workletName, inputMap) { var _a; - const classCode = (0, generator_1.default)(classNode).code; - const classWithPolyfills = (0, transform_1.workletTransformSync)(classCode, { + restoreRecursiveCalls(fun, workletName); + const draftExpression = fun.program.body.find((obj) => (0, types_12.isFunctionDeclaration)(obj)) || fun.program.body.find((obj) => (0, types_12.isExpressionStatement)(obj)); + (0, assert_1.strict)(draftExpression, "[Reanimated] `draftExpression` is undefined."); + const expression = (0, types_12.isFunctionDeclaration)(draftExpression) ? draftExpression : draftExpression.expression; + (0, assert_1.strict)("params" in expression, "'params' property is undefined in 'expression'"); + (0, assert_1.strict)((0, types_12.isBlockStatement)(expression.body), "[Reanimated] `expression.body` is not a `BlockStatement`"); + const parsedClasses = /* @__PURE__ */ new Set(); + if (!state.opts.disableWorkletClasses) { + (0, core_1.traverse)(fun, { + NewExpression(path) { + if (!(0, types_12.isIdentifier)(path.node.callee)) { + return; + } + const constructorName = path.node.callee.name; + if (!closureVariables.some((variable) => variable.name === constructorName) || parsedClasses.has(constructorName)) { + return; + } + const index = closureVariables.findIndex((variable) => variable.name === constructorName); + closureVariables.splice(index, 1); + const workletClassFactoryName = constructorName + types_2.workletClassFactorySuffix; + closureVariables.push((0, types_12.identifier)(workletClassFactoryName)); + (0, types_12.assertBlockStatement)(expression.body); + expression.body.body.unshift((0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(constructorName), (0, types_12.callExpression)((0, types_12.identifier)(workletClassFactoryName), [])) + ])); + parsedClasses.add(constructorName); + } + }); + } + const workletFunction = (0, types_12.functionExpression)((0, types_12.identifier)(workletName), expression.params, expression.body, expression.generator, expression.async); + const code = (0, generator_1.default)(workletFunction).code; + (0, assert_1.strict)(inputMap, "[Reanimated] `inputMap` is undefined."); + const includeSourceMap = !((0, utils_1.isRelease)() || state.opts.disableSourceMaps); + if (includeSourceMap) { + inputMap.sourcesContent = []; + for (const sourceFile of inputMap.sources) { + inputMap.sourcesContent.push(fs.readFileSync(sourceFile).toString("utf-8")); + } + } + const transformed = (0, transform_1.workletTransformSync)(code, { + filename: state.file.opts.filename, extraPlugins: [ - "@babel/plugin-transform-class-properties", - "@babel/plugin-transform-classes", - "@babel/plugin-transform-unicode-regex", + getClosurePlugin(closureVariables), ...(_a = state.opts.extraPlugins) !== null && _a !== void 0 ? _a : [] ], extraPresets: state.opts.extraPresets, - filename: state.file.opts.filename, - ast: true, + compact: true, + sourceMaps: includeSourceMap, + inputSourceMap: inputMap, + ast: false, babelrc: false, - configFile: false + configFile: false, + comments: false }); - (0, assert_1.strict)(classWithPolyfills && classWithPolyfills.ast); - return classWithPolyfills.ast; - } - function appendWorkletDirectiveToPolyfills(statements) { - statements.forEach((statement) => { - if ((0, types_12.isFunctionDeclaration)(statement)) { - const workletDirective = (0, types_12.directive)((0, types_12.directiveLiteral)("worklet")); - statement.body.directives.push(workletDirective); + (0, assert_1.strict)(transformed, "[Reanimated] `transformed` is null."); + let sourceMap; + if (includeSourceMap) { + if (shouldMockSourceMap()) { + sourceMap = MOCK_SOURCE_MAP; + } else { + sourceMap = convertSourceMap.fromObject(transformed.map).toObject(); + delete sourceMap.sourcesContent; } - }); - } - function replaceClassDeclarationWithFactoryAndCall(statements, className) { - const classFactoryName = className + types_2.workletClassFactorySuffix; - const classDeclarationIndex = getPolyfilledClassDeclarationIndex(statements, className); - const classDeclarationToReplace = statements[classDeclarationIndex]; - const classDeclarationInit = classDeclarationToReplace.declarations[0].init; - const classFactoryDeclaration = (0, types_12.functionDeclaration)((0, types_12.identifier)(classFactoryName), [], (0, types_12.blockStatement)([ - (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(className), classDeclarationInit) - ]), - (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(className), (0, types_12.identifier)(classFactoryName)), (0, types_12.identifier)(classFactoryName))), - (0, types_12.returnStatement)((0, types_12.identifier)(className)) - ], [(0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))])); - const newClassDeclaration = (0, types_12.variableDeclaration)("const", [ - (0, types_12.variableDeclarator)((0, types_12.identifier)(className), (0, types_12.callExpression)((0, types_12.identifier)(classFactoryName), [])) - ]); - statements.splice(classDeclarationIndex, 1, classFactoryDeclaration, newClassDeclaration); - } - function getPolyfilledClassDeclarationIndex(statements, className) { - const index = statements.findIndex((statement) => (0, types_12.isVariableDeclaration)(statement) && statement.declarations.some((declaration) => (0, types_12.isIdentifier)(declaration.id) && declaration.id.name === className)); - (0, assert_1.strict)(index >= 0); - return index; - } - function hasWorkletClassMarker(classBody) { - return classBody.body.some((statement) => (0, types_12.isClassProperty)(statement) && (0, types_12.isIdentifier)(statement.key) && statement.key.name === classWorkletMarker); - } - function removeWorkletClassMarker(classBody) { - classBody.body = classBody.body.filter((statement) => !(0, types_12.isClassProperty)(statement) || !(0, types_12.isIdentifier)(statement.key) || statement.key.name !== classWorkletMarker); - } - function sortPolyfills(ast) { - const toSort = getPolyfillsToSort(ast); - const sorted = topoSort(toSort); - const toSortIndices = toSort.map((element) => element.index); - const sortedIndices = sorted.map((element) => element.index); - const statements = ast.program.body; - const oldStatements = [...statements]; - for (let i = 0; i < toSort.length; i++) { - const sourceIndex = sortedIndices[i]; - const targetIndex = toSortIndices[i]; - const source = oldStatements[sourceIndex]; - statements[targetIndex] = source; } + return [transformed.code, JSON.stringify(sourceMap)]; } - function getPolyfillsToSort(ast) { - const polyfills = []; - (0, traverse_1.default)(ast, { - Program: { - enter: (functionPath) => { - const statements = functionPath.get("body"); - statements.forEach((statement, index) => { - var _a; - const bindingIdentifiers = statement.getBindingIdentifiers(); - if (!statement.isFunctionDeclaration() || !((_a = statement.node.id) === null || _a === void 0 ? void 0 : _a.name)) { - return; - } - const element = { - name: statement.node.id.name, - index, - dependencies: /* @__PURE__ */ new Set() - }; - polyfills.push(element); - statement.traverse({ - Identifier(path) { - if (isOutsideDependency(path, bindingIdentifiers, statement)) { - element.dependencies.add(path.node.name); - } - } - }); - }); + function restoreRecursiveCalls(file, newName) { + (0, core_1.traverse)(file, { + FunctionExpression(path) { + if (!path.node.id) { + path.stop(); + return; } + const oldName = path.node.id.name; + const scope = path.scope; + scope.rename(oldName, newName); } }); - return polyfills; - } - function topoSort(toSort) { - const sorted = []; - const stack = /* @__PURE__ */ new Set(); - for (const element of toSort) { - recursiveTopoSort(element, toSort, sorted, stack); - } - return sorted; - } - function recursiveTopoSort(current, toSort, sorted, stack) { - if (stack.has(current.name)) { - throw new Error("Cycle detected. This should never happen."); - } - if (sorted.find((element) => element.name === current.name)) { - return; - } - stack.add(current.name); - for (const dependency of current.dependencies) { - if (!sorted.find((element) => element.name === dependency)) { - const next = toSort.find((element) => element.name === dependency); - (0, assert_1.strict)(next); - recursiveTopoSort(next, toSort, sorted, stack); - } - } - sorted.push(current); - stack.delete(current.name); - } - function isOutsideDependency(identifierPath, bindingIdentifiers, functionPath) { - return ( - // We don't care about identifiers that were just declared. - identifierPath.isReferencedIdentifier() && // We don't care about identifiers that are bound in the scope. - !(identifierPath.node.name in bindingIdentifiers) && // This I don't exactly understand, but the function identifier itself isn't in `bindingIdentifiers`, - // but it return true on `hasOwnBinding`. - !functionPath.scope.hasOwnBinding(identifierPath.node.name) && // `hasReference` returns true for global identifiers, like `Object`, - // we don't want to include those. - functionPath.scope.hasReference(identifierPath.node.name) - ); } - function isWorkletizableClass(classPath, state) { - var _a; - const className = (_a = classPath.node.id) === null || _a === void 0 ? void 0 : _a.name; - const classNode = classPath.node; - if (!className) { - return false; - } - const isMarked = hasWorkletClassMarker(classNode.body); - const isMemoizedNode = state.classesToWorkletize.some((record) => record.node === classNode); - const isTopLevelMemoizedName = classPath.parentPath.isProgram() && state.classesToWorkletize.some((record) => record.name === className); - state.classesToWorkletize = state.classesToWorkletize.filter((record) => record.node !== classNode && record.name !== className); - const result = isMarked || isMemoizedNode || isTopLevelMemoizedName; - return result; + function shouldMockSourceMap() { + return process.env.REANIMATED_JEST_SHOULD_MOCK_SOURCE_MAP === "1"; } - } -}); - -// lib/contextObject.js -var require_contextObject = __commonJS({ - "lib/contextObject.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.contextObjectMarker = void 0; - exports2.processIfWorkletContextObject = processIfWorkletContextObject; - exports2.isContextObject = isContextObject; - var types_12 = require("@babel/types"); - exports2.contextObjectMarker = "__workletContextObject"; - function processIfWorkletContextObject(path, _state) { - if (!isContextObject(path.node)) { - return false; + function prependClosure(path, closureVariables, closureDeclaration) { + if (closureVariables.length === 0 || !(0, types_12.isProgram)(path.parent)) { + return; + } + if (!(0, types_12.isExpression)(path.node.body)) { + path.node.body.body.unshift(closureDeclaration); } - removeContextObjectMarker(path.node); - processWorkletContextObject(path.node); - return true; - } - function isContextObject(objectExpression) { - return objectExpression.properties.some((property) => (0, types_12.isObjectProperty)(property) && (0, types_12.isIdentifier)(property.key) && property.key.name === exports2.contextObjectMarker); } - function processWorkletContextObject(objectExpression) { - const workletObjectFactory = (0, types_12.functionExpression)(null, [], (0, types_12.blockStatement)([(0, types_12.returnStatement)((0, types_12.cloneNode)(objectExpression))], [(0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))])); - objectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)(`${exports2.contextObjectMarker}Factory`), workletObjectFactory)); + function prependRecursiveDeclaration(path) { + var _a; + if ((0, types_12.isProgram)(path.parent) && !(0, types_12.isArrowFunctionExpression)(path.node) && !(0, types_12.isObjectMethod)(path.node) && path.node.id && path.scope.parent) { + const hasRecursiveCalls = ((_a = path.scope.parent.bindings[path.node.id.name]) === null || _a === void 0 ? void 0 : _a.references) > 0; + if (hasRecursiveCalls) { + path.node.body.body.unshift((0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(path.node.id.name), (0, types_12.memberExpression)((0, types_12.thisExpression)(), (0, types_12.identifier)("_recur"))) + ])); + } + } } - function removeContextObjectMarker(objectExpression) { - objectExpression.properties = objectExpression.properties.filter((property) => !((0, types_12.isObjectProperty)(property) && (0, types_12.isIdentifier)(property.key) && property.key.name === exports2.contextObjectMarker)); + function getClosurePlugin(closureVariables) { + const closureDeclaration = (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.objectPattern)(closureVariables.map((variable) => (0, types_12.objectProperty)((0, types_12.identifier)(variable.name), (0, types_12.identifier)(variable.name), false, true))), (0, types_12.memberExpression)((0, types_12.thisExpression)(), (0, types_12.identifier)("__closure"))) + ]); + return { + visitor: { + "FunctionDeclaration|FunctionExpression|ArrowFunctionExpression|ObjectMethod": (path) => { + prependClosure(path, closureVariables, closureDeclaration); + prependRecursiveDeclaration(path); + } + } + }; } } }); -// lib/file.js -var require_file = __commonJS({ - "lib/file.js"(exports2) { +// lib/workletFactory.js +var require_workletFactory = __commonJS({ + "lib/workletFactory.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.processIfWorkletFile = processIfWorkletFile; - exports2.isImplicitContextObject = isImplicitContextObject; + exports2.makeWorkletFactory = makeWorkletFactory; + var generator_1 = __importDefault(require("@babel/generator")); var types_12 = require("@babel/types"); - var contextObject_12 = require_contextObject(); + var assert_1 = require("assert"); + var path_1 = require("path"); + var closure_1 = require_closure(); + var generate_1 = require_generate(); + var transform_1 = require_transform(); var types_2 = require_types(); - function processIfWorkletFile(path, state) { - if (!path.node.directives.some((functionDirective) => functionDirective.value.value === "worklet")) { - return false; - } - path.node.directives = path.node.directives.filter((functionDirective) => functionDirective.value.value !== "worklet"); - processWorkletFile(path, state); - return true; - } - function processWorkletFile(programPath, state) { - const statements = programPath.get("body"); - dehoistCommonJSExports(programPath.node); - statements.forEach((statement) => { - const candidatePath = getCandidate(statement); - processWorkletizableEntity(candidatePath, state); + var utils_1 = require_utils(); + var workletStringCode_1 = require_workletStringCode(); + var REAL_VERSION = require("../package.json").version; + var MOCK_VERSION = "x.y.z"; + function makeWorkletFactory(fun, state) { + var _a; + removeWorkletDirective(fun); + (0, assert_1.strict)(state.file.opts.filename, "[Reanimated] `state.file.opts.filename` is undefined."); + const codeObject = (0, generator_1.default)(fun.node, { + sourceMaps: true, + sourceFileName: state.file.opts.filename }); - } - function getCandidate(statementPath) { - if (statementPath.isExportNamedDeclaration() || statementPath.isExportDefaultDeclaration()) { - return statementPath.get("declaration"); + codeObject.code = "(" + (fun.isObjectMethod() ? "function " : "") + codeObject.code + "\n)"; + const transformed = (0, transform_1.workletTransformSync)(codeObject.code, { + extraPlugins: [...extraPlugins, ...(_a = state.opts.extraPlugins) !== null && _a !== void 0 ? _a : []], + extraPresets: state.opts.extraPresets, + filename: state.file.opts.filename, + ast: true, + babelrc: false, + configFile: false, + inputSourceMap: codeObject.map + }); + (0, assert_1.strict)(transformed, "[Reanimated] `transformed` is undefined."); + (0, assert_1.strict)(transformed.ast, "[Reanimated] `transformed.ast` is undefined."); + const { closureVariables, libraryBindingsToImport, relativeBindingsToImport } = (0, closure_1.getClosure)(fun, state); + const clone = (0, types_12.cloneNode)(fun.node); + const funExpression = (0, types_12.isBlockStatement)(clone.body) ? (0, types_12.functionExpression)(null, clone.params, clone.body, clone.generator, clone.async) : clone; + const { workletName, reactName } = makeWorkletName(fun, state); + let mutatedClosureVariables; + if (state.opts.bundleMode) { + mutatedClosureVariables = closureVariables.map((variable) => (0, types_12.cloneNode)(variable, true)); } else { - return statementPath; + mutatedClosureVariables = closureVariables; } - } - function processWorkletizableEntity(nodePath, state) { - var _a; - if ((0, types_2.isWorkletizableFunctionPath)(nodePath)) { - if (nodePath.isArrowFunctionExpression()) { - replaceImplicitReturnWithBlock(nodePath.node); + let [funString, sourceMapString] = (0, workletStringCode_1.buildWorkletString)(transformed.ast, state, mutatedClosureVariables, workletName, transformed.map); + (0, assert_1.strict)(funString, "[Reanimated] `funString` is undefined."); + const workletHash = hash(funString); + let lineOffset = 1; + if (closureVariables.length > 0) { + lineOffset -= closureVariables.length + 2; + } + const pathForStringDefinitions = fun.parentPath.isProgram() ? fun : fun.findParent((path) => { + var _a2, _b; + return (_b = (_a2 = path.parentPath) === null || _a2 === void 0 ? void 0 : _a2.isProgram()) !== null && _b !== void 0 ? _b : false; + }); + (0, assert_1.strict)(pathForStringDefinitions, "[Reanimated] `pathForStringDefinitions` is null."); + (0, assert_1.strict)(pathForStringDefinitions.parentPath, "[Reanimated] `pathForStringDefinitions.parentPath` is null."); + const initDataId = pathForStringDefinitions.parentPath.scope.generateUidIdentifier(`worklet_${workletHash}_init_data`); + const initDataObjectExpression = (0, types_12.objectExpression)([ + (0, types_12.objectProperty)((0, types_12.identifier)("code"), (0, types_12.stringLiteral)(funString)) + ]); + const shouldInjectLocation = !(0, utils_1.isRelease)(); + if (shouldInjectLocation) { + let location = state.file.opts.filename; + if (state.opts.relativeSourceLocation) { + location = (0, path_1.relative)(state.cwd, location); + sourceMapString = sourceMapString === null || sourceMapString === void 0 ? void 0 : sourceMapString.replace(state.file.opts.filename, location); } - appendWorkletDirective(nodePath.node.body); - } else if ((0, types_2.isWorkletizableObjectPath)(nodePath)) { - if (isImplicitContextObject(nodePath)) { - appendWorkletContextObjectMarker(nodePath.node); + initDataObjectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)("location"), (0, types_12.stringLiteral)(location))); + } + if (sourceMapString) { + initDataObjectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)("sourceMap"), (0, types_12.stringLiteral)(sourceMapString))); + } + const shouldIncludeInitData = !state.opts.omitNativeOnlyData; + if (shouldIncludeInitData && !state.opts.bundleMode) { + const initDataDeclaration = (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)(initDataId, initDataObjectExpression) + ]); + if (state.opts.limitInitDataHoisting) { + fun.getFunctionParent().node.body.body.unshift(initDataDeclaration); } else { - processWorkletAggregator(nodePath, state); - } - } else if (nodePath.isVariableDeclaration()) { - processVariableDeclaration(nodePath, state); - } else if (nodePath.isClassDeclaration()) { - appendWorkletClassMarker(nodePath.node.body); - if ((_a = nodePath.node.id) === null || _a === void 0 ? void 0 : _a.name) { - state.classesToWorkletize.push({ - node: nodePath.node, - name: nodePath.node.id.name - }); + pathForStringDefinitions.insertBefore(initDataDeclaration); } } - } - function processVariableDeclaration(variableDeclarationPath, state) { - const declarations = variableDeclarationPath.get("declarations"); - declarations.forEach((declaration) => { - const initPath = declaration.get("init"); - if (initPath.isExpression()) { - processWorkletizableEntity(initPath, state); - } - }); - } - function processWorkletAggregator(objectPath, state) { - const properties = objectPath.get("properties"); - properties.forEach((property) => { - if (property.isObjectMethod()) { - appendWorkletDirective(property.node.body); - } else if (property.isObjectProperty()) { - const valuePath = property.get("value"); - processWorkletizableEntity(valuePath, state); + (0, assert_1.strict)(!(0, types_12.isFunctionDeclaration)(funExpression), "[Reanimated] `funExpression` is a `FunctionDeclaration`."); + (0, assert_1.strict)(!(0, types_12.isObjectMethod)(funExpression), "[Reanimated] `funExpression` is an `ObjectMethod`."); + const statements = [ + (0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)(reactName), funExpression) + ]), + (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__closure"), false), (0, types_12.objectExpression)(closureVariables.map((variable) => !state.opts.bundleMode && variable.name.endsWith(types_2.workletClassFactorySuffix) ? (0, types_12.objectProperty)((0, types_12.identifier)(variable.name), (0, types_12.memberExpression)((0, types_12.identifier)(variable.name.slice(0, variable.name.length - types_2.workletClassFactorySuffix.length)), (0, types_12.identifier)(variable.name))) : (0, types_12.objectProperty)((0, types_12.cloneNode)(variable, true), (0, types_12.cloneNode)(variable, true), false, true))))), + (0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__workletHash"), false), (0, types_12.numericLiteral)(workletHash))) + ]; + const shouldInjectVersion = !(0, utils_1.isRelease)(); + if (shouldInjectVersion) { + statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__pluginVersion")), (0, types_12.stringLiteral)(shouldMockVersion() ? MOCK_VERSION : REAL_VERSION)))); + } + if (shouldIncludeInitData && !state.opts.bundleMode) { + statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__initData"), false), (0, types_12.cloneNode)(initDataId, true)))); + } + if (!(0, utils_1.isRelease)()) { + statements.unshift((0, types_12.variableDeclaration)("const", [ + (0, types_12.variableDeclarator)((0, types_12.identifier)("_e"), (0, types_12.arrayExpression)([ + (0, types_12.newExpression)((0, types_12.memberExpression)((0, types_12.identifier)("global"), (0, types_12.identifier)("Error")), []), + (0, types_12.numericLiteral)(lineOffset), + (0, types_12.numericLiteral)(-27) + // the placement of opening bracket after Exception in line that defined '_e' variable + ])) + ])); + statements.push((0, types_12.expressionStatement)((0, types_12.assignmentExpression)("=", (0, types_12.memberExpression)((0, types_12.identifier)(reactName), (0, types_12.identifier)("__stackDetails"), false), (0, types_12.identifier)("_e")))); + } + statements.push((0, types_12.returnStatement)((0, types_12.identifier)(reactName))); + const factoryParams = closureVariables.map((variableId) => { + const clonedId = (0, types_12.cloneNode)(variableId, true); + if (!state.opts.bundleMode && clonedId.name.endsWith(types_2.workletClassFactorySuffix)) { + clonedId.name = clonedId.name.slice(0, clonedId.name.length - types_2.workletClassFactorySuffix.length); } + return clonedId; }); - } - function replaceImplicitReturnWithBlock(path) { - if (!(0, types_12.isBlockStatement)(path.body)) { - path.body = (0, types_12.blockStatement)([(0, types_12.returnStatement)(path.body)]); - } - } - function appendWorkletDirective(node) { - if (!node.directives.some((functionDirective) => functionDirective.value.value === "worklet")) { - node.directives.push((0, types_12.directive)((0, types_12.directiveLiteral)("worklet"))); + if (shouldIncludeInitData && !state.opts.bundleMode) { + factoryParams.unshift((0, types_12.cloneNode)(initDataId, true)); } - } - function appendWorkletContextObjectMarker(objectExpression) { - if (objectExpression.properties.some((value) => (0, types_12.isObjectProperty)(value) && (0, types_12.isIdentifier)(value.key) && value.key.name === contextObject_12.contextObjectMarker)) { - return; + const factoryParamObjectPattern = (0, types_12.objectPattern)(factoryParams.map((param) => (0, types_12.objectProperty)((0, types_12.cloneNode)(param, true), (0, types_12.cloneNode)(param, true), false, true))); + const factory = (0, types_12.functionExpression)((0, types_12.identifier)(workletName + "Factory"), [factoryParamObjectPattern], (0, types_12.blockStatement)(statements)); + const factoryCallArgs = factoryParams.map((param) => (0, types_12.cloneNode)(param, true)); + const factoryCallParamPack = (0, types_12.objectExpression)(factoryCallArgs.map((param) => (0, types_12.objectProperty)((0, types_12.cloneNode)(param, true), (0, types_12.cloneNode)(param, true), false, true))); + if (state.opts.bundleMode) { + (0, generate_1.generateWorkletFile)(libraryBindingsToImport, relativeBindingsToImport, factory, workletHash, state); } - objectExpression.properties.push((0, types_12.objectProperty)((0, types_12.identifier)(`${contextObject_12.contextObjectMarker}`), (0, types_12.booleanLiteral)(true))); + factory.workletized = true; + return { factory, factoryCallParamPack, workletHash }; } - function isImplicitContextObject(path) { - const propertyPaths = path.get("properties"); - return propertyPaths.some((propertyPath) => { - if (!propertyPath.isObjectMethod()) { - return false; + function removeWorkletDirective(fun) { + fun.traverse({ + DirectiveLiteral(nodePath) { + if (nodePath.node.value === "worklet" && nodePath.getFunctionParent() === fun) { + nodePath.parentPath.remove(); + } } - return hasThisExpression(propertyPath); }); } - function hasThisExpression(path) { - let result = false; - path.traverse({ - ThisExpression(thisPath) { - result = true; - thisPath.stop(); - } - }); - return result; + function shouldMockVersion() { + return process.env.REANIMATED_JEST_SHOULD_MOCK_VERSION === "1"; } - function appendWorkletClassMarker(classBody) { - classBody.body.push((0, types_12.classProperty)((0, types_12.identifier)("__workletClass"), (0, types_12.booleanLiteral)(true))); + function hash(str) { + let i = str.length; + let hash1 = 5381; + let hash2 = 52711; + while (i--) { + const char = str.charCodeAt(i); + hash1 = hash1 * 33 ^ char; + hash2 = hash2 * 33 ^ char; + } + return (hash1 >>> 0) * 4096 + (hash2 >>> 0); } - function dehoistCommonJSExports(program) { - const statements = program.body; - let end = statements.length; - let current = 0; - while (current < end) { - const statement = statements[current]; - if (!isCommonJSExport(statement)) { - current++; - continue; + function makeWorkletName(fun, state) { + let source = "unknownFile"; + if (state.file.opts.filename) { + const filepath = state.file.opts.filename; + source = (0, path_1.basename)(filepath); + const splitFilepath = filepath.split("/"); + const nodeModulesIndex = splitFilepath.indexOf("node_modules"); + if (nodeModulesIndex !== -1) { + const libraryName = splitFilepath[nodeModulesIndex + 1]; + source = `${libraryName}_${source}`; } - const exportStatement = statements.splice(current, 1); - statements.push(...exportStatement); - end--; } + const suffix = `${source}${state.workletNumber++}`; + let reactName = ""; + if ((0, types_12.isObjectMethod)(fun.node) && (0, types_12.isIdentifier)(fun.node.key)) { + reactName = fun.node.key.name; + } else if (((0, types_12.isFunctionDeclaration)(fun.node) || (0, types_12.isFunctionExpression)(fun.node)) && (0, types_12.isIdentifier)(fun.node.id)) { + reactName = fun.node.id.name; + } + const workletName = reactName ? (0, types_12.toIdentifier)(`${reactName}_${suffix}`) : (0, types_12.toIdentifier)(suffix); + reactName = reactName || (0, types_12.toIdentifier)(suffix); + return { workletName, reactName }; } - function isCommonJSExport(statement) { - return (0, types_12.isExpressionStatement)(statement) && (0, types_12.isAssignmentExpression)(statement.expression) && (0, types_12.isMemberExpression)(statement.expression.left) && (0, types_12.isIdentifier)(statement.expression.left.object) && statement.expression.left.object.name === "exports"; - } + var extraPlugins = [ + require.resolve("@babel/plugin-transform-shorthand-properties"), + require.resolve("@babel/plugin-transform-arrow-functions"), + require.resolve("@babel/plugin-transform-optional-chaining"), + require.resolve("@babel/plugin-transform-nullish-coalescing-operator"), + [ + require.resolve("@babel/plugin-transform-template-literals"), + { loose: true } + ] + ]; } }); -// lib/inlineStylesWarning.js -var require_inlineStylesWarning = __commonJS({ - "lib/inlineStylesWarning.js"(exports2) { +// lib/workletFactoryCall.js +var require_workletFactoryCall = __commonJS({ + "lib/workletFactoryCall.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.processInlineStylesWarning = processInlineStylesWarning; + exports2.makeWorkletFactoryCall = makeWorkletFactoryCall; var types_12 = require("@babel/types"); - var assert_1 = require("assert"); - var utils_1 = require_utils(); - function generateInlineStylesWarning(path) { - return (0, types_12.callExpression)((0, types_12.arrowFunctionExpression)([], (0, types_12.blockStatement)([ - (0, types_12.expressionStatement)((0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.identifier)("console"), (0, types_12.identifier)("warn")), [ - (0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.callExpression)((0, types_12.identifier)("require"), [ - (0, types_12.stringLiteral)("react-native-reanimated") - ]), (0, types_12.identifier)("getUseOfValueInStyleWarning")), []) - ])), - (0, types_12.returnStatement)(path.node) - ])), []); - } - function processPropertyValueForInlineStylesWarning(path) { - if (path.isMemberExpression() && (0, types_12.isIdentifier)(path.node.property)) { - if (!path.node.computed && path.node.property.name === "value") { - path.replaceWith(generateInlineStylesWarning(path)); - } - } - } - function processTransformPropertyForInlineStylesWarning(path) { - if ((0, types_12.isArrayExpression)(path.node)) { - const elements = path.get("elements"); - (0, assert_1.strict)(Array.isArray(elements), "[Reanimated] `elements` should be an array."); - for (const element of elements) { - if (element.isObjectExpression()) { - processStyleObjectForInlineStylesWarning(element); - } - } - } - } - function processStyleObjectForInlineStylesWarning(path) { - const properties = path.get("properties"); - for (const property of properties) { - if (property.isObjectProperty()) { - const value = property.get("value"); - if ((0, types_12.isIdentifier)(property.node.key) && property.node.key.name === "transform") { - processTransformPropertyForInlineStylesWarning(value); - } else { - processPropertyValueForInlineStylesWarning(value); - } - } + var types_2 = require_types(); + var workletFactory_1 = require_workletFactory(); + function makeWorkletFactoryCall(path, state) { + const { factory, factoryCallParamPack, workletHash } = (0, workletFactory_1.makeWorkletFactory)(path, state); + let factoryCall; + if (state.opts.bundleMode) { + factoryCall = (0, types_12.callExpression)((0, types_12.memberExpression)((0, types_12.callExpression)((0, types_12.identifier)("require"), [ + (0, types_12.stringLiteral)(`react-native-worklets/${types_2.generatedWorkletsDir}/${workletHash}.js`) + ]), (0, types_12.identifier)("default")), [factoryCallParamPack]); + } else { + factoryCall = (0, types_12.callExpression)(factory, [factoryCallParamPack]); } + addStackTraceDataToWorkletFactory(path, factoryCall); + const replacement = factoryCall; + return replacement; } - function processInlineStylesWarning(path, state) { - if ((0, utils_1.isRelease)()) { - return; - } - if (state.opts.disableInlineStylesWarning) { - return; - } - if (path.node.name.name !== "style") { - return; - } - if (!(0, types_12.isJSXExpressionContainer)(path.node.value)) { - return; - } - const expression = path.get("value").get("expression"); - (0, assert_1.strict)(!Array.isArray(expression), "[Reanimated] `expression` should not be an array."); - if (expression.isArrayExpression()) { - const elements = expression.get("elements"); - (0, assert_1.strict)(Array.isArray(elements), "[Reanimated] `elements` should be an array."); - for (const element of elements) { - if (element.isObjectExpression()) { - processStyleObjectForInlineStylesWarning(element); - } - } - } else if (expression.isObjectExpression()) { - processStyleObjectForInlineStylesWarning(expression); + function addStackTraceDataToWorkletFactory(path, workletFactoryCall) { + const originalWorkletLocation = path.node.loc; + if (originalWorkletLocation) { + workletFactoryCall.callee.loc = { + filename: originalWorkletLocation.filename, + identifierName: originalWorkletLocation.identifierName, + start: originalWorkletLocation.start, + end: originalWorkletLocation.start + }; } } } }); -// lib/webOptimization.js -var require_webOptimization = __commonJS({ - "lib/webOptimization.js"(exports2) { +// lib/workletSubstitution.js +var require_workletSubstitution = __commonJS({ + "lib/workletSubstitution.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.substituteWebCallExpression = substituteWebCallExpression; + exports2.processIfWithWorkletDirective = processIfWithWorkletDirective; + exports2.processWorklet = processWorklet; + exports2.substituteObjectMethodWithObjectProperty = substituteObjectMethodWithObjectProperty; var types_12 = require("@babel/types"); - function substituteWebCallExpression(path) { - const callee = path.node.callee; - if ((0, types_12.isIdentifier)(callee)) { - const name = callee.name; - if (name === "isWeb" || name === "shouldBeUseWeb") { - path.replaceWith((0, types_12.booleanLiteral)(true)); + var types_2 = require_types(); + var utils_1 = require_utils(); + var workletFactoryCall_1 = require_workletFactoryCall(); + function processIfWithWorkletDirective(path, state) { + if (!(0, types_12.isBlockStatement)(path.node.body)) { + return false; + } + if (!hasWorkletDirective(path.node.body.directives)) { + return false; + } + processWorklet(path, state); + return true; + } + function processWorklet(path, state) { + path.traverse({ + // @ts-expect-error TypeScript doesn't like this syntax here. + [types_2.WorkletizableFunction](subPath, passedState) { + processIfWithWorkletDirective(subPath, passedState); } + }, state); + const workletFactoryCall = (0, workletFactoryCall_1.makeWorkletFactoryCall)(path, state); + substituteWorkletWithWorkletFactoryCall(path, workletFactoryCall); + path.scope.getProgramParent().crawl(); + } + function hasWorkletDirective(directives) { + return directives.some((directive) => (0, types_12.isDirectiveLiteral)(directive.value) && directive.value.value === "worklet"); + } + function substituteWorkletWithWorkletFactoryCall(path, workletFactoryCall) { + var _a; + if (path.isObjectMethod()) { + substituteObjectMethodWithObjectProperty(path, workletFactoryCall); + } else { + const name = "id" in path.node ? (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name : void 0; + (0, utils_1.replaceWithFactoryCall)(path, name, workletFactoryCall); } } + function substituteObjectMethodWithObjectProperty(path, workletFactoryCall) { + const replacement = (0, types_12.objectProperty)(path.node.key, workletFactoryCall); + path.replaceWith(replacement); + } } }); // lib/plugin.js Object.defineProperty(exports, "__esModule", { value: true }); +exports.getAutoworkletizationMicroPlugin = getAutoworkletizationMicroPlugin; var autoworkletization_1 = require_autoworkletization(); var bundleMode_1 = require_bundleMode(); var class_1 = require_class(); @@ -1833,28 +1827,18 @@ var types_1 = require_types(); var webOptimization_1 = require_webOptimization(); var workletSubstitution_1 = require_workletSubstitution(); module.exports = function WorkletsBabelPlugin() { - function runWithTaggedExceptions(fun) { - try { - fun(); - } catch (e) { - const error = e; - error.message = `[Worklets] Babel plugin exception: ${error.message}`; - error.name = "WorkletsBabelPluginError"; - throw error; - } - } return { name: "worklets", pre() { runWithTaggedExceptions(() => { (0, globals_1.initializeState)(this); + this.file.path.traverse(getAutoworkletizationMicroPlugin(), this); }); }, visitor: { CallExpression: { enter(path, state) { runWithTaggedExceptions(() => { - (0, autoworkletization_1.processCalleesAutoworkletizableCallbacks)(path, state); if (state.opts.substituteWebPlatformChecks) { (0, webOptimization_1.substituteWebCallExpression)(path); } @@ -1863,7 +1847,9 @@ module.exports = function WorkletsBabelPlugin() { }, [types_1.WorkletizableFunction]: { enter(path, state) { - runWithTaggedExceptions(() => (0, workletSubstitution_1.processIfWithWorkletDirective)(path, state) || (0, autoworkletization_1.processIfAutoworkletizableCallback)(path, state)); + runWithTaggedExceptions(() => { + (0, workletSubstitution_1.processIfWithWorkletDirective)(path, state); + }); } }, ObjectExpression: { @@ -1905,4 +1891,28 @@ module.exports = function WorkletsBabelPlugin() { } }; }; +function getAutoworkletizationMicroPlugin() { + return { + CallExpression: { + enter(path, state) { + (0, autoworkletization_1.addWorkletDirectivesToCallbacks)(path, state); + } + }, + [types_1.WorkletizableFunction]: { + enter(path) { + (0, autoworkletization_1.addWorkletDirectiveToKnownCallback)(path); + } + } + }; +} +function runWithTaggedExceptions(fun) { + try { + fun(); + } catch (e) { + const error = e; + error.message = `[Worklets] Babel plugin exception: ${error.message}`; + error.name = "WorkletsBabelPluginError"; + throw error; + } +} //# sourceMappingURL=index.js.map diff --git a/packages/react-native-worklets/plugin/package.json b/packages/react-native-worklets/plugin/package.json index 73c7d57b29c9..38901e54f4e4 100644 --- a/packages/react-native-worklets/plugin/package.json +++ b/packages/react-native-worklets/plugin/package.json @@ -12,6 +12,7 @@ "@babel/types": "7.28.4", "@types/node": "24.0.14", "@typescript-eslint/parser": "8.37.0", + "babel-plugin-react-compiler": "1.0.0", "esbuild": "0.25.10", "eslint": "9.37.0", "prettier": "3.6.2", diff --git a/packages/react-native-worklets/plugin/src/autoworkletization.ts b/packages/react-native-worklets/plugin/src/autoworkletization.ts index fa87c0b8429b..ce618ba98cbf 100644 --- a/packages/react-native-worklets/plugin/src/autoworkletization.ts +++ b/packages/react-native-worklets/plugin/src/autoworkletization.ts @@ -1,7 +1,9 @@ import type { NodePath } from '@babel/core'; -import type { CallExpression } from '@babel/types'; +import type { BlockStatement, CallExpression } from '@babel/types'; import { isSequenceExpression, isV8IntrinsicIdentifier } from '@babel/types'; +import { appendWorkletDirective, replaceImplicitReturnWithBlock } from './file'; +import { findWorklet } from './findWorklet'; import { gestureHandlerBuilderMethods, gestureHandlerObjectHooks, @@ -9,9 +11,13 @@ import { isGestureObjectEventCallbackMethod, } from './gestureHandlerAutoworkletization'; import { isLayoutAnimationCallback } from './layoutAnimationAutoworkletization'; -import { tryProcessingNode } from './objectWorklets'; -import type { WorkletizableFunction, WorkletsPluginPass } from './types'; -import { processWorklet } from './workletSubstitution'; +import { + isWorkletizableFunctionPath, + isWorkletizableObjectPath, + type WorkletizableFunction, + type WorkletizableObject, + type WorkletsPluginPass, +} from './types'; const reanimatedObjectHooks = new Set([ 'useAnimatedScrollHandler', @@ -72,19 +78,15 @@ const reanimatedFunctionArgsToWorkletize = new Map([ ...Array.from(gestureHandlerBuilderMethods).map((name) => [name, [0]]), ] as [string, number[]][]); -/** @returns `true` if the function was workletized, `false` otherwise. */ -export function processIfAutoworkletizableCallback( - path: NodePath, - state: WorkletsPluginPass -): boolean { +export function addWorkletDirectiveToKnownCallback( + path: NodePath +): void { if (isGestureHandlerEventCallback(path) || isLayoutAnimationCallback(path)) { - processWorklet(path, state); - return true; + addWorkletDirective(path); } - return false; } -export function processCalleesAutoworkletizableCallbacks( +export function addWorkletDirectivesToCallbacks( path: NodePath, state: WorkletsPluginPass ): void { @@ -112,23 +114,86 @@ export function processCalleesAutoworkletizableCallbacks( .get('arguments') .filter((_, index) => argIndices.includes(index)); - processArgs(args, state, acceptWorkletizableFunction, acceptObject); + addWorkletDirectiveToArgs( + args, + state, + acceptWorkletizableFunction, + acceptObject + ); } else if ( !isV8IntrinsicIdentifier(callee) && isGestureObjectEventCallbackMethod(callee) ) { const args = path.get('arguments'); - processArgs(args, state, true, true); + addWorkletDirectiveToArgs(args, state, true, true); } } -function processArgs( +function addWorkletDirectiveToArgs( args: NodePath[], state: WorkletsPluginPass, acceptWorkletizableFunction: boolean, acceptObject: boolean ): void { args.forEach((arg) => { - tryProcessingNode(arg, state, acceptWorkletizableFunction, acceptObject); + addWorkletDirectiveToNode( + arg, + state, + acceptWorkletizableFunction, + acceptObject + ); }); } + +function addWorkletDirectiveToNode( + arg: NodePath, + state: WorkletsPluginPass, + acceptWorkletizableFunction: boolean, + acceptObject: boolean +): void { + const maybeWorklet = findWorklet( + arg, + state, + acceptWorkletizableFunction, + acceptObject + ); + if (!maybeWorklet) { + return; + } + if (isWorkletizableFunctionPath(maybeWorklet)) { + addWorkletDirective(maybeWorklet); + } else if (isWorkletizableObjectPath(maybeWorklet)) { + addWorkletDirectiveToMethods(maybeWorklet, state); + } +} + +function addWorkletDirectiveToMethods( + path: NodePath, + state: WorkletsPluginPass +): void { + const properties = path.get('properties'); + for (const property of properties) { + if (property.isObjectMethod()) { + addWorkletDirective(property); + } else if (property.isObjectProperty()) { + const value = property.get('value'); + addWorkletDirectiveToNode( + value, + state, + true, // acceptWorkletizableFunction + false // acceptObject + ); + } else { + throw new Error( + `[Reanimated] '${property.type}' as to-be workletized argument is not supported for object hooks.` + ); + } + } +} + +function addWorkletDirective(path: NodePath): void { + if (path.isArrowFunctionExpression()) { + replaceImplicitReturnWithBlock(path.node); + } + appendWorkletDirective(path.node.body as BlockStatement); +} diff --git a/packages/react-native-worklets/plugin/src/file.ts b/packages/react-native-worklets/plugin/src/file.ts index e0f41bb4d517..c763c86827d0 100644 --- a/packages/react-native-worklets/plugin/src/file.ts +++ b/packages/react-native-worklets/plugin/src/file.ts @@ -144,13 +144,13 @@ function processWorkletAggregator( * This is necessary because the worklet directive is only allowed on block * statements. */ -function replaceImplicitReturnWithBlock(path: ArrowFunctionExpression) { +export function replaceImplicitReturnWithBlock(path: ArrowFunctionExpression) { if (!isBlockStatement(path.body)) { path.body = blockStatement([returnStatement(path.body)]); } } -function appendWorkletDirective(node: BlockStatement) { +export function appendWorkletDirective(node: BlockStatement) { if ( !node.directives.some( (functionDirective) => functionDirective.value.value === 'worklet' diff --git a/packages/react-native-worklets/plugin/src/objectWorklets.ts b/packages/react-native-worklets/plugin/src/objectWorklets.ts deleted file mode 100644 index fd615a042f92..000000000000 --- a/packages/react-native-worklets/plugin/src/objectWorklets.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { NodePath } from '@babel/core'; - -import { findWorklet } from './findWorklet'; -import type { WorkletizableObject, WorkletsPluginPass } from './types'; -import { - isWorkletizableFunctionPath, - isWorkletizableObjectPath, -} from './types'; -import { processWorklet } from './workletSubstitution'; - -export function tryProcessingNode( - arg: NodePath, - state: WorkletsPluginPass, - acceptWorkletizableFunction: boolean, - acceptObject: boolean -) { - const maybeWorklet = findWorklet( - arg, - state, - acceptWorkletizableFunction, - acceptObject - ); - // @ts-expect-error There's no need to workletize - // inside an already workletized function. - if (!maybeWorklet || maybeWorklet.getFunctionParent()?.node.workletized) { - return; - } - if (isWorkletizableFunctionPath(maybeWorklet)) { - processWorklet(maybeWorklet, state); - } else if (isWorkletizableObjectPath(maybeWorklet)) { - processWorkletizableObject(maybeWorklet, state); - } -} - -export function processWorkletizableObject( - path: NodePath, - state: WorkletsPluginPass -): void { - const properties = path.get('properties'); - for (const property of properties) { - if (property.isObjectMethod()) { - processWorklet(property, state); - } else if (property.isObjectProperty()) { - const value = property.get('value'); - tryProcessingNode( - value, - state, - true, // acceptWorkletizableFunction - false // acceptObject - ); - } else { - throw new Error( - `[Reanimated] '${property.type}' as to-be workletized argument is not supported for object hooks.` - ); - } - } -} diff --git a/packages/react-native-worklets/plugin/src/plugin.ts b/packages/react-native-worklets/plugin/src/plugin.ts index f9b9701a0130..1a03c2bca800 100644 --- a/packages/react-native-worklets/plugin/src/plugin.ts +++ b/packages/react-native-worklets/plugin/src/plugin.ts @@ -9,8 +9,8 @@ import type { } from '@babel/types'; import { - processCalleesAutoworkletizableCallbacks, - processIfAutoworkletizableCallback, + addWorkletDirectivesToCallbacks, + addWorkletDirectiveToKnownCallback, } from './autoworkletization'; import { toggleBundleMode } from './bundleMode'; import { processIfWorkletClass } from './class'; @@ -24,30 +24,25 @@ import { substituteWebCallExpression } from './webOptimization'; import { processIfWithWorkletDirective } from './workletSubstitution'; module.exports = function WorkletsBabelPlugin(): PluginItem { - function runWithTaggedExceptions(fun: () => void) { - try { - fun(); - } catch (e) { - const error = e as Error; - error.message = `[Worklets] Babel plugin exception: ${error.message}`; - error.name = 'WorkletsBabelPluginError'; - throw error; - } - } - return { name: 'worklets', pre(this: WorkletsPluginPass) { runWithTaggedExceptions(() => { initializeState(this); + /** + * We run the micro-plugin in the `pre` step of the whole pipeline to + * add all 'worklet' directives before React Compiler kicks in. + * + * As of now React Compiler begins its work on `Program` visitor. + */ + this.file.path.traverse(getAutoworkletizationMicroPlugin(), this); }); }, visitor: { CallExpression: { enter(path: NodePath, state: WorkletsPluginPass) { runWithTaggedExceptions(() => { - processCalleesAutoworkletizableCallbacks(path, state); if (state.opts.substituteWebPlatformChecks) { substituteWebCallExpression(path); } @@ -59,11 +54,9 @@ module.exports = function WorkletsBabelPlugin(): PluginItem { path: NodePath, state: WorkletsPluginPass ) { - runWithTaggedExceptions( - () => - processIfWithWorkletDirective(path, state) || - processIfAutoworkletizableCallback(path, state) - ); + runWithTaggedExceptions(() => { + processIfWithWorkletDirective(path, state); + }); }, }, ObjectExpression: { @@ -107,3 +100,31 @@ module.exports = function WorkletsBabelPlugin(): PluginItem { }, }; }; + +export function getAutoworkletizationMicroPlugin() { + return { + CallExpression: { + enter(path: NodePath, state: WorkletsPluginPass) { + addWorkletDirectivesToCallbacks(path, state); + }, + }, + [WorkletizableFunction]: { + enter(path: NodePath) { + addWorkletDirectiveToKnownCallback( + path as NodePath + ); + }, + }, + }; +} + +function runWithTaggedExceptions(fun: () => void) { + try { + fun(); + } catch (e) { + const error = e as Error; + error.message = `[Worklets] Babel plugin exception: ${error.message}`; + error.name = 'WorkletsBabelPluginError'; + throw error; + } +} diff --git a/yarn.lock b/yarn.lock index 21231a112f9d..c35bba18f55a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11855,7 +11855,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-react-compiler@npm:^1.0.0": +"babel-plugin-react-compiler@npm:1.0.0, babel-plugin-react-compiler@npm:^1.0.0": version: 1.0.0 resolution: "babel-plugin-react-compiler@npm:1.0.0" dependencies: @@ -12243,6 +12243,7 @@ __metadata: "@babel/types": "npm:7.28.4" "@types/node": "npm:24.0.14" "@typescript-eslint/parser": "npm:8.37.0" + babel-plugin-react-compiler: "npm:1.0.0" esbuild: "npm:0.25.10" eslint: "npm:9.37.0" prettier: "npm:3.6.2"