@fluixi/compiler 1.0.0-alpha.91 → 1.0.0-alpha.93
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/dist/analyze/intrinsics.cjs +21 -1
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +20 -0
- package/dist/analyze/intrinsics.mjs +21 -1
- package/dist/analyze/reactive-bindings.cjs +21 -1
- package/dist/analyze/reactive-bindings.mjs +21 -1
- package/dist/analyze/static-graph.cjs +25 -5
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +25 -5
- package/dist/{babel-VBLQRHQ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-D53J7ICY.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-S4J4OCWK.mjs → chunk-OD53TMER.mjs} +22 -2
- package/dist/{chunk-TWDJUXWZ.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-QX6Y3OAR.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-3JWMCK4A.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +27 -7
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +27 -7
- package/dist/frontend/babel/build-ir-lit.cjs +123 -44
- package/dist/frontend/babel/build-ir-lit.mjs +123 -44
- package/dist/frontend/babel/build-ir.cjs +123 -44
- package/dist/frontend/babel/build-ir.mjs +123 -44
- package/dist/frontend/babel/index.cjs +124 -45
- package/dist/frontend/babel/index.mjs +124 -45
- package/dist/frontend/babel/lower-template.cjs +123 -44
- package/dist/frontend/babel/lower-template.mjs +123 -44
- package/dist/frontend/babel/plugin.cjs +123 -44
- package/dist/frontend/babel/plugin.mjs +123 -44
- package/dist/index.cjs +86 -46
- package/dist/index.mjs +88 -48
- package/dist/integrations.cjs +246 -61
- package/dist/integrations.mjs +53 -19
- package/dist/lower/compile-template.cjs +44 -39
- package/dist/lower/compile-template.mjs +44 -39
- package/dist/lower/jsx.cjs +509 -6
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +114 -6
- package/dist/lower/jsx.mjs +509 -6
- package/dist/lower/template.cjs +43 -38
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +43 -38
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +33 -8
- package/dist/resolve/component-globals.d.cts +8 -0
- package/dist/resolve/component-globals.d.ts +8 -0
- package/dist/resolve/component-globals.d.ts.map +1 -1
- package/dist/resolve/component-globals.js +21 -12
- package/dist/resolve/component-globals.mjs +33 -8
- package/dist/resolve/write-globals.cjs +59 -8
- package/dist/resolve/write-globals.d.cts +6 -0
- package/dist/resolve/write-globals.d.ts +6 -0
- package/dist/resolve/write-globals.d.ts.map +1 -1
- package/dist/resolve/write-globals.js +35 -2
- package/dist/resolve/write-globals.mjs +61 -10
- package/dist/{server-fns-J56G3PFP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-7PUFLRGF.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +199 -49
- package/dist/transform/index.mjs +199 -49
- package/dist/transform/intrinsics.cjs +47 -2
- package/dist/transform/intrinsics.d.cts +12 -0
- package/dist/transform/intrinsics.d.ts +12 -0
- package/dist/transform/intrinsics.d.ts.map +1 -1
- package/dist/transform/intrinsics.js +43 -1
- package/dist/transform/intrinsics.mjs +47 -2
- package/dist/transform/source-locations.cjs +67 -4
- package/dist/transform/source-locations.d.cts +7 -2
- package/dist/transform/source-locations.d.ts +7 -2
- package/dist/transform/source-locations.d.ts.map +1 -1
- package/dist/transform/source-locations.js +68 -3
- package/dist/transform/source-locations.mjs +67 -4
- package/dist/transform/templates.cjs +198 -48
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +5 -3
- package/dist/transform/templates.mjs +198 -48
- package/dist/{transform-D536WXGM.mjs → transform-QWWQDCXE.mjs} +33 -8
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -3
|
@@ -6,6 +6,7 @@ var INTRINSICS = {
|
|
|
6
6
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
7
7
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
8
8
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
9
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
9
10
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
10
11
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
11
12
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -15,7 +16,22 @@ var INTRINSICS = {
|
|
|
15
16
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
16
17
|
// dependency analysis must not guess at.
|
|
17
18
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
18
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
19
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
20
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
21
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
22
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
23
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
24
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
25
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
26
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
27
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
28
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
29
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
30
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
31
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
32
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
33
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
34
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
19
35
|
};
|
|
20
36
|
var RUNTIME_PRIMITIVES = {
|
|
21
37
|
signal: "signal-handle",
|
|
@@ -26,8 +42,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
26
42
|
createMemo: "memo-accessor",
|
|
27
43
|
createEffect: "effect",
|
|
28
44
|
createRenderEffect: "effect",
|
|
45
|
+
renderEffect: "effect",
|
|
46
|
+
computed: "effect",
|
|
29
47
|
createStore: "reactive-object",
|
|
30
48
|
resource: "resource-handle",
|
|
49
|
+
cachedResource: "resource-handle",
|
|
31
50
|
createResource: "reactive-object",
|
|
32
51
|
createSelector: "memo-accessor",
|
|
33
52
|
createDeferred: "memo-accessor"
|
|
@@ -36,6 +55,7 @@ var PRIMITIVE_MODULES = [
|
|
|
36
55
|
"@fluixi/reactive",
|
|
37
56
|
"@fluixi/reactive/signal",
|
|
38
57
|
"@fluixi/reactive/store",
|
|
58
|
+
"@fluixi/reactive/cached-resource",
|
|
39
59
|
"@fluixi/core"
|
|
40
60
|
];
|
|
41
61
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -178,16 +198,41 @@ function collectIntrinsicEdits(program) {
|
|
|
178
198
|
});
|
|
179
199
|
return { edits, diagnostics, imports };
|
|
180
200
|
}
|
|
201
|
+
function avoidBindingClashes(program, result, bound) {
|
|
202
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
203
|
+
for (const stmt of program.body ?? []) {
|
|
204
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
205
|
+
const module = stmt.source.value;
|
|
206
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
207
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
208
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
209
|
+
if (imported === spec.local.name && result.imports.get(module)?.has(imported)) {
|
|
210
|
+
importedAsIs.add(imported);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
215
|
+
for (const names of result.imports.values()) {
|
|
216
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
217
|
+
}
|
|
218
|
+
if (!aliases.size) return;
|
|
219
|
+
for (const edit of result.edits) {
|
|
220
|
+
const alias = aliases.get(edit.code);
|
|
221
|
+
if (alias) edit.code = alias;
|
|
222
|
+
}
|
|
223
|
+
result.aliases = aliases;
|
|
224
|
+
}
|
|
181
225
|
function intrinsicImports(result, bound) {
|
|
182
226
|
const lines = [];
|
|
183
227
|
for (const [module, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
184
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
228
|
+
const wanted = [...names].filter((name) => result.aliases?.has(name) || !bound.has(name)).sort().map((name) => result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name);
|
|
185
229
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module)};`);
|
|
186
230
|
}
|
|
187
231
|
return lines.length ? `${lines.join("\n")}
|
|
188
232
|
` : "";
|
|
189
233
|
}
|
|
190
234
|
export {
|
|
235
|
+
avoidBindingClashes,
|
|
191
236
|
collectIntrinsicEdits,
|
|
192
237
|
intrinsicImports
|
|
193
238
|
};
|
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/transform/source-locations.ts
|
|
21
21
|
var source_locations_exports = {};
|
|
22
22
|
__export(source_locations_exports, {
|
|
23
|
+
CLASS_MARKER: () => CLASS_MARKER,
|
|
23
24
|
COMPONENT_MARKER: () => COMPONENT_MARKER,
|
|
24
25
|
HOLE_MARKER: () => HOLE_MARKER,
|
|
25
26
|
PROPS_MARKER: () => PROPS_MARKER,
|
|
@@ -27,7 +28,7 @@ __export(source_locations_exports, {
|
|
|
27
28
|
collectSourceEdits: () => collectSourceEdits,
|
|
28
29
|
markHole: () => markHole,
|
|
29
30
|
markProps: () => markProps,
|
|
30
|
-
|
|
31
|
+
mayHaveSourceMarks: () => mayHaveSourceMarks
|
|
31
32
|
});
|
|
32
33
|
module.exports = __toCommonJS(source_locations_exports);
|
|
33
34
|
|
|
@@ -39,6 +40,7 @@ var INTRINSICS = {
|
|
|
39
40
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
40
41
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
41
42
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
43
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
42
44
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
43
45
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
44
46
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -48,7 +50,22 @@ var INTRINSICS = {
|
|
|
48
50
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
49
51
|
// dependency analysis must not guess at.
|
|
50
52
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
51
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
53
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
54
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
55
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
56
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
57
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
58
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
59
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
60
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
61
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
62
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
63
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
64
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
65
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
66
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
67
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
68
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
52
69
|
};
|
|
53
70
|
var RUNTIME_PRIMITIVES = {
|
|
54
71
|
signal: "signal-handle",
|
|
@@ -59,8 +76,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
59
76
|
createMemo: "memo-accessor",
|
|
60
77
|
createEffect: "effect",
|
|
61
78
|
createRenderEffect: "effect",
|
|
79
|
+
renderEffect: "effect",
|
|
80
|
+
computed: "effect",
|
|
62
81
|
createStore: "reactive-object",
|
|
63
82
|
resource: "resource-handle",
|
|
83
|
+
cachedResource: "resource-handle",
|
|
64
84
|
createResource: "reactive-object",
|
|
65
85
|
createSelector: "memo-accessor",
|
|
66
86
|
createDeferred: "memo-accessor"
|
|
@@ -69,6 +89,7 @@ var PRIMITIVE_MODULES = [
|
|
|
69
89
|
"@fluixi/reactive",
|
|
70
90
|
"@fluixi/reactive/signal",
|
|
71
91
|
"@fluixi/reactive/store",
|
|
92
|
+
"@fluixi/reactive/cached-resource",
|
|
72
93
|
"@fluixi/core"
|
|
73
94
|
];
|
|
74
95
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -172,6 +193,7 @@ function resolveReactiveBindings(program) {
|
|
|
172
193
|
// src/transform/source-locations.ts
|
|
173
194
|
var SOURCE_MARKER = "__fx_source";
|
|
174
195
|
var COMPONENT_MARKER = "__fx_component";
|
|
196
|
+
var CLASS_MARKER = "__fx_class";
|
|
175
197
|
var HOLE_MARKER = "__fx_hole";
|
|
176
198
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
177
199
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -189,11 +211,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
189
211
|
"createStore",
|
|
190
212
|
"createResource"
|
|
191
213
|
]);
|
|
192
|
-
function
|
|
214
|
+
function mayHaveSourceMarks(code) {
|
|
193
215
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
194
216
|
if (code.includes(name)) return true;
|
|
195
217
|
}
|
|
196
|
-
|
|
218
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
219
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
197
220
|
}
|
|
198
221
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
199
222
|
"IfStatement",
|
|
@@ -212,6 +235,7 @@ function isLoneBranch(statement, parent) {
|
|
|
212
235
|
function isExport(node) {
|
|
213
236
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
214
237
|
}
|
|
238
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
215
239
|
function isStatement(node) {
|
|
216
240
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
217
241
|
}
|
|
@@ -232,6 +256,14 @@ function walk2(node, visit, stack = []) {
|
|
|
232
256
|
}
|
|
233
257
|
function nameFor(stack) {
|
|
234
258
|
const declarator = stack[stack.length - 1];
|
|
259
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
260
|
+
const key = declarator.key;
|
|
261
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
262
|
+
const name = key.name ?? key.id?.name;
|
|
263
|
+
return name;
|
|
264
|
+
}
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
235
267
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
236
268
|
const id = declarator.id;
|
|
237
269
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -280,6 +312,17 @@ function collectSourceEdits(program, filename) {
|
|
|
280
312
|
});
|
|
281
313
|
}
|
|
282
314
|
}
|
|
315
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
316
|
+
const at = node.loc?.start;
|
|
317
|
+
const body = node.body;
|
|
318
|
+
if (at && body) {
|
|
319
|
+
edits.push({
|
|
320
|
+
start: body.start + 1,
|
|
321
|
+
end: body.start + 1,
|
|
322
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
283
326
|
if (node.type !== "CallExpression") return;
|
|
284
327
|
const callee = node.callee;
|
|
285
328
|
if (callee?.type !== "Identifier") return;
|
|
@@ -289,6 +332,26 @@ function collectSourceEdits(program, filename) {
|
|
|
289
332
|
if (!intrinsic && !imported) return;
|
|
290
333
|
const position = node.loc?.start;
|
|
291
334
|
if (!position) return;
|
|
335
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
336
|
+
const up = stack[i];
|
|
337
|
+
if (isStatement(up)) break;
|
|
338
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
339
|
+
if (claimed.has(node.start)) return;
|
|
340
|
+
claimed.add(node.start);
|
|
341
|
+
const label2 = nameFor(stack);
|
|
342
|
+
const own = !up.static;
|
|
343
|
+
const args2 = [
|
|
344
|
+
JSON.stringify(filename),
|
|
345
|
+
String(position.line),
|
|
346
|
+
String(position.column),
|
|
347
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
348
|
+
own ? "this" : void 0
|
|
349
|
+
].filter((a) => a !== void 0).join(",");
|
|
350
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
351
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
292
355
|
let statement;
|
|
293
356
|
let parent;
|
|
294
357
|
let index = -1;
|
|
@@ -12,6 +12,11 @@ export interface SourceLocationsResult {
|
|
|
12
12
|
export declare const SOURCE_MARKER = "__fx_source";
|
|
13
13
|
/** Where a component was declared. Keyed by name, since that is all the runtime carries. */
|
|
14
14
|
export declare const COMPONENT_MARKER = "__fx_component";
|
|
15
|
+
/**
|
|
16
|
+
* Where a class that extends another was declared, keyed by the class itself: a custom
|
|
17
|
+
* element's definition, which the runtime can only reach through `element.constructor`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CLASS_MARKER = "__fx_class";
|
|
15
20
|
/**
|
|
16
21
|
* Where one reactive hole was written. This one wraps: the position has to travel with the
|
|
17
22
|
* accessor to wherever the dom wires it up. A template is emitted as one overwrite, so the
|
|
@@ -38,6 +43,6 @@ export declare const markHole: (accessor: string, line: number, column: number,
|
|
|
38
43
|
export declare const PROPS_MARKER = "__fx_props";
|
|
39
44
|
/** `_({ get a() {…} }, {"a":[9,25]})`, or the object untouched when nothing is watching. */
|
|
40
45
|
export declare const markProps: (object: string, at: Record<string, [number, number]>) => string;
|
|
41
|
-
/** Cheap enough to run before parsing. */
|
|
42
|
-
export declare function
|
|
46
|
+
/** Whether a module has anything to mark: a primitive call or a subclass. Cheap enough to run before parsing. */
|
|
47
|
+
export declare function mayHaveSourceMarks(code: string): boolean;
|
|
43
48
|
export declare function collectSourceEdits(program: unknown, filename: string): SourceLocationsResult;
|
|
@@ -12,6 +12,11 @@ export interface SourceLocationsResult {
|
|
|
12
12
|
export declare const SOURCE_MARKER = "__fx_source";
|
|
13
13
|
/** Where a component was declared. Keyed by name, since that is all the runtime carries. */
|
|
14
14
|
export declare const COMPONENT_MARKER = "__fx_component";
|
|
15
|
+
/**
|
|
16
|
+
* Where a class that extends another was declared, keyed by the class itself: a custom
|
|
17
|
+
* element's definition, which the runtime can only reach through `element.constructor`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CLASS_MARKER = "__fx_class";
|
|
15
20
|
/**
|
|
16
21
|
* Where one reactive hole was written. This one wraps: the position has to travel with the
|
|
17
22
|
* accessor to wherever the dom wires it up. A template is emitted as one overwrite, so the
|
|
@@ -38,7 +43,7 @@ export declare const markHole: (accessor: string, line: number, column: number,
|
|
|
38
43
|
export declare const PROPS_MARKER = "__fx_props";
|
|
39
44
|
/** `_({ get a() {…} }, {"a":[9,25]})`, or the object untouched when nothing is watching. */
|
|
40
45
|
export declare const markProps: (object: string, at: Record<string, [number, number]>) => string;
|
|
41
|
-
/** Cheap enough to run before parsing. */
|
|
42
|
-
export declare function
|
|
46
|
+
/** Whether a module has anything to mark: a primitive call or a subclass. Cheap enough to run before parsing. */
|
|
47
|
+
export declare function mayHaveSourceMarks(code: string): boolean;
|
|
43
48
|
export declare function collectSourceEdits(program: unknown, filename: string): SourceLocationsResult;
|
|
44
49
|
//# sourceMappingURL=source-locations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-locations.d.ts","sourceRoot":"","sources":["../../src/transform/source-locations.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAE3C,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,cAAc,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,OAAO,MAAM,KACZ,MAGE,CAAC;AAEN;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,eAAe,CAAC;AAEzC,4FAA4F;AAC5F,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAG,MACF,CAAC;AAQhF,
|
|
1
|
+
{"version":3,"file":"source-locations.d.ts","sourceRoot":"","sources":["../../src/transform/source-locations.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAE3C,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,YAAY,eAAe,CAAC;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,cAAc,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,OAAO,MAAM,KACZ,MAGE,CAAC;AAEN;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,eAAe,CAAC;AAEzC,4FAA4F;AAC5F,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAG,MACF,CAAC;AAQhF,iHAAiH;AACjH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOxD;AAmFD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CA6J5F"}
|
|
@@ -22,6 +22,11 @@ import { resolveReactiveBindings } from '../analyze/reactive-bindings.js';
|
|
|
22
22
|
export const SOURCE_MARKER = '__fx_source';
|
|
23
23
|
/** Where a component was declared. Keyed by name, since that is all the runtime carries. */
|
|
24
24
|
export const COMPONENT_MARKER = '__fx_component';
|
|
25
|
+
/**
|
|
26
|
+
* Where a class that extends another was declared, keyed by the class itself: a custom
|
|
27
|
+
* element's definition, which the runtime can only reach through `element.constructor`.
|
|
28
|
+
*/
|
|
29
|
+
export const CLASS_MARKER = '__fx_class';
|
|
25
30
|
/**
|
|
26
31
|
* Where one reactive hole was written. This one wraps: the position has to travel with the
|
|
27
32
|
* accessor to wherever the dom wires it up. A template is emitted as one overwrite, so the
|
|
@@ -53,13 +58,16 @@ const RUNTIME_PRIMITIVES = new Set([
|
|
|
53
58
|
'signal', 'memo', 'effect', 'store', 'resource', 'watch',
|
|
54
59
|
'createSignal', 'createMemo', 'createEffect', 'createStore', 'createResource',
|
|
55
60
|
]);
|
|
56
|
-
/** Cheap enough to run before parsing. */
|
|
57
|
-
export function
|
|
61
|
+
/** Whether a module has anything to mark: a primitive call or a subclass. Cheap enough to run before parsing. */
|
|
62
|
+
export function mayHaveSourceMarks(code) {
|
|
58
63
|
for (const name of RUNTIME_PRIMITIVES) {
|
|
59
64
|
if (code.includes(name))
|
|
60
65
|
return true;
|
|
61
66
|
}
|
|
62
|
-
|
|
67
|
+
if (code.includes('$signal') || code.includes('$memo') || code.includes('$effect') || code.includes('$store'))
|
|
68
|
+
return true;
|
|
69
|
+
// A subclass gets a declaration mark, so an element with no signal of its own is still found.
|
|
70
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
63
71
|
}
|
|
64
72
|
/** Positions where the grammar allows exactly one statement, so a second one changes it. */
|
|
65
73
|
const SINGLE_STATEMENT_PARENTS = new Set([
|
|
@@ -74,6 +82,8 @@ function isLoneBranch(statement, parent) {
|
|
|
74
82
|
function isExport(node) {
|
|
75
83
|
return node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration';
|
|
76
84
|
}
|
|
85
|
+
/** Where a class holds a per-instance initializer: the value of a field. */
|
|
86
|
+
const CLASS_FIELDS = new Set(['PropertyDefinition', 'ClassProperty', 'ClassPrivateProperty', 'AccessorProperty']);
|
|
77
87
|
function isStatement(node) {
|
|
78
88
|
return node.type.endsWith('Statement') || node.type === 'VariableDeclaration';
|
|
79
89
|
}
|
|
@@ -103,6 +113,15 @@ function walk(node, visit, stack = []) {
|
|
|
103
113
|
*/
|
|
104
114
|
function nameFor(stack) {
|
|
105
115
|
const declarator = stack[stack.length - 1];
|
|
116
|
+
// `#count = signal(0)` and `count = signal(0)`: the field's name, without the `#`.
|
|
117
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
118
|
+
const key = declarator.key;
|
|
119
|
+
if (key?.type === 'Identifier' || key?.type === 'PrivateIdentifier' || key?.type === 'PrivateName') {
|
|
120
|
+
const name = (key.name ?? key.id?.name);
|
|
121
|
+
return name;
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
106
125
|
if (declarator?.type !== 'VariableDeclarator')
|
|
107
126
|
return undefined;
|
|
108
127
|
const id = declarator.id;
|
|
@@ -170,6 +189,20 @@ export function collectSourceEdits(program, filename) {
|
|
|
170
189
|
});
|
|
171
190
|
}
|
|
172
191
|
}
|
|
192
|
+
// A static block at the top of the body runs once, when the class is defined, with `this`
|
|
193
|
+
// bound to the class. Only a subclass: that covers every custom element and keeps the mark
|
|
194
|
+
// off plain classes. An ambient `declare class` has no body to run.
|
|
195
|
+
if ((node.type === 'ClassDeclaration' || node.type === 'ClassExpression') && node.superClass && !node.declare) {
|
|
196
|
+
const at = node.loc?.start;
|
|
197
|
+
const body = node.body;
|
|
198
|
+
if (at && body) {
|
|
199
|
+
edits.push({
|
|
200
|
+
start: body.start + 1,
|
|
201
|
+
end: body.start + 1,
|
|
202
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
173
206
|
if (node.type !== 'CallExpression')
|
|
174
207
|
return;
|
|
175
208
|
const callee = node.callee;
|
|
@@ -186,6 +219,38 @@ export function collectSourceEdits(program, filename) {
|
|
|
186
219
|
const position = node.loc?.start;
|
|
187
220
|
if (!position)
|
|
188
221
|
return;
|
|
222
|
+
// A class field (`#count = signal(0)`) runs once per instance, and the class body has no
|
|
223
|
+
// statement to put the mark in front of. Hoisting it before the class runs it once, at
|
|
224
|
+
// definition, and the next node created anywhere took its name and line; inside a function
|
|
225
|
+
// (a mixin) the nearest statement was the function's body block, and the mark landed in
|
|
226
|
+
// front of the `{`. The call itself carries the mark instead, so it runs right before the
|
|
227
|
+
// node it describes.
|
|
228
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
229
|
+
const up = stack[i];
|
|
230
|
+
if (isStatement(up))
|
|
231
|
+
break;
|
|
232
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
233
|
+
if (claimed.has(node.start))
|
|
234
|
+
return;
|
|
235
|
+
claimed.add(node.start);
|
|
236
|
+
const label = nameFor(stack);
|
|
237
|
+
// An instance field also hands over `this`: the constructor runs before a custom
|
|
238
|
+
// element opens its scope, and the instance is what ties the node to it later.
|
|
239
|
+
const own = !up.static;
|
|
240
|
+
const args = [
|
|
241
|
+
JSON.stringify(filename),
|
|
242
|
+
String(position.line),
|
|
243
|
+
String(position.column),
|
|
244
|
+
label ? JSON.stringify(label) : own ? 'undefined' : undefined,
|
|
245
|
+
own ? 'this' : undefined,
|
|
246
|
+
]
|
|
247
|
+
.filter((a) => a !== undefined)
|
|
248
|
+
.join(',');
|
|
249
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args}),` });
|
|
250
|
+
edits.push({ start: node.end, end: node.end, code: ')' });
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
189
254
|
// The mark goes in front of the statement, clear of any span another pass rewrites.
|
|
190
255
|
let statement;
|
|
191
256
|
let parent;
|
|
@@ -6,6 +6,7 @@ var INTRINSICS = {
|
|
|
6
6
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
7
7
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
8
8
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
9
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
9
10
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
10
11
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
11
12
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -15,7 +16,22 @@ var INTRINSICS = {
|
|
|
15
16
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
16
17
|
// dependency analysis must not guess at.
|
|
17
18
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
18
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
19
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
20
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
21
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
22
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
23
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
24
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
25
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
26
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
27
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
28
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
29
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
30
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
31
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
32
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
33
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
34
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
19
35
|
};
|
|
20
36
|
var RUNTIME_PRIMITIVES = {
|
|
21
37
|
signal: "signal-handle",
|
|
@@ -26,8 +42,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
26
42
|
createMemo: "memo-accessor",
|
|
27
43
|
createEffect: "effect",
|
|
28
44
|
createRenderEffect: "effect",
|
|
45
|
+
renderEffect: "effect",
|
|
46
|
+
computed: "effect",
|
|
29
47
|
createStore: "reactive-object",
|
|
30
48
|
resource: "resource-handle",
|
|
49
|
+
cachedResource: "resource-handle",
|
|
31
50
|
createResource: "reactive-object",
|
|
32
51
|
createSelector: "memo-accessor",
|
|
33
52
|
createDeferred: "memo-accessor"
|
|
@@ -36,6 +55,7 @@ var PRIMITIVE_MODULES = [
|
|
|
36
55
|
"@fluixi/reactive",
|
|
37
56
|
"@fluixi/reactive/signal",
|
|
38
57
|
"@fluixi/reactive/store",
|
|
58
|
+
"@fluixi/reactive/cached-resource",
|
|
39
59
|
"@fluixi/core"
|
|
40
60
|
];
|
|
41
61
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -139,6 +159,7 @@ function resolveReactiveBindings(program) {
|
|
|
139
159
|
// src/transform/source-locations.ts
|
|
140
160
|
var SOURCE_MARKER = "__fx_source";
|
|
141
161
|
var COMPONENT_MARKER = "__fx_component";
|
|
162
|
+
var CLASS_MARKER = "__fx_class";
|
|
142
163
|
var HOLE_MARKER = "__fx_hole";
|
|
143
164
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
144
165
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -156,11 +177,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
156
177
|
"createStore",
|
|
157
178
|
"createResource"
|
|
158
179
|
]);
|
|
159
|
-
function
|
|
180
|
+
function mayHaveSourceMarks(code) {
|
|
160
181
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
161
182
|
if (code.includes(name)) return true;
|
|
162
183
|
}
|
|
163
|
-
|
|
184
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
185
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
164
186
|
}
|
|
165
187
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
166
188
|
"IfStatement",
|
|
@@ -179,6 +201,7 @@ function isLoneBranch(statement, parent) {
|
|
|
179
201
|
function isExport(node) {
|
|
180
202
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
181
203
|
}
|
|
204
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
182
205
|
function isStatement(node) {
|
|
183
206
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
184
207
|
}
|
|
@@ -199,6 +222,14 @@ function walk2(node, visit, stack = []) {
|
|
|
199
222
|
}
|
|
200
223
|
function nameFor(stack) {
|
|
201
224
|
const declarator = stack[stack.length - 1];
|
|
225
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
226
|
+
const key = declarator.key;
|
|
227
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
228
|
+
const name = key.name ?? key.id?.name;
|
|
229
|
+
return name;
|
|
230
|
+
}
|
|
231
|
+
return void 0;
|
|
232
|
+
}
|
|
202
233
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
203
234
|
const id = declarator.id;
|
|
204
235
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -247,6 +278,17 @@ function collectSourceEdits(program, filename) {
|
|
|
247
278
|
});
|
|
248
279
|
}
|
|
249
280
|
}
|
|
281
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
282
|
+
const at = node.loc?.start;
|
|
283
|
+
const body = node.body;
|
|
284
|
+
if (at && body) {
|
|
285
|
+
edits.push({
|
|
286
|
+
start: body.start + 1,
|
|
287
|
+
end: body.start + 1,
|
|
288
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
250
292
|
if (node.type !== "CallExpression") return;
|
|
251
293
|
const callee = node.callee;
|
|
252
294
|
if (callee?.type !== "Identifier") return;
|
|
@@ -256,6 +298,26 @@ function collectSourceEdits(program, filename) {
|
|
|
256
298
|
if (!intrinsic && !imported) return;
|
|
257
299
|
const position = node.loc?.start;
|
|
258
300
|
if (!position) return;
|
|
301
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
302
|
+
const up = stack[i];
|
|
303
|
+
if (isStatement(up)) break;
|
|
304
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
305
|
+
if (claimed.has(node.start)) return;
|
|
306
|
+
claimed.add(node.start);
|
|
307
|
+
const label2 = nameFor(stack);
|
|
308
|
+
const own = !up.static;
|
|
309
|
+
const args2 = [
|
|
310
|
+
JSON.stringify(filename),
|
|
311
|
+
String(position.line),
|
|
312
|
+
String(position.column),
|
|
313
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
314
|
+
own ? "this" : void 0
|
|
315
|
+
].filter((a) => a !== void 0).join(",");
|
|
316
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
317
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
259
321
|
let statement;
|
|
260
322
|
let parent;
|
|
261
323
|
let index = -1;
|
|
@@ -296,6 +358,7 @@ function collectSourceEdits(program, filename) {
|
|
|
296
358
|
return { edits, marked: edits.length };
|
|
297
359
|
}
|
|
298
360
|
export {
|
|
361
|
+
CLASS_MARKER,
|
|
299
362
|
COMPONENT_MARKER,
|
|
300
363
|
HOLE_MARKER,
|
|
301
364
|
PROPS_MARKER,
|
|
@@ -303,5 +366,5 @@ export {
|
|
|
303
366
|
collectSourceEdits,
|
|
304
367
|
markHole,
|
|
305
368
|
markProps,
|
|
306
|
-
|
|
369
|
+
mayHaveSourceMarks
|
|
307
370
|
};
|