phantom-build 0.1.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 +378 -0
- package/dist/analyzer.d.ts +11 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +330 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/ast-compat.d.ts +11 -0
- package/dist/ast-compat.d.ts.map +1 -0
- package/dist/ast-compat.js +84 -0
- package/dist/ast-compat.js.map +1 -0
- package/dist/classify/boundary.d.ts +30 -0
- package/dist/classify/boundary.d.ts.map +1 -0
- package/dist/classify/boundary.js +145 -0
- package/dist/classify/boundary.js.map +1 -0
- package/dist/classify/browser-globals.d.ts +29 -0
- package/dist/classify/browser-globals.d.ts.map +1 -0
- package/dist/classify/browser-globals.js +197 -0
- package/dist/classify/browser-globals.js.map +1 -0
- package/dist/classify/index.d.ts +14 -0
- package/dist/classify/index.d.ts.map +1 -0
- package/dist/classify/index.js +294 -0
- package/dist/classify/index.js.map +1 -0
- package/dist/classify/lazy-llm.d.ts +122 -0
- package/dist/classify/lazy-llm.d.ts.map +1 -0
- package/dist/classify/lazy-llm.js +142 -0
- package/dist/classify/lazy-llm.js.map +1 -0
- package/dist/classify/lazy.d.ts +23 -0
- package/dist/classify/lazy.d.ts.map +1 -0
- package/dist/classify/lazy.js +686 -0
- package/dist/classify/lazy.js.map +1 -0
- package/dist/classify/llm-client.d.ts +59 -0
- package/dist/classify/llm-client.d.ts.map +1 -0
- package/dist/classify/llm-client.js +193 -0
- package/dist/classify/llm-client.js.map +1 -0
- package/dist/classify/purity.d.ts +21 -0
- package/dist/classify/purity.d.ts.map +1 -0
- package/dist/classify/purity.js +47 -0
- package/dist/classify/purity.js.map +1 -0
- package/dist/classify/react-patterns.d.ts +15 -0
- package/dist/classify/react-patterns.d.ts.map +1 -0
- package/dist/classify/react-patterns.js +82 -0
- package/dist/classify/react-patterns.js.map +1 -0
- package/dist/classify/taint.d.ts +32 -0
- package/dist/classify/taint.d.ts.map +1 -0
- package/dist/classify/taint.js +68 -0
- package/dist/classify/taint.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +109 -0
- package/dist/cli.js.map +1 -0
- package/dist/extract/chunk-module.d.ts +20 -0
- package/dist/extract/chunk-module.d.ts.map +1 -0
- package/dist/extract/chunk-module.js +163 -0
- package/dist/extract/chunk-module.js.map +1 -0
- package/dist/extract/client-stub.d.ts +25 -0
- package/dist/extract/client-stub.d.ts.map +1 -0
- package/dist/extract/client-stub.js +233 -0
- package/dist/extract/client-stub.js.map +1 -0
- package/dist/extract/import-resolver.d.ts +20 -0
- package/dist/extract/import-resolver.d.ts.map +1 -0
- package/dist/extract/import-resolver.js +51 -0
- package/dist/extract/import-resolver.js.map +1 -0
- package/dist/extract/index.d.ts +20 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +105 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/lazy-transform.d.ts +14 -0
- package/dist/extract/lazy-transform.d.ts.map +1 -0
- package/dist/extract/lazy-transform.js +473 -0
- package/dist/extract/lazy-transform.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +7 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +535 -0
- package/dist/plugin.js.map +1 -0
- package/dist/runtime/index.d.ts +28 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +73 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +3 -0
- package/dist/vite.js.map +1 -0
- package/dist/webpack.d.ts +3 -0
- package/dist/webpack.d.ts.map +1 -0
- package/dist/webpack.js +3 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-only global identifiers.
|
|
3
|
+
* If a function references any of these (unresolved), it must stay on the client.
|
|
4
|
+
*/
|
|
5
|
+
export declare const BROWSER_GLOBALS: Set<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Cross-environment globals — available in both browser and Node.js.
|
|
8
|
+
* Functions using ONLY these should be classified as Ambiguous, not ClientInteractive.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AMBIGUOUS_GLOBALS: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* "Safe" globals that are pure computation — NOT browser-specific.
|
|
13
|
+
* These exist in all JS environments (Node.js, Deno, browsers).
|
|
14
|
+
* Functions referencing ONLY these are still PureComputation candidates.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PURE_GLOBALS: Set<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if an unresolved global reference is a browser-only API.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isBrowserGlobal(name: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Check if an unresolved global reference is a cross-environment API.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isAmbiguousGlobal(name: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if an unresolved global reference is a safe pure builtin.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isPureGlobal(name: string): boolean;
|
|
29
|
+
//# sourceMappingURL=browser-globals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-globals.d.ts","sourceRoot":"","sources":["../../src/classify/browser-globals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,eAAe,aA8F1B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAmB5B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,aAkEvB,CAAC;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-only global identifiers.
|
|
3
|
+
* If a function references any of these (unresolved), it must stay on the client.
|
|
4
|
+
*/
|
|
5
|
+
export const BROWSER_GLOBALS = new Set([
|
|
6
|
+
// Window / global
|
|
7
|
+
'window',
|
|
8
|
+
'self',
|
|
9
|
+
// DOM
|
|
10
|
+
'document',
|
|
11
|
+
'navigator',
|
|
12
|
+
'location',
|
|
13
|
+
'history',
|
|
14
|
+
'screen',
|
|
15
|
+
// Storage
|
|
16
|
+
'localStorage',
|
|
17
|
+
'sessionStorage',
|
|
18
|
+
'indexedDB',
|
|
19
|
+
'caches',
|
|
20
|
+
// Timers / Animation
|
|
21
|
+
'requestAnimationFrame',
|
|
22
|
+
'cancelAnimationFrame',
|
|
23
|
+
'requestIdleCallback',
|
|
24
|
+
'cancelIdleCallback',
|
|
25
|
+
// Observers
|
|
26
|
+
'IntersectionObserver',
|
|
27
|
+
'MutationObserver',
|
|
28
|
+
'ResizeObserver',
|
|
29
|
+
'PerformanceObserver',
|
|
30
|
+
// Web APIs
|
|
31
|
+
'XMLHttpRequest',
|
|
32
|
+
'WebSocket',
|
|
33
|
+
'EventSource',
|
|
34
|
+
'BroadcastChannel',
|
|
35
|
+
'MessageChannel',
|
|
36
|
+
'Worker',
|
|
37
|
+
'SharedWorker',
|
|
38
|
+
'ServiceWorker',
|
|
39
|
+
// Media
|
|
40
|
+
'Audio',
|
|
41
|
+
'Image',
|
|
42
|
+
'MediaRecorder',
|
|
43
|
+
'MediaStream',
|
|
44
|
+
// DOM constructors
|
|
45
|
+
'HTMLElement',
|
|
46
|
+
'HTMLFormElement',
|
|
47
|
+
'HTMLInputElement',
|
|
48
|
+
'HTMLButtonElement',
|
|
49
|
+
'HTMLTextAreaElement',
|
|
50
|
+
'HTMLSelectElement',
|
|
51
|
+
'HTMLAnchorElement',
|
|
52
|
+
'HTMLImageElement',
|
|
53
|
+
'Element',
|
|
54
|
+
'Node',
|
|
55
|
+
'Event',
|
|
56
|
+
'CustomEvent',
|
|
57
|
+
'MouseEvent',
|
|
58
|
+
'KeyboardEvent',
|
|
59
|
+
'TouchEvent',
|
|
60
|
+
'DragEvent',
|
|
61
|
+
'ClipboardEvent',
|
|
62
|
+
'FocusEvent',
|
|
63
|
+
'FormData',
|
|
64
|
+
// DOM query/manipulation
|
|
65
|
+
'getComputedStyle',
|
|
66
|
+
'getSelection',
|
|
67
|
+
'scrollTo',
|
|
68
|
+
'scrollBy',
|
|
69
|
+
'matchMedia',
|
|
70
|
+
'DOMParser',
|
|
71
|
+
'Range',
|
|
72
|
+
'Selection',
|
|
73
|
+
'TreeWalker',
|
|
74
|
+
'NodeIterator',
|
|
75
|
+
// Window properties
|
|
76
|
+
'visualViewport',
|
|
77
|
+
'screenX',
|
|
78
|
+
'screenY',
|
|
79
|
+
'outerWidth',
|
|
80
|
+
'outerHeight',
|
|
81
|
+
'devicePixelRatio',
|
|
82
|
+
// Other browser-specific
|
|
83
|
+
'alert',
|
|
84
|
+
'confirm',
|
|
85
|
+
'prompt',
|
|
86
|
+
'print',
|
|
87
|
+
'Notification',
|
|
88
|
+
'Clipboard',
|
|
89
|
+
]);
|
|
90
|
+
/**
|
|
91
|
+
* Cross-environment globals — available in both browser and Node.js.
|
|
92
|
+
* Functions using ONLY these should be classified as Ambiguous, not ClientInteractive.
|
|
93
|
+
*/
|
|
94
|
+
export const AMBIGUOUS_GLOBALS = new Set([
|
|
95
|
+
'fetch',
|
|
96
|
+
'structuredClone',
|
|
97
|
+
'crypto',
|
|
98
|
+
'performance',
|
|
99
|
+
'queueMicrotask',
|
|
100
|
+
'globalThis',
|
|
101
|
+
// Timers — available in both browser and Node.js
|
|
102
|
+
'setTimeout',
|
|
103
|
+
'clearTimeout',
|
|
104
|
+
'setInterval',
|
|
105
|
+
'clearInterval',
|
|
106
|
+
'setImmediate',
|
|
107
|
+
'clearImmediate',
|
|
108
|
+
// Encoding — available in Node.js since v16
|
|
109
|
+
'atob',
|
|
110
|
+
'btoa',
|
|
111
|
+
]);
|
|
112
|
+
/**
|
|
113
|
+
* "Safe" globals that are pure computation — NOT browser-specific.
|
|
114
|
+
* These exist in all JS environments (Node.js, Deno, browsers).
|
|
115
|
+
* Functions referencing ONLY these are still PureComputation candidates.
|
|
116
|
+
*/
|
|
117
|
+
export const PURE_GLOBALS = new Set([
|
|
118
|
+
// Math & Numbers
|
|
119
|
+
'Math',
|
|
120
|
+
'Number',
|
|
121
|
+
'BigInt',
|
|
122
|
+
'NaN',
|
|
123
|
+
'Infinity',
|
|
124
|
+
'isNaN',
|
|
125
|
+
'isFinite',
|
|
126
|
+
'parseInt',
|
|
127
|
+
'parseFloat',
|
|
128
|
+
// Strings
|
|
129
|
+
'String',
|
|
130
|
+
'RegExp',
|
|
131
|
+
// Collections
|
|
132
|
+
'Array',
|
|
133
|
+
'Object',
|
|
134
|
+
'Map',
|
|
135
|
+
'Set',
|
|
136
|
+
'WeakMap',
|
|
137
|
+
'WeakSet',
|
|
138
|
+
'WeakRef',
|
|
139
|
+
// Structured data
|
|
140
|
+
'JSON',
|
|
141
|
+
'ArrayBuffer',
|
|
142
|
+
'SharedArrayBuffer',
|
|
143
|
+
'DataView',
|
|
144
|
+
'Uint8Array',
|
|
145
|
+
'Uint16Array',
|
|
146
|
+
'Uint32Array',
|
|
147
|
+
'Int8Array',
|
|
148
|
+
'Int16Array',
|
|
149
|
+
'Int32Array',
|
|
150
|
+
'Float32Array',
|
|
151
|
+
'Float64Array',
|
|
152
|
+
// Error types
|
|
153
|
+
'Error',
|
|
154
|
+
'TypeError',
|
|
155
|
+
'RangeError',
|
|
156
|
+
'ReferenceError',
|
|
157
|
+
'SyntaxError',
|
|
158
|
+
'URIError',
|
|
159
|
+
'EvalError',
|
|
160
|
+
'AggregateError',
|
|
161
|
+
// Other pure builtins
|
|
162
|
+
'Symbol',
|
|
163
|
+
'Proxy',
|
|
164
|
+
'Reflect',
|
|
165
|
+
'Promise',
|
|
166
|
+
'Date',
|
|
167
|
+
'Boolean',
|
|
168
|
+
'Function',
|
|
169
|
+
'undefined',
|
|
170
|
+
'null',
|
|
171
|
+
'true',
|
|
172
|
+
'false',
|
|
173
|
+
'console', // debatable, but console.log is a side effect we'll allow
|
|
174
|
+
'encodeURI',
|
|
175
|
+
'encodeURIComponent',
|
|
176
|
+
'decodeURI',
|
|
177
|
+
'decodeURIComponent',
|
|
178
|
+
]);
|
|
179
|
+
/**
|
|
180
|
+
* Check if an unresolved global reference is a browser-only API.
|
|
181
|
+
*/
|
|
182
|
+
export function isBrowserGlobal(name) {
|
|
183
|
+
return BROWSER_GLOBALS.has(name);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Check if an unresolved global reference is a cross-environment API.
|
|
187
|
+
*/
|
|
188
|
+
export function isAmbiguousGlobal(name) {
|
|
189
|
+
return AMBIGUOUS_GLOBALS.has(name);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Check if an unresolved global reference is a safe pure builtin.
|
|
193
|
+
*/
|
|
194
|
+
export function isPureGlobal(name) {
|
|
195
|
+
return PURE_GLOBALS.has(name);
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=browser-globals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-globals.js","sourceRoot":"","sources":["../../src/classify/browser-globals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IACrC,kBAAkB;IAClB,QAAQ;IACR,MAAM;IAEN,MAAM;IACN,UAAU;IACV,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IAER,UAAU;IACV,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,QAAQ;IAER,qBAAqB;IACrB,uBAAuB;IACvB,sBAAsB;IACtB,qBAAqB;IACrB,oBAAoB;IAEpB,YAAY;IACZ,sBAAsB;IACtB,kBAAkB;IAClB,gBAAgB;IAChB,qBAAqB;IAErB,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,aAAa;IACb,kBAAkB;IAClB,gBAAgB;IAChB,QAAQ;IACR,cAAc;IACd,eAAe;IAEf,QAAQ;IACR,OAAO;IACP,OAAO;IACP,eAAe;IACf,aAAa;IAEb,mBAAmB;IACnB,aAAa;IACb,iBAAiB;IACjB,kBAAkB;IAClB,mBAAmB;IACnB,qBAAqB;IACrB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,SAAS;IACT,MAAM;IACN,OAAO;IACP,aAAa;IACb,YAAY;IACZ,eAAe;IACf,YAAY;IACZ,WAAW;IACX,gBAAgB;IAChB,YAAY;IACZ,UAAU;IAEV,yBAAyB;IACzB,kBAAkB;IAClB,cAAc;IACd,UAAU;IACV,UAAU;IACV,YAAY;IACZ,WAAW;IACX,OAAO;IACP,WAAW;IACX,YAAY;IACZ,cAAc;IAEd,oBAAoB;IACpB,gBAAgB;IAChB,SAAS;IACT,SAAS;IACT,YAAY;IACZ,aAAa;IACb,kBAAkB;IAElB,yBAAyB;IACzB,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,cAAc;IACd,WAAW;CACZ,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IACvC,OAAO;IACP,iBAAiB;IACjB,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,YAAY;IAEZ,iDAAiD;IACjD,YAAY;IACZ,cAAc;IACd,aAAa;IACb,eAAe;IACf,cAAc;IACd,gBAAgB;IAEhB,4CAA4C;IAC5C,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAClC,iBAAiB;IACjB,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,UAAU;IACV,OAAO;IACP,UAAU;IACV,UAAU;IACV,YAAY;IAEZ,UAAU;IACV,QAAQ;IACR,QAAQ;IAER,cAAc;IACd,OAAO;IACP,QAAQ;IACR,KAAK;IACL,KAAK;IACL,SAAS;IACT,SAAS;IACT,SAAS;IAET,kBAAkB;IAClB,MAAM;IACN,aAAa;IACb,mBAAmB;IACnB,UAAU;IACV,YAAY;IACZ,aAAa;IACb,aAAa;IACb,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,cAAc;IAEd,cAAc;IACd,OAAO;IACP,WAAW;IACX,YAAY;IACZ,gBAAgB;IAChB,aAAa;IACb,UAAU;IACV,WAAW;IACX,gBAAgB;IAEhB,sBAAsB;IACtB,QAAQ;IACR,OAAO;IACP,SAAS;IACT,SAAS;IACT,MAAM;IACN,SAAS;IACT,UAAU;IACV,WAAW;IACX,MAAM;IACN,MAAM;IACN,OAAO;IACP,SAAS,EAAE,0DAA0D;IACrE,WAAW;IACX,oBAAoB;IACpB,WAAW;IACX,oBAAoB;CACrB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AnalyzedModule, ClassifiedSegment } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Run the full 3-pass classification on an analyzed module.
|
|
4
|
+
*
|
|
5
|
+
* Pass 1: Taint analysis — mark functions that reference browser APIs
|
|
6
|
+
* Pass 2: Purity analysis — determine if non-tainted functions are pure
|
|
7
|
+
* Pass 3: Boundary detection — classify and identify extraction candidates
|
|
8
|
+
*/
|
|
9
|
+
export declare function classifyModule(analyzed: AnalyzedModule, sourceCode: string): ClassifiedSegment[];
|
|
10
|
+
export { analyzeTaint, type TaintResult } from './taint.js';
|
|
11
|
+
export { analyzePurity, type PurityResult } from './purity.js';
|
|
12
|
+
export { classifySegment } from './boundary.js';
|
|
13
|
+
export { detectLazyCandidates } from './lazy.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/classify/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AAMzF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,MAAM,GACjB,iBAAiB,EAAE,CAgDrB;AA8RD,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { analyzeTaint, propagateTaint } from './taint.js';
|
|
2
|
+
import { analyzePurity } from './purity.js';
|
|
3
|
+
import { classifySegment } from './boundary.js';
|
|
4
|
+
import { EXTRACTABLE_HOOKS, CLIENT_ONLY_HOOKS, EVENT_HANDLER_PROPS } from './react-patterns.js';
|
|
5
|
+
/**
|
|
6
|
+
* Run the full 3-pass classification on an analyzed module.
|
|
7
|
+
*
|
|
8
|
+
* Pass 1: Taint analysis — mark functions that reference browser APIs
|
|
9
|
+
* Pass 2: Purity analysis — determine if non-tainted functions are pure
|
|
10
|
+
* Pass 3: Boundary detection — classify and identify extraction candidates
|
|
11
|
+
*/
|
|
12
|
+
export function classifyModule(analyzed, sourceCode) {
|
|
13
|
+
const { functions } = analyzed;
|
|
14
|
+
if (functions.length === 0)
|
|
15
|
+
return [];
|
|
16
|
+
// Pass 1: Taint analysis
|
|
17
|
+
const taintResults = new Map();
|
|
18
|
+
for (const fn of functions) {
|
|
19
|
+
taintResults.set(fn, analyzeTaint(fn));
|
|
20
|
+
}
|
|
21
|
+
// Propagate taint through call chains
|
|
22
|
+
propagateTaint(functions, taintResults);
|
|
23
|
+
// Determine parent hook context for each function
|
|
24
|
+
const hookContexts = detectHookContexts(analyzed, sourceCode);
|
|
25
|
+
// Detect event handler contexts from JSX
|
|
26
|
+
const eventHandlerContexts = detectEventHandlerContexts(analyzed);
|
|
27
|
+
// Build span → AST node map for JSX detection
|
|
28
|
+
const astNodes = buildAstNodeMap(analyzed);
|
|
29
|
+
// Pass 2 + 3: Purity analysis + boundary detection
|
|
30
|
+
const segments = [];
|
|
31
|
+
for (let i = 0; i < functions.length; i++) {
|
|
32
|
+
const fn = functions[i];
|
|
33
|
+
const taint = taintResults.get(fn);
|
|
34
|
+
const purity = analyzePurity(fn, taint);
|
|
35
|
+
const parentHook = hookContexts.get(fn) ?? null;
|
|
36
|
+
const parentEventProp = eventHandlerContexts.get(fn) ?? null;
|
|
37
|
+
const astNode = astNodes.get(`${fn.span.start}:${fn.span.end}`) ?? null;
|
|
38
|
+
const segment = classifySegment({
|
|
39
|
+
fn,
|
|
40
|
+
taint,
|
|
41
|
+
purity,
|
|
42
|
+
parentHook,
|
|
43
|
+
parentEventProp,
|
|
44
|
+
sourceCode,
|
|
45
|
+
filePath: analyzed.path,
|
|
46
|
+
index: i,
|
|
47
|
+
astNode,
|
|
48
|
+
});
|
|
49
|
+
segments.push(segment);
|
|
50
|
+
}
|
|
51
|
+
return segments;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build a map from span key to AST node for all function nodes.
|
|
55
|
+
* Used to pass AST nodes to the boundary classifier for JSX detection.
|
|
56
|
+
*/
|
|
57
|
+
function buildAstNodeMap(analyzed) {
|
|
58
|
+
const nodeMap = new Map();
|
|
59
|
+
walkNode(analyzed.ast, (node) => {
|
|
60
|
+
if (node.type === 'FunctionDeclaration' ||
|
|
61
|
+
node.type === 'FunctionExpression' ||
|
|
62
|
+
node.type === 'ArrowFunctionExpression') {
|
|
63
|
+
const start = node.start;
|
|
64
|
+
const end = node.end;
|
|
65
|
+
if (start != null && end != null) {
|
|
66
|
+
nodeMap.set(`${start}:${end}`, node);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return nodeMap;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Detect which functions are callbacks of React hooks.
|
|
74
|
+
*
|
|
75
|
+
* Walks the AST looking for call expressions like:
|
|
76
|
+
* useMemo(() => ..., [deps])
|
|
77
|
+
* useEffect(() => ..., [deps])
|
|
78
|
+
*
|
|
79
|
+
* Maps the callback function to its parent hook name.
|
|
80
|
+
*/
|
|
81
|
+
function detectHookContexts(analyzed, sourceCode) {
|
|
82
|
+
const hookContexts = new Map();
|
|
83
|
+
const hookNames = new Set([...EXTRACTABLE_HOOKS, ...CLIENT_ONLY_HOOKS]);
|
|
84
|
+
// Walk AST to find hook calls
|
|
85
|
+
walkNode(analyzed.ast, (node) => {
|
|
86
|
+
if (node.type !== 'CallExpression')
|
|
87
|
+
return;
|
|
88
|
+
const call = node;
|
|
89
|
+
const callee = call.callee;
|
|
90
|
+
// Resolve hook name from callee
|
|
91
|
+
let hookName = null;
|
|
92
|
+
if (callee.type === 'Identifier') {
|
|
93
|
+
// Direct call: useMemo(...)
|
|
94
|
+
const name = callee.name;
|
|
95
|
+
if (hookNames.has(name))
|
|
96
|
+
hookName = name;
|
|
97
|
+
}
|
|
98
|
+
else if (callee.type === 'MemberExpression') {
|
|
99
|
+
// Namespace call: React.useMemo(...)
|
|
100
|
+
const prop = callee.property;
|
|
101
|
+
if (prop.type === 'Identifier') {
|
|
102
|
+
const name = prop.name;
|
|
103
|
+
if (hookNames.has(name))
|
|
104
|
+
hookName = name;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (!hookName)
|
|
108
|
+
return;
|
|
109
|
+
// First argument should be the callback
|
|
110
|
+
const firstArg = call.arguments[0];
|
|
111
|
+
if (!firstArg ||
|
|
112
|
+
(firstArg.type !== 'ArrowFunctionExpression' &&
|
|
113
|
+
firstArg.type !== 'FunctionExpression')) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Find the matching FunctionDependency by span
|
|
117
|
+
const argStart = firstArg.start;
|
|
118
|
+
const argEnd = firstArg.end;
|
|
119
|
+
if (argStart == null || argEnd == null)
|
|
120
|
+
return;
|
|
121
|
+
const matchingFn = analyzed.functions.find((fn) => fn.span.start === argStart && fn.span.end === argEnd);
|
|
122
|
+
if (matchingFn) {
|
|
123
|
+
hookContexts.set(matchingFn, hookName);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return hookContexts;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Detect which functions are used exclusively as JSX event handler props.
|
|
130
|
+
*
|
|
131
|
+
* Walks the AST looking for JSX attributes like:
|
|
132
|
+
* onClick={handleClick}
|
|
133
|
+
* onSubmit={(e) => { ... }}
|
|
134
|
+
*
|
|
135
|
+
* For identifier references (onClick={handleClick}), also traces through
|
|
136
|
+
* useCallback: if `handleClick = useCallback(fn, deps)`, marks the inner
|
|
137
|
+
* callback `fn` as the extraction target.
|
|
138
|
+
*
|
|
139
|
+
* Only marks a function as an event handler if ALL its references in the
|
|
140
|
+
* module are as JSX event handler props (exclusive-use check).
|
|
141
|
+
*/
|
|
142
|
+
function detectEventHandlerContexts(analyzed) {
|
|
143
|
+
const result = new Map();
|
|
144
|
+
// Step 1: Collect all event handler references from JSX
|
|
145
|
+
// Maps function name → event prop name (for identifier references)
|
|
146
|
+
const eventHandlerNames = new Map();
|
|
147
|
+
// Maps span key → event prop name (for inline function references)
|
|
148
|
+
const eventHandlerSpans = new Map();
|
|
149
|
+
// Also build a map from useCallback result names to inner callback FunctionDependency
|
|
150
|
+
// useCallback(fn, deps) → the variable holding the result maps to fn's inner callback
|
|
151
|
+
const useCallbackMap = new Map();
|
|
152
|
+
// Detect useCallback patterns: const handler = useCallback(fn, deps)
|
|
153
|
+
walkNode(analyzed.ast, (node) => {
|
|
154
|
+
if (node.type !== 'VariableDeclarator')
|
|
155
|
+
return;
|
|
156
|
+
const decl = node;
|
|
157
|
+
if (!decl.id || decl.id.type !== 'Identifier')
|
|
158
|
+
return;
|
|
159
|
+
if (!decl.init || decl.init.type !== 'CallExpression')
|
|
160
|
+
return;
|
|
161
|
+
const call = decl.init;
|
|
162
|
+
const callee = call.callee;
|
|
163
|
+
let isUseCallback = false;
|
|
164
|
+
if (callee.type === 'Identifier' && callee.name === 'useCallback') {
|
|
165
|
+
isUseCallback = true;
|
|
166
|
+
}
|
|
167
|
+
else if (callee.type === 'MemberExpression') {
|
|
168
|
+
const prop = callee.property;
|
|
169
|
+
if (prop.type === 'Identifier' && prop.name === 'useCallback') {
|
|
170
|
+
isUseCallback = true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!isUseCallback)
|
|
174
|
+
return;
|
|
175
|
+
const firstArg = call.arguments[0];
|
|
176
|
+
if (!firstArg ||
|
|
177
|
+
(firstArg.type !== 'ArrowFunctionExpression' && firstArg.type !== 'FunctionExpression')) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const argStart = firstArg.start;
|
|
181
|
+
const argEnd = firstArg.end;
|
|
182
|
+
if (argStart == null || argEnd == null)
|
|
183
|
+
return;
|
|
184
|
+
const matchingFn = analyzed.functions.find((fn) => fn.span.start === argStart && fn.span.end === argEnd);
|
|
185
|
+
if (matchingFn) {
|
|
186
|
+
useCallbackMap.set(decl.id.name, matchingFn);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
// Walk JSX to find event handler props
|
|
190
|
+
walkNode(analyzed.ast, (node) => {
|
|
191
|
+
if (node.type !== 'JSXAttribute')
|
|
192
|
+
return;
|
|
193
|
+
const attr = node;
|
|
194
|
+
// Check if this is an event handler prop
|
|
195
|
+
const propName = attr.name?.name;
|
|
196
|
+
if (!propName || !EVENT_HANDLER_PROPS.has(propName))
|
|
197
|
+
return;
|
|
198
|
+
const value = attr.value;
|
|
199
|
+
if (!value || value.type !== 'JSXExpressionContainer')
|
|
200
|
+
return;
|
|
201
|
+
const container = value;
|
|
202
|
+
const expr = container.expression;
|
|
203
|
+
if (expr.type === 'Identifier') {
|
|
204
|
+
// onClick={handleClick} → record the identifier name
|
|
205
|
+
eventHandlerNames.set(expr.name, propName);
|
|
206
|
+
}
|
|
207
|
+
else if (expr.type === 'ArrowFunctionExpression' ||
|
|
208
|
+
expr.type === 'FunctionExpression') {
|
|
209
|
+
// onClick={() => ...} → record by span
|
|
210
|
+
const start = expr.start;
|
|
211
|
+
const end = expr.end;
|
|
212
|
+
if (start != null && end != null) {
|
|
213
|
+
eventHandlerSpans.set(`${start}:${end}`, propName);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// CallExpression → skip (e.g., onClick={createHandler()})
|
|
217
|
+
});
|
|
218
|
+
// Step 2: Count total references to each name in the module for exclusive-use check
|
|
219
|
+
const totalRefs = new Map();
|
|
220
|
+
walkNode(analyzed.ast, (node) => {
|
|
221
|
+
if (node.type === 'Identifier') {
|
|
222
|
+
const name = node.name;
|
|
223
|
+
totalRefs.set(name, (totalRefs.get(name) ?? 0) + 1);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// Count event handler references per name
|
|
227
|
+
const eventRefs = new Map();
|
|
228
|
+
for (const [name] of eventHandlerNames) {
|
|
229
|
+
eventRefs.set(name, (eventRefs.get(name) ?? 0) + 1);
|
|
230
|
+
}
|
|
231
|
+
// Step 3: Match to FunctionDependency entries
|
|
232
|
+
// Handle inline functions (matched by span)
|
|
233
|
+
for (const fn of analyzed.functions) {
|
|
234
|
+
const spanKey = `${fn.span.start}:${fn.span.end}`;
|
|
235
|
+
const propName = eventHandlerSpans.get(spanKey);
|
|
236
|
+
if (propName) {
|
|
237
|
+
// Inline functions are always exclusively used as event handlers
|
|
238
|
+
result.set(fn, propName);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Handle identifier references (matched by name)
|
|
243
|
+
for (const [handlerName, propName] of eventHandlerNames) {
|
|
244
|
+
// Exclusive-use check: the handler name should only appear in JSX event props
|
|
245
|
+
// We approximate this: total refs should be ≤ eventRefs + 1 (the declaration itself)
|
|
246
|
+
// If it's referenced elsewhere (called in render, passed as non-event prop), skip it
|
|
247
|
+
const total = totalRefs.get(handlerName) ?? 0;
|
|
248
|
+
const eventCount = eventRefs.get(handlerName) ?? 0;
|
|
249
|
+
// declaration (1) + event handler references (eventCount) should account for all refs
|
|
250
|
+
if (total > eventCount + 1) {
|
|
251
|
+
// Referenced elsewhere — not exclusively an event handler
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
// Check if this is a useCallback wrapper — trace to inner callback
|
|
255
|
+
const innerFn = useCallbackMap.get(handlerName);
|
|
256
|
+
if (innerFn) {
|
|
257
|
+
result.set(innerFn, propName);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
// Direct match — find the FunctionDependency by name
|
|
261
|
+
const matchingFn = analyzed.functions.find((fn) => fn.name === handlerName);
|
|
262
|
+
if (matchingFn) {
|
|
263
|
+
result.set(matchingFn, propName);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Simple recursive AST walker.
|
|
270
|
+
*/
|
|
271
|
+
function walkNode(node, callback) {
|
|
272
|
+
if (!node || typeof node !== 'object')
|
|
273
|
+
return;
|
|
274
|
+
if (Array.isArray(node)) {
|
|
275
|
+
for (const child of node) {
|
|
276
|
+
walkNode(child, callback);
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const obj = node;
|
|
281
|
+
if (typeof obj.type !== 'string')
|
|
282
|
+
return;
|
|
283
|
+
callback(obj);
|
|
284
|
+
for (const key of Object.keys(obj)) {
|
|
285
|
+
if (key === 'type')
|
|
286
|
+
continue;
|
|
287
|
+
walkNode(obj[key], callback);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
export { analyzeTaint } from './taint.js';
|
|
291
|
+
export { analyzePurity } from './purity.js';
|
|
292
|
+
export { classifySegment } from './boundary.js';
|
|
293
|
+
export { detectLazyCandidates } from './lazy.js';
|
|
294
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/classify/index.ts"],"names":[],"mappings":"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"}
|