@rn-org/react-native-thread 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,6 +19,7 @@ Run JavaScript on real background threads in React Native — no Workers, no Wor
19
19
  - [destroyThread](#destroythread)
20
20
  - [onMessage](#onmessage)
21
21
  - [ThreadHandle](#threadhandle)
22
+ - [ThreadError](#threaderror)
22
23
  - [ThreadInfo](#threadinfo)
23
24
  - [ThreadTask](#threadtask)
24
25
  - [Thread globals](#thread-globals)
@@ -26,6 +27,12 @@ Run JavaScript on real background threads in React Native — no Workers, no Wor
26
27
  - [console](#console)
27
28
  - [`__params__`](#__params__)
28
29
  - [Hermes & Babel plugin](#hermes--babel-plugin-deep-dive)
30
+ - [Task function](#task-function-first-argument)
31
+ - [Function params](#function-params-second-argument)
32
+ - [Cross-module imports](#cross-module-imports)
33
+ - [Supported call sites](#supported-call-sites)
34
+ - [What the plugin captures](#what-the-plugin-captures-in-params)
35
+ - [Limitations](#limitations)
29
36
  - [Constraints](#constraints)
30
37
  - [Contributing](#contributing)
31
38
  - [License](#license)
@@ -38,8 +45,11 @@ Run JavaScript on real background threads in React Native — no Workers, no Wor
38
45
  - **Unlimited threads** — create as many threads as you need; each is isolated.
39
46
  - **Shared thread** (`runOnJS`) — fire-and-forget tasks on a single persistent background thread; no teardown required.
40
47
  - **Per-thread message passing** — call `resolveThreadMessage(data)` from any thread, receive it on the main thread with `onMessage` (callback or `await`).
41
- - **Parameter injection** — pass a JSON-serialisable value from the main thread into the background function as a typed argument `(args) => { ... }`.
48
+ - **Parameter injection** — pass values from the main thread into the background function as a typed argument `(args) => { ... }`. Supports primitives, objects, arrays, **and functions**.
49
+ - **Function params** — pass functions (including imported ones) alongside plain data in the params object. The Babel plugin extracts their source at compile time, captures closed-over variables transitively, and downlevels to ES5 for Rhino compatibility.
50
+ - **Cross-module function params** — functions imported from other files (e.g. `import { compute } from './math'`) are automatically resolved and inlined by the Babel plugin.
42
51
  - **Named threads** — give threads friendly names; list or destroy them by name.
52
+ - **Error handling** — thread exceptions are automatically caught and forwarded to the main thread. Use `onError` or `.catch()` on the `onMessage()` promise.
43
53
  - **Full `console` support** — `console.log/info/warn/error/debug` work inside threads and appear in Logcat / Xcode logs.
44
54
  - **Hermes-safe** — ships a Babel plugin that extracts function source at compile time so Hermes bytecode never breaks serialisation.
45
55
  - **New Architecture only** — built on the TurboModule / Codegen pipeline.
@@ -77,7 +87,14 @@ cd ios && pod install
77
87
 
78
88
  ## Babel plugin (required for Hermes)
79
89
 
80
- Hermes compiles your JS to bytecode at build time. That means `fn.toString()` at runtime returns a placeholder (`"function () { [bytecode] }"`) instead of source code. The library includes a Babel plugin that extracts arrow-function / function-expression source at **compile time** and replaces it with a string literal before Hermes ever sees it.
90
+ Hermes compiles your JS to bytecode at build time. That means `fn.toString()` at runtime returns a placeholder (`"function () { [bytecode] }"`) instead of source code. The library includes a Babel plugin that:
91
+
92
+ 1. Extracts the **task function** (first argument) source at compile time and replaces it with a string literal.
93
+ 2. Detects **function-valued properties** in the params object (second argument) and inlines their source.
94
+ 3. **Captures closed-over variables** transitively — if a function references outer `const`/`let`/`var` bindings (literals or other functions), those are bundled into a self-contained IIFE.
95
+ 4. **Resolves cross-module imports** — functions imported from relative paths (e.g. `import { fn } from './utils'`) are read from disk and inlined.
96
+ 5. **Downlevels ES6+ to ES5** — arrow functions, `let`/`const`, template literals, etc. are transpiled for Rhino (Android's JS engine).
97
+ 6. **Strips TypeScript** annotations automatically when the source file is `.ts` or `.tsx`.
81
98
 
82
99
  Add the plugin to your app's `babel.config.js`:
83
100
 
@@ -109,7 +126,7 @@ runOnJS((args) => {
109
126
  // ── 2. Create a named, persistent thread ────────────────────────────────────
110
127
  const thread = createThread('MyThread');
111
128
 
112
- // Send work + params
129
+ // Send work + params (including plain values)
113
130
  thread.run(
114
131
  (args) => {
115
132
  var result = 0;
@@ -119,6 +136,40 @@ thread.run(
119
136
  { limit: 1_000_000 }
120
137
  );
121
138
 
139
+ // ── 2b. Pass functions as params ────────────────────────────────────────────
140
+ function multiply(a, b) {
141
+ return a * b;
142
+ }
143
+
144
+ thread.run(
145
+ (args) => {
146
+ const result = args.multiply(args.x, args.y);
147
+ resolveThreadMessage(result);
148
+ },
149
+ { x: 6, y: 7, multiply }
150
+ );
151
+
152
+ // Functions that close over outer variables work too:
153
+ const factor = 10;
154
+ const scale = (n) => n * factor;
155
+
156
+ thread.run(
157
+ (args) => {
158
+ resolveThreadMessage(args.scale(5)); // 50
159
+ },
160
+ { scale }
161
+ );
162
+
163
+ // Imported functions are also supported:
164
+ import { checkEvenOdd } from './utils';
165
+
166
+ thread.run(
167
+ (args) => {
168
+ resolveThreadMessage(args.checkEvenOdd(args.num));
169
+ },
170
+ { num: 42, checkEvenOdd }
171
+ );
172
+
122
173
  // Option A — callback
123
174
  const unsubscribe = thread.onMessage((data) => {
124
175
  console.log('Result from thread:', data);
@@ -262,10 +313,12 @@ type ThreadHandle = {
262
313
  readonly id: number;
263
314
  readonly name: string;
264
315
  run(task: ThreadTask, params?: unknown): void;
265
- /** Callback variant — fires on every message. Returns unsubscribe fn. */
316
+ /** Callback variant — fires on every successful message. Returns unsubscribe fn. */
266
317
  onMessage(handler: (data: unknown) => void): () => void;
267
- /** Promise variant — resolves on the next message from this thread. */
318
+ /** Promise variant — resolves on success, rejects on thread error. */
268
319
  onMessage(): Promise<unknown>;
320
+ /** Subscribe to errors thrown inside this thread. Returns unsubscribe fn. */
321
+ onError(handler: (error: ThreadError) => void): () => void;
269
322
  destroy(): void;
270
323
  };
271
324
  ```
@@ -275,12 +328,26 @@ type ThreadHandle = {
275
328
  | `id` | Numeric ID assigned by the native layer. |
276
329
  | `name` | Display name provided at creation (or the default `RNThread-<id>`). |
277
330
  | `run(task, params?)` | Execute `task` on this thread. `params` is passed as the first argument to the function. Can be called multiple times. |
278
- | `onMessage(handler)` | Subscribe to `resolveThreadMessage` output from **this thread only**. Returns an unsubscribe function. |
279
- | `onMessage()` | Returns a `Promise` that resolves with the next message from **this thread only**, then auto-unsubscribes. |
331
+ | `onMessage(handler)` | Subscribe to `resolveThreadMessage` output from **this thread only**. Error messages are filtered out. Returns an unsubscribe function. |
332
+ | `onMessage()` | Returns a `Promise` that resolves with the next message from **this thread only**, or **rejects** with an `Error` if the thread threw. Auto-unsubscribes. |
333
+ | `onError(handler)` | Subscribe to uncaught exceptions from **this thread only**. The handler receives a `ThreadError` with `message` and `stack`. Returns an unsubscribe function. |
280
334
  | `destroy()` | Shut down the thread and remove it from the registry. Equivalent to calling `destroyThread(handle.id)`. |
281
335
 
282
336
  ---
283
337
 
338
+ ### `ThreadError`
339
+
340
+ ```ts
341
+ type ThreadError = {
342
+ message: string;
343
+ stack: string;
344
+ };
345
+ ```
346
+
347
+ Received by `ThreadHandle.onError` when a thread throws an uncaught exception. The `message` is the error's `.message` and `stack` is the `.stack` trace from the thread engine.
348
+
349
+ ---
350
+
284
351
  ### `ThreadInfo`
285
352
 
286
353
  ```ts
@@ -398,35 +465,87 @@ Because this library must *serialise* functions to strings and send them to a se
398
465
 
399
466
  ### The solution
400
467
 
401
- The included Babel plugin runs at **compile time** — before Hermes touches the code — and replaces arrow-function / function-expression arguments to the thread API with string literals containing the original source wrapped as an IIFE:
468
+ The included Babel plugin runs at **compile time** — before Hermes touches the code — and transforms both the task function and function-valued params.
469
+
470
+ #### Task function (first argument)
471
+
472
+ Arrow functions and function expressions are replaced with an ES5-downleveled string literal wrapped as an IIFE:
402
473
 
403
474
  ```js
404
475
  // Input (your source)
405
476
  thread.run((args) => {
406
- resolveThreadMessage(args.greeting);
407
- }, { greeting: 'hello' });
477
+ resolveThreadMessage(`${args.num} is great`);
478
+ }, { num: 42 });
408
479
 
409
480
  // Output (what Hermes compiles)
410
- thread.run("((args) => {\n resolveThreadMessage(args.greeting);\n})(__params__)", { greeting: 'hello' });
481
+ thread.run("((function (args) {\n resolveThreadMessage(\"\".concat(args.num, \" is great\"));\n}))(__params__)", { num: 42 });
411
482
  ```
412
483
 
413
- The second `params` argument is left untouched; only the first (function) argument is transformed.
484
+ #### Function params (second argument)
485
+
486
+ Functions passed inside the params object are detected, extracted, and tagged with `{ __rnThreadFn: "<source>" }`. The runtime serializer emits the source directly into the thread code.
487
+
488
+ ```js
489
+ // Input
490
+ const b = 3;
491
+ const add = (x) => x + b;
492
+ function multiply(a) {
493
+ return add(a) * 2;
494
+ }
495
+ thread.run(fn, { multiply });
496
+
497
+ // Output — transitive closures are captured in a self-contained IIFE
498
+ thread.run(fn, {
499
+ multiply: {
500
+ __rnThreadFn: "(function(){ var b = 3;\nvar add = function(x) { return x + b; };\nreturn function multiply(a) { return add(a) * 2; };})()"
501
+ }
502
+ });
503
+ ```
504
+
505
+ #### Cross-module imports
506
+
507
+ Functions imported from relative paths are resolved from disk, parsed, and inlined:
508
+
509
+ ```js
510
+ // utils.ts
511
+ export function checkEvenOdd(num: number): string {
512
+ return num % 2 === 0 ? 'Even' : 'Odd';
513
+ }
514
+
515
+ // App.tsx
516
+ import { checkEvenOdd } from './utils';
517
+ thread.run(fn, { checkEvenOdd });
518
+ // → checkEvenOdd is inlined with TypeScript stripped and ES5-downleveled
519
+ ```
414
520
 
415
521
  ### Supported call sites
416
522
 
417
- | Pattern | Transformed |
523
+ | Pattern | Task transformed | Params transformed |
524
+ |---|---|---|
525
+ | `runOnJS(() => { ... }, { fn })` | Yes | Yes |
526
+ | `runOnNewJS(() => { ... }, { fn })` | Yes | Yes |
527
+ | `anyHandle.run(() => { ... }, { fn })` | Yes | Yes |
528
+ | Raw code string `run("...", { fn })` | No (already a string) | Yes |
529
+
530
+ ### What the plugin captures in params
531
+
532
+ | Value type | Captured |
418
533
  |---|---|
419
- | `runOnJS(() => { ... })` | Yes |
420
- | `runOnNewJS(() => { ... })` | Yes |
421
- | `anyHandle.run(() => { ... })` | Yes |
422
- | Raw code string `run("...")` | No (already a string) |
534
+ | Inline arrow / function expression | Yes |
535
+ | Reference to local `function` declaration | Yes |
536
+ | Reference to local `const fn = () => ...` | Yes |
537
+ | Imported function (`import { fn } from './mod'`) | Yes (relative paths only) |
538
+ | Closed-over `const`/`let`/`var` with literal init | Yes (transitively) |
539
+ | Closed-over function references | Yes (transitively) |
540
+ | Runtime-computed values, `Map`, `Set`, classes | No — pass as plain params |
423
541
 
424
542
  ### Limitations
425
543
 
426
- - Thread functions are **self-contained**: they run in an isolated JS engine with no access to the outer closure, imported modules, or the React tree.
427
- - All values must be passed explicitly via the `args` parameter, `__params__`, or `resolveThreadMessage`.
544
+ - **Captured closures must be statically resolvable**: only variables initialized with literals and functions (local or imported) are captured. Runtime-computed values (e.g. `const x = fetchValue()`) must be passed explicitly as params.
545
+ - **Cross-module resolution** only follows **relative imports** (e.g. `'./utils'`). Package imports (e.g. `'lodash'`) are not resolved.
428
546
  - Thread function bodies must be **ASCII-safe**: Rhino (Android) does not support non-ASCII identifier characters in source mode.
429
- - The `params` value must be **JSON-serialisable**: functions, `undefined`, `Map`, `Set`, etc. are not supported.
547
+ - `undefined`, `Map`, `Set`, and class instances are not serialisable as param values — use plain objects, arrays, strings, numbers, booleans, or `null`.
548
+ - Thread functions run in an **isolated JS engine** with no access to the React tree, native modules, or the main thread's global scope.
430
549
 
431
550
  ---
432
551
 
@@ -434,9 +553,11 @@ The second `params` argument is left untouched; only the first (function) argume
434
553
 
435
554
  | Constraint | Reason |
436
555
  |---|---|
437
- | Functions are closure-isolated | They run in a completely separate JS engine |
438
- | `params` must be JSON-serialisable | Serialised and passed as a function argument |
556
+ | Thread functions run in isolation | They execute in a completely separate JS engine |
557
+ | Function params must be statically resolvable | The Babel plugin extracts source at compile time |
558
+ | Non-function `params` must be JSON-serialisable | Serialised via `JSON.stringify` at runtime |
439
559
  | `resolveThreadMessage` payload must be JSON-serialisable | Transported as a JSON string over the bridge |
560
+ | Cross-module resolution is relative-only | The plugin reads files from disk using the import path |
440
561
  | Function body must be ASCII-safe | Rhino parser limitation |
441
562
  | New Architecture required | TurboModule / Codegen only; no bridge fallback |
442
563
 
@@ -1,19 +1,339 @@
1
1
  'use strict';
2
2
 
3
+ const nodePath = require('path');
4
+ const fs = require('fs');
3
5
  const TOP_LEVEL_API = new Set(['runOnJS', 'runOnNewJS']);
4
6
  const METHOD_API = new Set(['run']);
7
+ const SKIP_KEYS = new Set(['type', 'start', 'end', 'loc', 'leadingComments', 'trailingComments', 'innerComments', 'extra', 'range']);
5
8
  module.exports = function reactNativeThreadPlugin({
6
- types: t
9
+ types: t,
10
+ ...babel
7
11
  }) {
12
+ const parser = babel.parser && babel.parser || require('@babel/parser');
13
+
14
+ // ── Cross-module import resolution ─────────────────────────────
15
+
16
+ const RESOLVE_EXTS = ['.ts', '.tsx', '.js', '.jsx', ''];
17
+
18
+ /**
19
+ * Given a relative import source (e.g. './Utility') and the
20
+ * filename of the importing file, try to resolve, read, parse,
21
+ * and extract the source of the named export `exportName`.
22
+ *
23
+ * Returns the raw function source string or null.
24
+ */
25
+ function resolveImportedFnSource(importSource, exportName, state) {
26
+ const currentFile = state.filename || state.file.opts.filename;
27
+ if (!currentFile || !importSource.startsWith('.')) return null;
28
+ const dir = nodePath.dirname(currentFile);
29
+ let resolvedFile = null;
30
+ for (const ext of RESOLVE_EXTS) {
31
+ const candidate = nodePath.resolve(dir, importSource + ext);
32
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
33
+ resolvedFile = candidate;
34
+ break;
35
+ }
36
+ }
37
+ if (!resolvedFile) {
38
+ // Try as directory with index file
39
+ for (const ext of RESOLVE_EXTS) {
40
+ const candidate = nodePath.resolve(dir, importSource, 'index' + ext);
41
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
42
+ resolvedFile = candidate;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ if (!resolvedFile) return null;
48
+ let source;
49
+ try {
50
+ source = fs.readFileSync(resolvedFile, 'utf8');
51
+ } catch {
52
+ return null;
53
+ }
54
+ let ast;
55
+ try {
56
+ ast = parser.parse(source, {
57
+ sourceType: 'module',
58
+ plugins: ['typescript', 'jsx']
59
+ });
60
+ } catch {
61
+ return null;
62
+ }
63
+
64
+ // Walk top-level statements to find the exported function
65
+ for (const stmt of ast.program.body) {
66
+ // export function foo() { ... }
67
+ if (t.isExportNamedDeclaration(stmt) && stmt.declaration) {
68
+ if (t.isFunctionDeclaration(stmt.declaration) && stmt.declaration.id && stmt.declaration.id.name === exportName) {
69
+ const raw = source.slice(stmt.declaration.start, stmt.declaration.end);
70
+ return transpileForThread(raw, {
71
+ filename: resolvedFile
72
+ });
73
+ }
74
+ // export const foo = () => { ... }
75
+ if (t.isVariableDeclaration(stmt.declaration)) {
76
+ for (const decl of stmt.declaration.declarations) {
77
+ if (t.isVariableDeclarator(decl) && t.isIdentifier(decl.id) && decl.id.name === exportName && decl.init && (t.isFunctionExpression(decl.init) || t.isArrowFunctionExpression(decl.init))) {
78
+ const raw = source.slice(decl.init.start, decl.init.end);
79
+ return transpileForThread(raw, {
80
+ filename: resolvedFile
81
+ });
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+
90
+ // ── AST helpers ────────────────────────────────────────────────
91
+
92
+ /** Collect all identifiers that appear in reference position inside `node`. */
93
+ function collectReferencedIds(node) {
94
+ const ids = new Set();
95
+ function walk(n, skipId) {
96
+ if (!n || typeof n !== 'object') return;
97
+ if (Array.isArray(n)) {
98
+ n.forEach(el => walk(el, false));
99
+ return;
100
+ }
101
+ if (!n.type) return;
102
+ if (t.isIdentifier(n) && !skipId) {
103
+ ids.add(n.name);
104
+ return;
105
+ }
106
+ if (t.isMemberExpression(n)) {
107
+ walk(n.object, false);
108
+ if (n.computed) walk(n.property, false);
109
+ return;
110
+ }
111
+ if (t.isObjectProperty(n)) {
112
+ if (n.computed) walk(n.key, false);
113
+ walk(n.value, false);
114
+ return;
115
+ }
116
+ if (t.isFunctionExpression(n) || t.isArrowFunctionExpression(n) || t.isFunctionDeclaration(n)) {
117
+ return;
118
+ }
119
+ for (const key of Object.keys(n)) {
120
+ if (SKIP_KEYS.has(key)) continue;
121
+ walk(n[key], false);
122
+ }
123
+ }
124
+ walk(node, false);
125
+ return ids;
126
+ }
127
+
128
+ /** Collect names declared locally inside a function (params + body). */
129
+ function collectLocalNames(fnNode) {
130
+ const names = new Set();
131
+ if (fnNode.params) {
132
+ for (const p of fnNode.params) {
133
+ if (t.isIdentifier(p)) names.add(p.name);
134
+ if (t.isAssignmentPattern(p) && t.isIdentifier(p.left)) names.add(p.left.name);
135
+ if (t.isRestElement(p) && t.isIdentifier(p.argument)) names.add(p.argument.name);
136
+ }
137
+ }
138
+ if (fnNode.id && t.isIdentifier(fnNode.id)) names.add(fnNode.id.name);
139
+ function walk(n) {
140
+ if (!n || typeof n !== 'object') return;
141
+ if (Array.isArray(n)) {
142
+ n.forEach(walk);
143
+ return;
144
+ }
145
+ if (!n.type) return;
146
+ if (t.isVariableDeclarator(n) && t.isIdentifier(n.id)) names.add(n.id.name);
147
+ if (t.isFunctionDeclaration(n) && n.id) {
148
+ names.add(n.id.name);
149
+ return;
150
+ }
151
+ if (t.isFunctionExpression(n) || t.isArrowFunctionExpression(n)) return;
152
+ for (const key of Object.keys(n)) {
153
+ if (SKIP_KEYS.has(key)) continue;
154
+ walk(n[key]);
155
+ }
156
+ }
157
+ if (fnNode.body) walk(fnNode.body);
158
+ return names;
159
+ }
160
+
161
+ /**
162
+ * For each free variable in `fnNode`, try to resolve it to a
163
+ * compile-time value (literal or function) via scope bindings.
164
+ * Handles transitive closures: if a captured function itself has
165
+ * free variables, those are captured too.
166
+ *
167
+ * Returns an array of source strings like `"var b = 3;"` or
168
+ * `"var add = (x) => x + b;"`.
169
+ */
170
+ function getCaptureDecls(fnNode, scope, state) {
171
+ const captures = [];
172
+ const seen = new Set();
173
+ function capture(targetFnNode) {
174
+ const referenced = collectReferencedIds(targetFnNode.body);
175
+ const locals = collectLocalNames(targetFnNode);
176
+ for (const name of referenced) {
177
+ if (locals.has(name) || seen.has(name)) continue;
178
+ seen.add(name);
179
+ const binding = scope.getBinding(name);
180
+ if (!binding) continue;
181
+ const bNode = binding.path.node;
182
+
183
+ // const/let/var x = <literal>
184
+ if (t.isVariableDeclarator(bNode) && bNode.init && t.isLiteral(bNode.init)) {
185
+ const initSrc = state.file.code.slice(bNode.init.start, bNode.init.end);
186
+ captures.push('var ' + name + ' = ' + initSrc + ';');
187
+ continue;
188
+ }
189
+
190
+ // const/let/var x = <arrow / function expression>
191
+ if (t.isVariableDeclarator(bNode) && bNode.init && (t.isFunctionExpression(bNode.init) || t.isArrowFunctionExpression(bNode.init))) {
192
+ // Recursively capture the inner function's free vars first
193
+ capture(bNode.init);
194
+ const initSrc = state.file.code.slice(bNode.init.start, bNode.init.end);
195
+ captures.push('var ' + name + ' = ' + transpileForThread(initSrc, state) + ';');
196
+ continue;
197
+ }
198
+
199
+ // function declaration
200
+ if (t.isFunctionDeclaration(bNode)) {
201
+ capture(bNode);
202
+ const fnSrc = state.file.code.slice(bNode.start, bNode.end);
203
+ captures.push(transpileForThread(fnSrc, state));
204
+ continue;
205
+ }
206
+ }
207
+ }
208
+ capture(fnNode);
209
+ return captures;
210
+ }
211
+
212
+ // ── Core transform helpers ─────────────────────────────────────
213
+
214
+ /**
215
+ * Transpile extracted source for the thread engine. Always downlevels
216
+ * to ES5 (for Rhino). Also strips TypeScript when the host file is TS.
217
+ */
218
+ function transpileForThread(code, state) {
219
+ try {
220
+ const babelCore = require('@babel/core');
221
+ const fn = state.filename || state.file.opts && state.file.opts.filename || '';
222
+ const isTS = /\.tsx?$/.test(fn);
223
+ const plugins = isTS ? [['@babel/plugin-transform-typescript', {
224
+ isTSX: true
225
+ }]] : [];
226
+ const result = babelCore.transformSync(code, {
227
+ presets: [['@babel/preset-env', {
228
+ targets: {
229
+ ie: '11'
230
+ },
231
+ modules: false
232
+ }]],
233
+ plugins,
234
+ configFile: false,
235
+ babelrc: false,
236
+ filename: isTS ? 'thread.tsx' : 'thread.js'
237
+ });
238
+ return (result && result.code || code).replace(/;\s*$/, '');
239
+ } catch {
240
+ return code;
241
+ }
242
+ }
8
243
  function maybeTransformArg(callPath, state, argNode, index) {
9
244
  if (!t.isArrowFunctionExpression(argNode) && !t.isFunctionExpression(argNode)) {
10
245
  return;
11
246
  }
12
247
  const originalCode = state.file.code;
13
- const fnSource = originalCode.slice(argNode.start, argNode.end);
248
+ const fnSource = transpileForThread(originalCode.slice(argNode.start, argNode.end), state);
14
249
  const iife = `(${fnSource})(__params__)`;
15
250
  callPath.node.arguments[index] = t.stringLiteral(iife);
16
251
  }
252
+
253
+ /**
254
+ * Resolve a node to its function source **and** any captured free-variable
255
+ * declarations. Returns the ready-to-eval source string, or null.
256
+ */
257
+ function extractFnSource(node, callPath, state) {
258
+ let fnNode = null;
259
+ let fnSource = null;
260
+ let isImported = false;
261
+ if (t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) {
262
+ fnNode = node;
263
+ fnSource = state.file.code.slice(node.start, node.end);
264
+ } else if (t.isIdentifier(node)) {
265
+ const binding = callPath.scope.getBinding(node.name);
266
+ if (!binding) return null;
267
+ const bNode = binding.path.node;
268
+ if (t.isFunctionDeclaration(bNode)) {
269
+ fnNode = bNode;
270
+ fnSource = state.file.code.slice(bNode.start, bNode.end);
271
+ } else if (t.isVariableDeclarator(bNode) && bNode.init) {
272
+ if (t.isFunctionExpression(bNode.init) || t.isArrowFunctionExpression(bNode.init)) {
273
+ fnNode = bNode.init;
274
+ fnSource = state.file.code.slice(bNode.init.start, bNode.init.end);
275
+ }
276
+ } else if (t.isImportSpecifier(bNode) || t.isImportDefaultSpecifier(bNode)) {
277
+ // Cross-module import: resolve the source file and extract the function
278
+ const importDecl = binding.path.parentPath.node;
279
+ const importSource = importDecl.source.value;
280
+ const exportName = t.isImportSpecifier(bNode) && bNode.imported ? t.isIdentifier(bNode.imported) ? bNode.imported.name : bNode.imported.value : 'default';
281
+ const imported = resolveImportedFnSource(importSource, exportName, state);
282
+ if (imported) {
283
+ fnSource = imported;
284
+ isImported = true;
285
+ }
286
+ }
287
+ }
288
+ if (!fnSource) return null;
289
+
290
+ // For imported functions we already have the full source (no local AST node
291
+ // to walk for captures — the function must be self-contained or only depend
292
+ // on its own module's scope which was already inlined).
293
+ if (isImported) return fnSource;
294
+ if (!fnNode) return null;
295
+ fnSource = transpileForThread(fnSource, state);
296
+ const captures = getCaptureDecls(fnNode, callPath.scope, state);
297
+ if (captures.length > 0) {
298
+ fnSource = '(function(){' + captures.join('\n') + '\nreturn ' + fnSource + ';})()';
299
+ }
300
+ return fnSource;
301
+ }
302
+ function tagFnValue(source) {
303
+ return t.objectExpression([t.objectProperty(t.identifier('__rnThreadFn'), t.stringLiteral(source))]);
304
+ }
305
+ function maybeTransformParams(callPath, state, paramsNode) {
306
+ if (!t.isObjectExpression(paramsNode)) return;
307
+ for (const prop of paramsNode.properties) {
308
+ if (!t.isObjectProperty(prop)) continue;
309
+ const fnSrc = extractFnSource(prop.value, callPath, state);
310
+ if (fnSrc) {
311
+ prop.value = tagFnValue(fnSrc);
312
+ prop.shorthand = false;
313
+ } else if (t.isObjectExpression(prop.value)) {
314
+ maybeTransformParams(callPath, state, prop.value);
315
+ } else if (t.isArrayExpression(prop.value)) {
316
+ maybeTransformArrayParams(callPath, state, prop.value);
317
+ }
318
+ }
319
+ }
320
+ function maybeTransformArrayParams(callPath, state, arrNode) {
321
+ for (let i = 0; i < arrNode.elements.length; i++) {
322
+ const el = arrNode.elements[i];
323
+ if (!el) continue;
324
+ const fnSrc = extractFnSource(el, callPath, state);
325
+ if (fnSrc) {
326
+ arrNode.elements[i] = tagFnValue(fnSrc);
327
+ } else if (t.isObjectExpression(el)) {
328
+ maybeTransformParams(callPath, state, el);
329
+ } else if (t.isArrayExpression(el)) {
330
+ maybeTransformArrayParams(callPath, state, el);
331
+ }
332
+ }
333
+ }
334
+
335
+ // ── Visitor ────────────────────────────────────────────────────
336
+
17
337
  return {
18
338
  name: 'react-native-thread',
19
339
  visitor: {
@@ -26,12 +346,18 @@ module.exports = function reactNativeThreadPlugin({
26
346
  if (args.length >= 1) {
27
347
  maybeTransformArg(path, state, args[0], 0);
28
348
  }
349
+ if (args.length >= 2) {
350
+ maybeTransformParams(path, state, args[1]);
351
+ }
29
352
  return;
30
353
  }
31
354
  if (t.isMemberExpression(callee) && !callee.computed && t.isIdentifier(callee.property) && METHOD_API.has(callee.property.name)) {
32
355
  if (args.length >= 1) {
33
356
  maybeTransformArg(path, state, args[0], 0);
34
357
  }
358
+ if (args.length >= 2) {
359
+ maybeTransformParams(path, state, args[1]);
360
+ }
35
361
  }
36
362
  }
37
363
  }
@@ -1 +1 @@
1
- {"version":3,"names":["TOP_LEVEL_API","Set","METHOD_API","module","exports","reactNativeThreadPlugin","types","t","maybeTransformArg","callPath","state","argNode","index","isArrowFunctionExpression","isFunctionExpression","originalCode","file","code","fnSource","slice","start","end","iife","node","arguments","stringLiteral","name","visitor","CallExpression","path","callee","args","isIdentifier","has","length","isMemberExpression","computed","property"],"sourceRoot":"../../src","sources":["babel-plugin.js"],"mappings":"AAAA,YAAY;;AAEZ,MAAMA,aAAa,GAAG,IAAIC,GAAG,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAExD,MAAMC,UAAU,GAAG,IAAID,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAEnCE,MAAM,CAACC,OAAO,GAAG,SAASC,uBAAuBA,CAAC;EAAEC,KAAK,EAAEC;AAAE,CAAC,EAAE;EAC9D,SAASC,iBAAiBA,CAACC,QAAQ,EAAEC,KAAK,EAAEC,OAAO,EAAEC,KAAK,EAAE;IAC1D,IACE,CAACL,CAAC,CAACM,yBAAyB,CAACF,OAAO,CAAC,IACrC,CAACJ,CAAC,CAACO,oBAAoB,CAACH,OAAO,CAAC,EAChC;MACA;IACF;IAEA,MAAMI,YAAY,GAAGL,KAAK,CAACM,IAAI,CAACC,IAAI;IACpC,MAAMC,QAAQ,GAAGH,YAAY,CAACI,KAAK,CAACR,OAAO,CAACS,KAAK,EAAET,OAAO,CAACU,GAAG,CAAC;IAC/D,MAAMC,IAAI,GAAG,IAAIJ,QAAQ,eAAe;IAExCT,QAAQ,CAACc,IAAI,CAACC,SAAS,CAACZ,KAAK,CAAC,GAAGL,CAAC,CAACkB,aAAa,CAACH,IAAI,CAAC;EACxD;EAEA,OAAO;IACLI,IAAI,EAAE,qBAAqB;IAC3BC,OAAO,EAAE;MACPC,cAAcA,CAACC,IAAI,EAAEnB,KAAK,EAAE;QAC1B,MAAM;UAAEoB,MAAM;UAAEN,SAAS,EAAEO;QAAK,CAAC,GAAGF,IAAI,CAACN,IAAI;QAE7C,IAAIhB,CAAC,CAACyB,YAAY,CAACF,MAAM,CAAC,IAAI9B,aAAa,CAACiC,GAAG,CAACH,MAAM,CAACJ,IAAI,CAAC,EAAE;UAC5D,IAAIK,IAAI,CAACG,MAAM,IAAI,CAAC,EAAE;YACpB1B,iBAAiB,CAACqB,IAAI,EAAEnB,KAAK,EAAEqB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;UAC5C;UACA;QACF;QAEA,IACExB,CAAC,CAAC4B,kBAAkB,CAACL,MAAM,CAAC,IAC5B,CAACA,MAAM,CAACM,QAAQ,IAChB7B,CAAC,CAACyB,YAAY,CAACF,MAAM,CAACO,QAAQ,CAAC,IAC/BnC,UAAU,CAAC+B,GAAG,CAACH,MAAM,CAACO,QAAQ,CAACX,IAAI,CAAC,EACpC;UACA,IAAIK,IAAI,CAACG,MAAM,IAAI,CAAC,EAAE;YACpB1B,iBAAiB,CAACqB,IAAI,EAAEnB,KAAK,EAAEqB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;UAC5C;QACF;MACF;IACF;EACF,CAAC;AACH,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["nodePath","require","fs","TOP_LEVEL_API","Set","METHOD_API","SKIP_KEYS","module","exports","reactNativeThreadPlugin","types","t","babel","parser","RESOLVE_EXTS","resolveImportedFnSource","importSource","exportName","state","currentFile","filename","file","opts","startsWith","dir","dirname","resolvedFile","ext","candidate","resolve","existsSync","statSync","isFile","source","readFileSync","ast","parse","sourceType","plugins","stmt","program","body","isExportNamedDeclaration","declaration","isFunctionDeclaration","id","name","raw","slice","start","end","transpileForThread","isVariableDeclaration","decl","declarations","isVariableDeclarator","isIdentifier","init","isFunctionExpression","isArrowFunctionExpression","collectReferencedIds","node","ids","walk","n","skipId","Array","isArray","forEach","el","type","add","isMemberExpression","object","computed","property","isObjectProperty","key","value","Object","keys","has","collectLocalNames","fnNode","names","params","p","isAssignmentPattern","left","isRestElement","argument","getCaptureDecls","scope","captures","seen","capture","targetFnNode","referenced","locals","binding","getBinding","bNode","path","isLiteral","initSrc","code","push","fnSrc","babelCore","fn","isTS","test","isTSX","result","transformSync","presets","targets","ie","modules","configFile","babelrc","replace","maybeTransformArg","callPath","argNode","index","originalCode","fnSource","iife","arguments","stringLiteral","extractFnSource","isImported","isImportSpecifier","isImportDefaultSpecifier","importDecl","parentPath","imported","length","join","tagFnValue","objectExpression","objectProperty","identifier","maybeTransformParams","paramsNode","isObjectExpression","prop","properties","shorthand","isArrayExpression","maybeTransformArrayParams","arrNode","i","elements","visitor","CallExpression","callee","args"],"sourceRoot":"../../src","sources":["babel-plugin.js"],"mappings":"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","ignoreList":[]}