@fictjs/compiler 0.2.2 → 0.2.3
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/index.cjs +795 -204
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +791 -203
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -179,7 +179,7 @@ var require_generated = __commonJS({
|
|
|
179
179
|
exports.isExpression = isExpression2;
|
|
180
180
|
exports.isExpressionStatement = isExpressionStatement2;
|
|
181
181
|
exports.isExpressionWrapper = isExpressionWrapper;
|
|
182
|
-
exports.isFile =
|
|
182
|
+
exports.isFile = isFile2;
|
|
183
183
|
exports.isFlow = isFlow;
|
|
184
184
|
exports.isFlowBaseAnnotation = isFlowBaseAnnotation;
|
|
185
185
|
exports.isFlowDeclaration = isFlowDeclaration;
|
|
@@ -489,7 +489,7 @@ var require_generated = __commonJS({
|
|
|
489
489
|
if (node.type !== "ExpressionStatement") return false;
|
|
490
490
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
491
491
|
}
|
|
492
|
-
function
|
|
492
|
+
function isFile2(node, opts) {
|
|
493
493
|
if (!node) return false;
|
|
494
494
|
if (node.type !== "File") return false;
|
|
495
495
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -7322,7 +7322,7 @@ var require_lowercase = __commonJS({
|
|
|
7322
7322
|
exports.restElement = restElement;
|
|
7323
7323
|
exports.restProperty = RestProperty;
|
|
7324
7324
|
exports.returnStatement = returnStatement2;
|
|
7325
|
-
exports.sequenceExpression =
|
|
7325
|
+
exports.sequenceExpression = sequenceExpression2;
|
|
7326
7326
|
exports.spreadElement = spreadElement;
|
|
7327
7327
|
exports.spreadProperty = SpreadProperty;
|
|
7328
7328
|
exports.staticBlock = staticBlock;
|
|
@@ -7876,7 +7876,7 @@ var require_lowercase = __commonJS({
|
|
|
7876
7876
|
validate(defs.argument, node, "argument", argument, 1);
|
|
7877
7877
|
return node;
|
|
7878
7878
|
}
|
|
7879
|
-
function
|
|
7879
|
+
function sequenceExpression2(expressions) {
|
|
7880
7880
|
const node = {
|
|
7881
7881
|
type: "SequenceExpression",
|
|
7882
7882
|
expressions
|
|
@@ -11970,7 +11970,7 @@ var require_cloneNode = __commonJS({
|
|
|
11970
11970
|
Object.defineProperty(exports, "__esModule", {
|
|
11971
11971
|
value: true
|
|
11972
11972
|
});
|
|
11973
|
-
exports.default =
|
|
11973
|
+
exports.default = cloneNode2;
|
|
11974
11974
|
var _index = require_definitions();
|
|
11975
11975
|
var _index2 = require_generated();
|
|
11976
11976
|
var {
|
|
@@ -11990,7 +11990,7 @@ var require_cloneNode = __commonJS({
|
|
|
11990
11990
|
}
|
|
11991
11991
|
return cloneIfNode(obj, deep, withoutLoc, commentsCache);
|
|
11992
11992
|
}
|
|
11993
|
-
function
|
|
11993
|
+
function cloneNode2(node, deep = true, withoutLoc = false) {
|
|
11994
11994
|
return cloneNodeInternal(node, deep, withoutLoc, /* @__PURE__ */ new Map());
|
|
11995
11995
|
}
|
|
11996
11996
|
function cloneNodeInternal(node, deep = true, withoutLoc = false, commentsCache) {
|
|
@@ -14308,6 +14308,7 @@ function debugWarn(flag, message, data) {
|
|
|
14308
14308
|
var t = __toESM(require_lib3(), 1);
|
|
14309
14309
|
import { transformFromAstSync } from "@babel/core";
|
|
14310
14310
|
import transformDestructuring from "@babel/plugin-transform-destructuring";
|
|
14311
|
+
import traverseModule from "@babel/traverse";
|
|
14311
14312
|
|
|
14312
14313
|
// src/ir/hir.ts
|
|
14313
14314
|
var HIRError = class extends Error {
|
|
@@ -14393,9 +14394,9 @@ function extractDependencyPath(expr) {
|
|
|
14393
14394
|
}
|
|
14394
14395
|
return void 0;
|
|
14395
14396
|
}
|
|
14396
|
-
function pathToString(
|
|
14397
|
-
let result =
|
|
14398
|
-
for (const seg of
|
|
14397
|
+
function pathToString(path2) {
|
|
14398
|
+
let result = path2.base;
|
|
14399
|
+
for (const seg of path2.segments) {
|
|
14399
14400
|
if (seg.optional) {
|
|
14400
14401
|
result += "?.";
|
|
14401
14402
|
} else {
|
|
@@ -14420,42 +14421,56 @@ var resolveDestructuringPlugin = () => {
|
|
|
14420
14421
|
const mod = transformDestructuring;
|
|
14421
14422
|
return mod?.default ?? mod;
|
|
14422
14423
|
};
|
|
14423
|
-
var
|
|
14424
|
-
const
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14437
|
-
|
|
14438
|
-
|
|
14439
|
-
|
|
14440
|
-
|
|
14441
|
-
|
|
14442
|
-
|
|
14443
|
-
const
|
|
14444
|
-
if (
|
|
14445
|
-
|
|
14424
|
+
var resolveTraverse = () => {
|
|
14425
|
+
const mod = traverseModule;
|
|
14426
|
+
return mod?.default ?? mod;
|
|
14427
|
+
};
|
|
14428
|
+
var OBJECT_REST_HELPERS = /* @__PURE__ */ new Set(["_objectWithoutProperties", "_objectWithoutPropertiesLoose"]);
|
|
14429
|
+
var OBJECT_DESTRUCTURING_EMPTY_HELPER = "_objectDestructuringEmpty";
|
|
14430
|
+
var EXTENDS_HELPER = "_extends";
|
|
14431
|
+
var isSameIdentifier = (left, right) => {
|
|
14432
|
+
return t.isIdentifier(left) && t.isIdentifier(right) && left.name === right.name;
|
|
14433
|
+
};
|
|
14434
|
+
var rewriteObjectRestHelpers = (ast) => {
|
|
14435
|
+
const traverse = resolveTraverse();
|
|
14436
|
+
traverse(ast, {
|
|
14437
|
+
CallExpression(path2) {
|
|
14438
|
+
const { callee, arguments: args } = path2.node;
|
|
14439
|
+
if (t.isIdentifier(callee) && OBJECT_REST_HELPERS.has(callee.name)) {
|
|
14440
|
+
path2.node.callee = t.identifier("__fictPropsRest");
|
|
14441
|
+
return;
|
|
14442
|
+
}
|
|
14443
|
+
if (t.isIdentifier(callee) && callee.name === EXTENDS_HELPER && args.length === 2 && t.isObjectExpression(args[0]) && args[0].properties.length === 0 && t.isSequenceExpression(args[1]) && args[1].expressions.length === 2) {
|
|
14444
|
+
const [checkExpr, sourceExpr] = args[1].expressions;
|
|
14445
|
+
if (t.isCallExpression(checkExpr) && t.isIdentifier(checkExpr.callee) && checkExpr.callee.name === OBJECT_DESTRUCTURING_EMPTY_HELPER && checkExpr.arguments.length === 1) {
|
|
14446
|
+
const [checkArg] = checkExpr.arguments;
|
|
14447
|
+
if (checkArg && isSameIdentifier(checkArg, sourceExpr)) {
|
|
14448
|
+
const restCall = t.callExpression(t.identifier("__fictPropsRest"), [
|
|
14449
|
+
t.cloneNode(sourceExpr, true),
|
|
14450
|
+
t.arrayExpression([])
|
|
14451
|
+
]);
|
|
14452
|
+
path2.replaceWith(t.sequenceExpression([checkExpr, restCall]));
|
|
14453
|
+
}
|
|
14454
|
+
}
|
|
14446
14455
|
}
|
|
14447
14456
|
}
|
|
14448
|
-
};
|
|
14457
|
+
});
|
|
14449
14458
|
};
|
|
14450
14459
|
var expandDestructuringAssignments = (ast) => {
|
|
14460
|
+
const pluginFactory = resolveDestructuringPlugin();
|
|
14461
|
+
if (typeof pluginFactory !== "function") {
|
|
14462
|
+
throw new Error("Expected @babel/plugin-transform-destructuring to export a function");
|
|
14463
|
+
}
|
|
14451
14464
|
const result = transformFromAstSync(ast, void 0, {
|
|
14452
14465
|
configFile: false,
|
|
14453
14466
|
babelrc: false,
|
|
14454
14467
|
ast: true,
|
|
14455
14468
|
code: false,
|
|
14456
|
-
plugins: [
|
|
14469
|
+
plugins: [pluginFactory]
|
|
14457
14470
|
});
|
|
14458
|
-
|
|
14471
|
+
const expanded = result?.ast ?? ast;
|
|
14472
|
+
rewriteObjectRestHelpers(expanded);
|
|
14473
|
+
return expanded;
|
|
14459
14474
|
};
|
|
14460
14475
|
var reportUnsupportedExpression = (node, overrideMessage) => {
|
|
14461
14476
|
const loc = getLoc(node);
|
|
@@ -16365,6 +16380,70 @@ function shouldMemoizeRegion(region) {
|
|
|
16365
16380
|
return false;
|
|
16366
16381
|
}
|
|
16367
16382
|
|
|
16383
|
+
// src/module-metadata.ts
|
|
16384
|
+
import path from "path";
|
|
16385
|
+
import { existsSync, statSync } from "fs";
|
|
16386
|
+
var globalMetadata = /* @__PURE__ */ new Map();
|
|
16387
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
16388
|
+
function normalizeFileName(fileName) {
|
|
16389
|
+
return path.resolve(fileName);
|
|
16390
|
+
}
|
|
16391
|
+
function getMetadataStore(options) {
|
|
16392
|
+
return options?.moduleMetadata ?? globalMetadata;
|
|
16393
|
+
}
|
|
16394
|
+
function isFile(pathName) {
|
|
16395
|
+
try {
|
|
16396
|
+
return statSync(pathName).isFile();
|
|
16397
|
+
} catch {
|
|
16398
|
+
return false;
|
|
16399
|
+
}
|
|
16400
|
+
}
|
|
16401
|
+
function resolveImportSource(source, importer, store) {
|
|
16402
|
+
if (!importer) return void 0;
|
|
16403
|
+
const isAbsolute = path.isAbsolute(source);
|
|
16404
|
+
if (!isAbsolute && !source.startsWith(".")) return void 0;
|
|
16405
|
+
const base = isAbsolute ? source : path.resolve(path.dirname(importer), source);
|
|
16406
|
+
const normalized = normalizeFileName(base);
|
|
16407
|
+
if (store.has(normalized)) return normalized;
|
|
16408
|
+
if (existsSync(normalized) && isFile(normalized)) return normalized;
|
|
16409
|
+
const ext = path.extname(normalized);
|
|
16410
|
+
if (!ext) {
|
|
16411
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
16412
|
+
const candidate = `${normalized}${suffix}`;
|
|
16413
|
+
if (store.has(candidate)) return candidate;
|
|
16414
|
+
if (existsSync(candidate) && isFile(candidate)) return candidate;
|
|
16415
|
+
}
|
|
16416
|
+
}
|
|
16417
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
16418
|
+
const candidate = path.join(normalized, `index${suffix}`);
|
|
16419
|
+
if (store.has(candidate)) return candidate;
|
|
16420
|
+
if (existsSync(candidate) && isFile(candidate)) return candidate;
|
|
16421
|
+
}
|
|
16422
|
+
return void 0;
|
|
16423
|
+
}
|
|
16424
|
+
function resolveModuleMetadata(source, importer, options) {
|
|
16425
|
+
if (options?.resolveModuleMetadata) {
|
|
16426
|
+
const resolved = options.resolveModuleMetadata(source, importer);
|
|
16427
|
+
if (resolved) return resolved;
|
|
16428
|
+
}
|
|
16429
|
+
const store = getMetadataStore(options);
|
|
16430
|
+
const resolvedKey = resolveImportSource(source, importer, store);
|
|
16431
|
+
if (resolvedKey) {
|
|
16432
|
+
return store.get(resolvedKey);
|
|
16433
|
+
}
|
|
16434
|
+
if (store.has(source)) return store.get(source);
|
|
16435
|
+
return void 0;
|
|
16436
|
+
}
|
|
16437
|
+
function setModuleMetadata(fileName, metadata, options) {
|
|
16438
|
+
if (!fileName) return;
|
|
16439
|
+
const store = getMetadataStore(options);
|
|
16440
|
+
store.set(normalizeFileName(fileName), metadata);
|
|
16441
|
+
}
|
|
16442
|
+
function clearModuleMetadata(options) {
|
|
16443
|
+
const store = getMetadataStore(options);
|
|
16444
|
+
store.clear();
|
|
16445
|
+
}
|
|
16446
|
+
|
|
16368
16447
|
// src/validation.ts
|
|
16369
16448
|
var DiagnosticMessages = {
|
|
16370
16449
|
["FICT-P001" /* FICT_P001 */]: "Props destructuring falls back to non-reactive binding.",
|
|
@@ -16557,6 +16636,23 @@ function buildPropsPlan(attributes, children, ctx, helpers) {
|
|
|
16557
16636
|
}
|
|
16558
16637
|
return false;
|
|
16559
16638
|
};
|
|
16639
|
+
const getBaseIdentifier2 = (expr) => {
|
|
16640
|
+
if (expr.kind === "Identifier") return expr.name;
|
|
16641
|
+
if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
|
|
16642
|
+
return getBaseIdentifier2(expr.object);
|
|
16643
|
+
}
|
|
16644
|
+
return null;
|
|
16645
|
+
};
|
|
16646
|
+
const isDynamicStoreMember = (expr) => {
|
|
16647
|
+
if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return false;
|
|
16648
|
+
if (!expr.computed) return false;
|
|
16649
|
+
if (expr.property.kind === "Literal" && (typeof expr.property.value === "string" || typeof expr.property.value === "number")) {
|
|
16650
|
+
return false;
|
|
16651
|
+
}
|
|
16652
|
+
const base = getBaseIdentifier2(expr.object);
|
|
16653
|
+
if (!base) return false;
|
|
16654
|
+
return ctx.storeVars?.has(helpers.deSSAVarName(base)) ?? false;
|
|
16655
|
+
};
|
|
16560
16656
|
const flushBucket = () => {
|
|
16561
16657
|
if (bucket.length === 0) return;
|
|
16562
16658
|
segments.push({ kind: "object", properties: bucket });
|
|
@@ -16628,13 +16724,15 @@ function buildPropsPlan(attributes, children, ctx, helpers) {
|
|
|
16628
16724
|
ctx
|
|
16629
16725
|
) : null;
|
|
16630
16726
|
const useMemoProp = usesTracked && trackedExpr && t4.isExpression(trackedExpr) && !t4.isIdentifier(trackedExpr) && !t4.isMemberExpression(trackedExpr) && !t4.isLiteral(trackedExpr);
|
|
16727
|
+
const forceMemoProp = usesTracked && isDynamicStoreMember(attr.value);
|
|
16728
|
+
const shouldMemoProp = useMemoProp || forceMemoProp;
|
|
16631
16729
|
const valueExpr = !isFunctionLike && isAccessorBase && baseIdent ? (() => {
|
|
16632
16730
|
ctx.helpersUsed.add("propGetter");
|
|
16633
16731
|
return t4.callExpression(t4.identifier(RUNTIME_ALIASES.propGetter), [
|
|
16634
16732
|
t4.arrowFunctionExpression([], t4.callExpression(t4.identifier(baseIdent), []))
|
|
16635
16733
|
]);
|
|
16636
16734
|
})() : usesTracked && t4.isExpression(lowered) ? (() => {
|
|
16637
|
-
if (
|
|
16735
|
+
if (shouldMemoProp) {
|
|
16638
16736
|
ctx.helpersUsed.add("prop");
|
|
16639
16737
|
return t4.callExpression(t4.identifier(RUNTIME_ALIASES.prop), [
|
|
16640
16738
|
t4.arrowFunctionExpression([], trackedExpr ?? lowered)
|
|
@@ -16827,7 +16925,13 @@ function rewriteExprWithMap(expr, rewrites) {
|
|
|
16827
16925
|
return {
|
|
16828
16926
|
...expr,
|
|
16829
16927
|
object: rewriteExprWithMap(expr.object, rewrites),
|
|
16830
|
-
property: rewriteExprWithMap(expr.property, rewrites)
|
|
16928
|
+
property: expr.computed ? rewriteExprWithMap(expr.property, rewrites) : expr.property
|
|
16929
|
+
};
|
|
16930
|
+
case "OptionalMemberExpression":
|
|
16931
|
+
return {
|
|
16932
|
+
...expr,
|
|
16933
|
+
object: rewriteExprWithMap(expr.object, rewrites),
|
|
16934
|
+
property: expr.computed ? rewriteExprWithMap(expr.property, rewrites) : expr.property
|
|
16831
16935
|
};
|
|
16832
16936
|
case "BinaryExpression":
|
|
16833
16937
|
case "LogicalExpression":
|
|
@@ -16850,11 +16954,12 @@ function rewriteExprWithMap(expr, rewrites) {
|
|
|
16850
16954
|
case "ObjectExpression":
|
|
16851
16955
|
return {
|
|
16852
16956
|
...expr,
|
|
16853
|
-
properties: expr.properties.map((p) =>
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16957
|
+
properties: expr.properties.map((p) => {
|
|
16958
|
+
if (p.kind === "SpreadElement") {
|
|
16959
|
+
return { ...p, argument: rewriteExprWithMap(p.argument, rewrites) };
|
|
16960
|
+
}
|
|
16961
|
+
return { ...p, value: rewriteExprWithMap(p.value, rewrites) };
|
|
16962
|
+
})
|
|
16858
16963
|
};
|
|
16859
16964
|
case "ImportExpression":
|
|
16860
16965
|
return {
|
|
@@ -16968,7 +17073,17 @@ function toSSA(fn) {
|
|
|
16968
17073
|
arguments: expr.arguments.map((a) => renameExpr(a))
|
|
16969
17074
|
};
|
|
16970
17075
|
case "MemberExpression":
|
|
16971
|
-
return {
|
|
17076
|
+
return {
|
|
17077
|
+
...expr,
|
|
17078
|
+
object: renameExpr(expr.object),
|
|
17079
|
+
property: expr.computed ? renameExpr(expr.property) : expr.property
|
|
17080
|
+
};
|
|
17081
|
+
case "OptionalMemberExpression":
|
|
17082
|
+
return {
|
|
17083
|
+
...expr,
|
|
17084
|
+
object: renameExpr(expr.object),
|
|
17085
|
+
property: expr.computed ? renameExpr(expr.property) : expr.property
|
|
17086
|
+
};
|
|
16972
17087
|
case "BinaryExpression":
|
|
16973
17088
|
case "LogicalExpression":
|
|
16974
17089
|
return { ...expr, left: renameExpr(expr.left), right: renameExpr(expr.right) };
|
|
@@ -16986,11 +17101,12 @@ function toSSA(fn) {
|
|
|
16986
17101
|
case "ObjectExpression":
|
|
16987
17102
|
return {
|
|
16988
17103
|
...expr,
|
|
16989
|
-
properties: expr.properties.map((p) =>
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
|
|
16993
|
-
|
|
17104
|
+
properties: expr.properties.map((p) => {
|
|
17105
|
+
if (p.kind === "SpreadElement") {
|
|
17106
|
+
return { ...p, argument: renameExpr(p.argument) };
|
|
17107
|
+
}
|
|
17108
|
+
return { ...p, value: renameExpr(p.value) };
|
|
17109
|
+
})
|
|
16994
17110
|
};
|
|
16995
17111
|
default:
|
|
16996
17112
|
return expr;
|
|
@@ -17485,8 +17601,8 @@ function mergeOverlappingScopes(scopes, _byName) {
|
|
|
17485
17601
|
scope.blocks.forEach((b) => merged.blocks.add(b));
|
|
17486
17602
|
scope.dependencies.forEach((d) => merged.dependencies.add(d));
|
|
17487
17603
|
for (const [base, paths] of scope.dependencyPaths) {
|
|
17488
|
-
for (const
|
|
17489
|
-
addPath(merged.dependencyPaths, base,
|
|
17604
|
+
for (const path2 of paths) {
|
|
17605
|
+
addPath(merged.dependencyPaths, base, path2);
|
|
17490
17606
|
}
|
|
17491
17607
|
}
|
|
17492
17608
|
merged.hasExternalEffect = merged.hasExternalEffect || scope.hasExternalEffect;
|
|
@@ -17580,12 +17696,12 @@ function collectExprReads(expr, into, paths, bound = /* @__PURE__ */ new Set(),
|
|
|
17580
17696
|
if (bound.has(baseName(expr.name))) return;
|
|
17581
17697
|
into.add(expr.name);
|
|
17582
17698
|
if (paths) {
|
|
17583
|
-
const
|
|
17699
|
+
const path2 = {
|
|
17584
17700
|
base: expr.name,
|
|
17585
17701
|
segments: [],
|
|
17586
17702
|
hasOptional: false
|
|
17587
17703
|
};
|
|
17588
|
-
addPath(paths, expr.name,
|
|
17704
|
+
addPath(paths, expr.name, path2);
|
|
17589
17705
|
}
|
|
17590
17706
|
return;
|
|
17591
17707
|
case "CallExpression": {
|
|
@@ -17741,11 +17857,11 @@ function collectExprReads(expr, into, paths, bound = /* @__PURE__ */ new Set(),
|
|
|
17741
17857
|
return;
|
|
17742
17858
|
}
|
|
17743
17859
|
}
|
|
17744
|
-
function addPath(paths, base,
|
|
17860
|
+
function addPath(paths, base, path2) {
|
|
17745
17861
|
const existing = paths.get(base) ?? [];
|
|
17746
|
-
const pathStr = pathToString(
|
|
17862
|
+
const pathStr = pathToString(path2);
|
|
17747
17863
|
if (!existing.some((p) => pathToString(p) === pathStr)) {
|
|
17748
|
-
existing.push(
|
|
17864
|
+
existing.push(path2);
|
|
17749
17865
|
paths.set(base, existing);
|
|
17750
17866
|
}
|
|
17751
17867
|
}
|
|
@@ -17764,11 +17880,11 @@ function analyzeOptionalChainDependencies(scope) {
|
|
|
17764
17880
|
} else {
|
|
17765
17881
|
let hasRequiredPath = false;
|
|
17766
17882
|
let hasOptionalOnlyPath = false;
|
|
17767
|
-
for (const
|
|
17768
|
-
if (!
|
|
17883
|
+
for (const path2 of paths) {
|
|
17884
|
+
if (!path2.hasOptional) {
|
|
17769
17885
|
hasRequiredPath = true;
|
|
17770
17886
|
} else {
|
|
17771
|
-
const firstOptionalIndex =
|
|
17887
|
+
const firstOptionalIndex = path2.segments.findIndex((s) => s.optional);
|
|
17772
17888
|
if (firstOptionalIndex === 0) {
|
|
17773
17889
|
hasOptionalOnlyPath = true;
|
|
17774
17890
|
} else if (firstOptionalIndex > 0) {
|
|
@@ -18519,12 +18635,23 @@ function createPropsShape() {
|
|
|
18519
18635
|
};
|
|
18520
18636
|
}
|
|
18521
18637
|
function cloneKeyContext(ctx) {
|
|
18522
|
-
|
|
18638
|
+
const cloneMap = (map) => {
|
|
18639
|
+
const next = /* @__PURE__ */ new Map();
|
|
18640
|
+
for (const [key, value] of map.entries()) {
|
|
18641
|
+
next.set(key, new Set(value));
|
|
18642
|
+
}
|
|
18643
|
+
return next;
|
|
18644
|
+
};
|
|
18645
|
+
return {
|
|
18646
|
+
values: cloneMap(ctx.values),
|
|
18647
|
+
keySets: cloneMap(ctx.keySets)
|
|
18648
|
+
};
|
|
18523
18649
|
}
|
|
18524
18650
|
function clearPatternBindings(pattern, ctx) {
|
|
18525
18651
|
if (!pattern || typeof pattern !== "object") return;
|
|
18526
18652
|
if (t2.isIdentifier(pattern)) {
|
|
18527
|
-
ctx.delete(pattern.name);
|
|
18653
|
+
ctx.values.delete(pattern.name);
|
|
18654
|
+
ctx.keySets.delete(pattern.name);
|
|
18528
18655
|
return;
|
|
18529
18656
|
}
|
|
18530
18657
|
if (t2.isRestElement(pattern)) {
|
|
@@ -18551,19 +18678,106 @@ function clearPatternBindings(pattern, ctx) {
|
|
|
18551
18678
|
}
|
|
18552
18679
|
}
|
|
18553
18680
|
}
|
|
18554
|
-
function
|
|
18681
|
+
function resolveNarrowedKeys(expr, ctx) {
|
|
18555
18682
|
if (expr.kind === "Literal") {
|
|
18556
18683
|
if (typeof expr.value === "string" || typeof expr.value === "number") {
|
|
18557
|
-
return expr.value;
|
|
18684
|
+
return /* @__PURE__ */ new Set([expr.value]);
|
|
18558
18685
|
}
|
|
18559
18686
|
return null;
|
|
18560
18687
|
}
|
|
18561
18688
|
if (expr.kind === "Identifier") {
|
|
18562
|
-
|
|
18689
|
+
const value = ctx.values.get(expr.name);
|
|
18690
|
+
return value ? new Set(value) : null;
|
|
18691
|
+
}
|
|
18692
|
+
if (expr.kind === "ConditionalExpression") {
|
|
18693
|
+
const consequent = resolveNarrowedKeys(expr.consequent, ctx);
|
|
18694
|
+
const alternate = resolveNarrowedKeys(expr.alternate, ctx);
|
|
18695
|
+
if (consequent && alternate) {
|
|
18696
|
+
return /* @__PURE__ */ new Set([...consequent, ...alternate]);
|
|
18697
|
+
}
|
|
18698
|
+
return null;
|
|
18699
|
+
}
|
|
18700
|
+
if (expr.kind === "SequenceExpression" && expr.expressions.length > 0) {
|
|
18701
|
+
const last = expr.expressions[expr.expressions.length - 1];
|
|
18702
|
+
return resolveNarrowedKeys(last, ctx);
|
|
18703
|
+
}
|
|
18704
|
+
if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
|
|
18705
|
+
if (expr.computed && expr.object.kind === "Identifier") {
|
|
18706
|
+
const keySet = ctx.keySets.get(expr.object.name);
|
|
18707
|
+
if (keySet && keySet.size > 0) {
|
|
18708
|
+
return new Set(keySet);
|
|
18709
|
+
}
|
|
18710
|
+
}
|
|
18711
|
+
}
|
|
18712
|
+
return null;
|
|
18713
|
+
}
|
|
18714
|
+
function resolveKeySet(expr, ctx) {
|
|
18715
|
+
if (expr.kind === "Identifier") {
|
|
18716
|
+
const set = ctx.keySets.get(expr.name);
|
|
18717
|
+
return set ? new Set(set) : null;
|
|
18718
|
+
}
|
|
18719
|
+
if (expr.kind === "ArrayExpression") {
|
|
18720
|
+
const values = [];
|
|
18721
|
+
for (const el of expr.elements) {
|
|
18722
|
+
if (!el) return null;
|
|
18723
|
+
if (el.kind !== "Literal") return null;
|
|
18724
|
+
if (typeof el.value !== "string" && typeof el.value !== "number") return null;
|
|
18725
|
+
values.push(el.value);
|
|
18726
|
+
}
|
|
18727
|
+
return values.length > 0 ? new Set(values) : null;
|
|
18728
|
+
}
|
|
18729
|
+
if (expr.kind === "CallExpression") {
|
|
18730
|
+
if (expr.callee.kind === "MemberExpression") {
|
|
18731
|
+
const object = expr.callee.object;
|
|
18732
|
+
const property = expr.callee.property;
|
|
18733
|
+
if (object.kind === "Identifier" && object.name === "Object" && !expr.callee.computed && property.kind === "Identifier" && property.name === "keys" && expr.arguments.length === 1) {
|
|
18734
|
+
const arg = expr.arguments[0];
|
|
18735
|
+
if (arg.kind === "ObjectExpression") {
|
|
18736
|
+
const values = [];
|
|
18737
|
+
for (const prop of arg.properties) {
|
|
18738
|
+
if (prop.kind !== "Property") return null;
|
|
18739
|
+
if (prop.key.kind === "Identifier") {
|
|
18740
|
+
values.push(prop.key.name);
|
|
18741
|
+
} else if (prop.key.kind === "Literal") {
|
|
18742
|
+
if (typeof prop.key.value !== "string" && typeof prop.key.value !== "number") {
|
|
18743
|
+
return null;
|
|
18744
|
+
}
|
|
18745
|
+
values.push(prop.key.value);
|
|
18746
|
+
} else {
|
|
18747
|
+
return null;
|
|
18748
|
+
}
|
|
18749
|
+
}
|
|
18750
|
+
return values.length > 0 ? new Set(values) : null;
|
|
18751
|
+
}
|
|
18752
|
+
}
|
|
18753
|
+
}
|
|
18754
|
+
}
|
|
18755
|
+
if (expr.kind === "ConditionalExpression") {
|
|
18756
|
+
const consequent = resolveKeySet(expr.consequent, ctx);
|
|
18757
|
+
const alternate = resolveKeySet(expr.alternate, ctx);
|
|
18758
|
+
if (consequent && alternate) {
|
|
18759
|
+
return /* @__PURE__ */ new Set([...consequent, ...alternate]);
|
|
18760
|
+
}
|
|
18761
|
+
return null;
|
|
18762
|
+
}
|
|
18763
|
+
if (expr.kind === "SequenceExpression" && expr.expressions.length > 0) {
|
|
18764
|
+
const last = expr.expressions[expr.expressions.length - 1];
|
|
18765
|
+
return resolveKeySet(last, ctx);
|
|
18563
18766
|
}
|
|
18564
18767
|
return null;
|
|
18565
18768
|
}
|
|
18566
18769
|
function extractEqualityNarrowing(expr) {
|
|
18770
|
+
if (expr.kind === "LogicalExpression" && expr.operator === "||") {
|
|
18771
|
+
const left = extractEqualityNarrowing(expr.left);
|
|
18772
|
+
const right = extractEqualityNarrowing(expr.right);
|
|
18773
|
+
if (left && right && left.kind === "eq" && right.kind === "eq" && left.name === right.name) {
|
|
18774
|
+
return {
|
|
18775
|
+
name: left.name,
|
|
18776
|
+
values: /* @__PURE__ */ new Set([...left.values, ...right.values]),
|
|
18777
|
+
kind: "eq"
|
|
18778
|
+
};
|
|
18779
|
+
}
|
|
18780
|
+
}
|
|
18567
18781
|
if (expr.kind !== "BinaryExpression") return null;
|
|
18568
18782
|
const isEq = expr.operator === "===";
|
|
18569
18783
|
const isNeq = expr.operator === "!==";
|
|
@@ -18578,17 +18792,55 @@ function extractEqualityNarrowing(expr) {
|
|
|
18578
18792
|
if (expr.left.kind === "Identifier") {
|
|
18579
18793
|
const value = literalValue(expr.right);
|
|
18580
18794
|
if (value !== null) {
|
|
18581
|
-
return { name: expr.left.name, value, kind: isEq ? "eq" : "neq" };
|
|
18795
|
+
return { name: expr.left.name, values: /* @__PURE__ */ new Set([value]), kind: isEq ? "eq" : "neq" };
|
|
18582
18796
|
}
|
|
18583
18797
|
}
|
|
18584
18798
|
if (expr.right.kind === "Identifier") {
|
|
18585
18799
|
const value = literalValue(expr.left);
|
|
18586
18800
|
if (value !== null) {
|
|
18587
|
-
return { name: expr.right.name, value, kind: isEq ? "eq" : "neq" };
|
|
18801
|
+
return { name: expr.right.name, values: /* @__PURE__ */ new Set([value]), kind: isEq ? "eq" : "neq" };
|
|
18588
18802
|
}
|
|
18589
18803
|
}
|
|
18590
18804
|
return null;
|
|
18591
18805
|
}
|
|
18806
|
+
function applyNarrowing(ctx, name, values) {
|
|
18807
|
+
const existing = ctx.values.get(name);
|
|
18808
|
+
if (!existing) {
|
|
18809
|
+
ctx.values.set(name, new Set(values));
|
|
18810
|
+
return;
|
|
18811
|
+
}
|
|
18812
|
+
const intersection = /* @__PURE__ */ new Set();
|
|
18813
|
+
for (const value of existing) {
|
|
18814
|
+
if (values.has(value)) intersection.add(value);
|
|
18815
|
+
}
|
|
18816
|
+
if (intersection.size > 0) {
|
|
18817
|
+
ctx.values.set(name, intersection);
|
|
18818
|
+
} else {
|
|
18819
|
+
ctx.values.delete(name);
|
|
18820
|
+
}
|
|
18821
|
+
}
|
|
18822
|
+
function applyKeyAssignment(ctx, name, expr) {
|
|
18823
|
+
ctx.values.delete(name);
|
|
18824
|
+
ctx.keySets.delete(name);
|
|
18825
|
+
let assignedKeys = null;
|
|
18826
|
+
let keySet = null;
|
|
18827
|
+
if (expr.kind === "Identifier") {
|
|
18828
|
+
assignedKeys = resolveNarrowedKeys(expr, ctx);
|
|
18829
|
+
keySet = resolveKeySet(expr, ctx);
|
|
18830
|
+
if (ctx.keySets.has(expr.name)) {
|
|
18831
|
+
ctx.keySets.delete(expr.name);
|
|
18832
|
+
}
|
|
18833
|
+
} else {
|
|
18834
|
+
assignedKeys = resolveNarrowedKeys(expr, ctx);
|
|
18835
|
+
keySet = resolveKeySet(expr, ctx);
|
|
18836
|
+
}
|
|
18837
|
+
if (assignedKeys && assignedKeys.size > 0) {
|
|
18838
|
+
ctx.values.set(name, new Set(assignedKeys));
|
|
18839
|
+
}
|
|
18840
|
+
if (keySet && keySet.size > 0) {
|
|
18841
|
+
ctx.keySets.set(name, new Set(keySet));
|
|
18842
|
+
}
|
|
18843
|
+
}
|
|
18592
18844
|
function mergeShapes(a, b) {
|
|
18593
18845
|
return {
|
|
18594
18846
|
knownKeys: /* @__PURE__ */ new Set([...a.knownKeys, ...b.knownKeys]),
|
|
@@ -18610,7 +18862,7 @@ function analyzeObjectShapes(fn) {
|
|
|
18610
18862
|
shapes.set(param.name, createUnknownShape({ kind: "param", name: param.name }));
|
|
18611
18863
|
}
|
|
18612
18864
|
}
|
|
18613
|
-
const baseCtx = /* @__PURE__ */ new Map();
|
|
18865
|
+
const baseCtx = { values: /* @__PURE__ */ new Map(), keySets: /* @__PURE__ */ new Map() };
|
|
18614
18866
|
let structured = null;
|
|
18615
18867
|
try {
|
|
18616
18868
|
structured = structurizeCFG(fn, {
|
|
@@ -18697,9 +18949,9 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18697
18949
|
const alternateCtx = cloneKeyContext(ctx);
|
|
18698
18950
|
if (narrowing) {
|
|
18699
18951
|
if (narrowing.kind === "eq") {
|
|
18700
|
-
consequentCtx
|
|
18952
|
+
applyNarrowing(consequentCtx, narrowing.name, narrowing.values);
|
|
18701
18953
|
} else {
|
|
18702
|
-
alternateCtx
|
|
18954
|
+
applyNarrowing(alternateCtx, narrowing.name, narrowing.values);
|
|
18703
18955
|
}
|
|
18704
18956
|
}
|
|
18705
18957
|
analyzeStructuredNode(node.consequent, shapes, propertyReads, consequentCtx);
|
|
@@ -18714,7 +18966,7 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18714
18966
|
for (const caseNode of node.cases) {
|
|
18715
18967
|
const caseCtx = cloneKeyContext(ctx);
|
|
18716
18968
|
if (discriminant && caseNode.test?.kind === "Literal" && (typeof caseNode.test.value === "string" || typeof caseNode.test.value === "number")) {
|
|
18717
|
-
caseCtx
|
|
18969
|
+
applyNarrowing(caseCtx, discriminant, /* @__PURE__ */ new Set([caseNode.test.value]));
|
|
18718
18970
|
}
|
|
18719
18971
|
analyzeStructuredNode(caseNode.body, shapes, propertyReads, caseCtx);
|
|
18720
18972
|
}
|
|
@@ -18745,7 +18997,8 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18745
18997
|
analyzeExpression(node.iterable, shapes, propertyReads, ctx);
|
|
18746
18998
|
{
|
|
18747
18999
|
const bodyCtx = cloneKeyContext(ctx);
|
|
18748
|
-
bodyCtx.delete(node.variable);
|
|
19000
|
+
bodyCtx.values.delete(node.variable);
|
|
19001
|
+
bodyCtx.keySets.delete(node.variable);
|
|
18749
19002
|
if (node.pattern) {
|
|
18750
19003
|
clearPatternBindings(node.pattern, bodyCtx);
|
|
18751
19004
|
}
|
|
@@ -18756,7 +19009,8 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18756
19009
|
analyzeExpression(node.object, shapes, propertyReads, ctx);
|
|
18757
19010
|
{
|
|
18758
19011
|
const bodyCtx = cloneKeyContext(ctx);
|
|
18759
|
-
bodyCtx.delete(node.variable);
|
|
19012
|
+
bodyCtx.values.delete(node.variable);
|
|
19013
|
+
bodyCtx.keySets.delete(node.variable);
|
|
18760
19014
|
if (node.pattern) {
|
|
18761
19015
|
clearPatternBindings(node.pattern, bodyCtx);
|
|
18762
19016
|
}
|
|
@@ -18768,7 +19022,8 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18768
19022
|
if (node.handler) {
|
|
18769
19023
|
const handlerCtx = cloneKeyContext(ctx);
|
|
18770
19024
|
if (node.handler.param) {
|
|
18771
|
-
handlerCtx.delete(node.handler.param);
|
|
19025
|
+
handlerCtx.values.delete(node.handler.param);
|
|
19026
|
+
handlerCtx.keySets.delete(node.handler.param);
|
|
18772
19027
|
}
|
|
18773
19028
|
analyzeStructuredNode(node.handler.body, shapes, propertyReads, handlerCtx);
|
|
18774
19029
|
}
|
|
@@ -18794,9 +19049,7 @@ function analyzeStructuredNode(node, shapes, propertyReads, ctx) {
|
|
|
18794
19049
|
}
|
|
18795
19050
|
function analyzeInstruction(instr, shapes, propertyReads, ctx) {
|
|
18796
19051
|
if (instr.kind === "Assign") {
|
|
18797
|
-
|
|
18798
|
-
ctx.delete(instr.target.name);
|
|
18799
|
-
}
|
|
19052
|
+
applyKeyAssignment(ctx, instr.target.name, instr.value);
|
|
18800
19053
|
const valueShape = analyzeExpression(instr.value, shapes, propertyReads, ctx);
|
|
18801
19054
|
if (valueShape) {
|
|
18802
19055
|
const existing = shapes.get(instr.target.name);
|
|
@@ -18853,12 +19106,14 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
18853
19106
|
const reads = propertyReads.get(base) ?? /* @__PURE__ */ new Set();
|
|
18854
19107
|
const baseShape = shapes.get(base);
|
|
18855
19108
|
if (directMember.computed) {
|
|
18856
|
-
const resolved =
|
|
18857
|
-
if (resolved
|
|
18858
|
-
const
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
baseShape
|
|
19109
|
+
const resolved = resolveNarrowedKeys(directMember.property, ctx);
|
|
19110
|
+
if (resolved && resolved.size > 0) {
|
|
19111
|
+
for (const value of resolved) {
|
|
19112
|
+
const key = String(value);
|
|
19113
|
+
reads.add(key);
|
|
19114
|
+
if (baseShape) {
|
|
19115
|
+
baseShape.knownKeys.add(key);
|
|
19116
|
+
}
|
|
18862
19117
|
}
|
|
18863
19118
|
} else if (baseShape) {
|
|
18864
19119
|
baseShape.dynamicAccess = true;
|
|
@@ -18880,6 +19135,34 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
18880
19135
|
return null;
|
|
18881
19136
|
}
|
|
18882
19137
|
case "CallExpression": {
|
|
19138
|
+
if (expr.callee.kind === "MemberExpression") {
|
|
19139
|
+
if (expr.callee.object.kind === "Identifier") {
|
|
19140
|
+
const baseName2 = expr.callee.object.name;
|
|
19141
|
+
const propName = !expr.callee.computed && expr.callee.property.kind === "Identifier" ? expr.callee.property.name : expr.callee.property.kind === "Literal" && typeof expr.callee.property.value === "string" ? expr.callee.property.value : null;
|
|
19142
|
+
if (propName && ctx.keySets.has(baseName2) && [
|
|
19143
|
+
"push",
|
|
19144
|
+
"pop",
|
|
19145
|
+
"shift",
|
|
19146
|
+
"unshift",
|
|
19147
|
+
"splice",
|
|
19148
|
+
"sort",
|
|
19149
|
+
"reverse",
|
|
19150
|
+
"copyWithin",
|
|
19151
|
+
"fill"
|
|
19152
|
+
].includes(propName)) {
|
|
19153
|
+
ctx.keySets.delete(baseName2);
|
|
19154
|
+
}
|
|
19155
|
+
}
|
|
19156
|
+
}
|
|
19157
|
+
for (const arg of expr.arguments) {
|
|
19158
|
+
if (arg.kind === "Identifier" && ctx.keySets.has(arg.name)) {
|
|
19159
|
+
ctx.keySets.delete(arg.name);
|
|
19160
|
+
} else if (arg.kind === "SpreadElement" && arg.argument.kind === "Identifier") {
|
|
19161
|
+
if (ctx.keySets.has(arg.argument.name)) {
|
|
19162
|
+
ctx.keySets.delete(arg.argument.name);
|
|
19163
|
+
}
|
|
19164
|
+
}
|
|
19165
|
+
}
|
|
18883
19166
|
for (const arg of expr.arguments) {
|
|
18884
19167
|
markEscaping(arg, shapes);
|
|
18885
19168
|
}
|
|
@@ -18931,9 +19214,7 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
18931
19214
|
}
|
|
18932
19215
|
case "AssignmentExpression": {
|
|
18933
19216
|
if (expr.left.kind === "Identifier") {
|
|
18934
|
-
|
|
18935
|
-
ctx.delete(expr.left.name);
|
|
18936
|
-
}
|
|
19217
|
+
applyKeyAssignment(ctx, expr.left.name, expr.right);
|
|
18937
19218
|
}
|
|
18938
19219
|
if (expr.left.kind === "MemberExpression") {
|
|
18939
19220
|
const base = getBaseIdentifier(expr.left.object);
|
|
@@ -18945,14 +19226,19 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
18945
19226
|
} else if (expr.left.property.kind === "Literal" && typeof expr.left.property.value === "string") {
|
|
18946
19227
|
shape.mutableKeys.add(expr.left.property.value);
|
|
18947
19228
|
} else {
|
|
18948
|
-
const resolved =
|
|
18949
|
-
if (resolved
|
|
18950
|
-
|
|
19229
|
+
const resolved = resolveNarrowedKeys(expr.left.property, ctx);
|
|
19230
|
+
if (resolved && resolved.size > 0) {
|
|
19231
|
+
for (const value of resolved) {
|
|
19232
|
+
shape.mutableKeys.add(String(value));
|
|
19233
|
+
}
|
|
18951
19234
|
} else {
|
|
18952
19235
|
shape.dynamicAccess = true;
|
|
18953
19236
|
}
|
|
18954
19237
|
}
|
|
18955
19238
|
}
|
|
19239
|
+
if (ctx.keySets.has(base)) {
|
|
19240
|
+
ctx.keySets.delete(base);
|
|
19241
|
+
}
|
|
18956
19242
|
}
|
|
18957
19243
|
}
|
|
18958
19244
|
analyzeExpression(expr.right, shapes, propertyReads, ctx);
|
|
@@ -18960,8 +19246,13 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
18960
19246
|
}
|
|
18961
19247
|
case "UpdateExpression": {
|
|
18962
19248
|
if (expr.argument.kind === "Identifier") {
|
|
18963
|
-
|
|
18964
|
-
|
|
19249
|
+
ctx.values.delete(expr.argument.name);
|
|
19250
|
+
ctx.keySets.delete(expr.argument.name);
|
|
19251
|
+
}
|
|
19252
|
+
if (expr.argument.kind === "MemberExpression") {
|
|
19253
|
+
const base = getBaseIdentifier(expr.argument.object);
|
|
19254
|
+
if (base) {
|
|
19255
|
+
ctx.keySets.delete(base);
|
|
18965
19256
|
}
|
|
18966
19257
|
}
|
|
18967
19258
|
analyzeExpression(expr.argument, shapes, propertyReads, ctx);
|
|
@@ -19393,7 +19684,11 @@ function expressionUsesTracked(expr, ctx) {
|
|
|
19393
19684
|
return ctx.trackedVars.has(deSSAVarName(expr.name)) || (ctx.externalTracked?.has(deSSAVarName(expr.name)) ?? false) || (ctx.memoVars?.has(deSSAVarName(expr.name)) ?? false) || (ctx.aliasVars?.has(deSSAVarName(expr.name)) ?? false);
|
|
19394
19685
|
case "MemberExpression":
|
|
19395
19686
|
case "OptionalMemberExpression":
|
|
19396
|
-
|
|
19687
|
+
if (expressionUsesTracked(expr.object, ctx)) return true;
|
|
19688
|
+
if (expr.computed && expr.property.kind !== "Literal") {
|
|
19689
|
+
return expressionUsesTracked(expr.property, ctx);
|
|
19690
|
+
}
|
|
19691
|
+
return false;
|
|
19397
19692
|
case "CallExpression":
|
|
19398
19693
|
case "OptionalCallExpression":
|
|
19399
19694
|
if (expressionUsesTracked(expr.callee, ctx)) return true;
|
|
@@ -21201,6 +21496,24 @@ function setNodeLoc(node, loc) {
|
|
|
21201
21496
|
node.loc = cloneLoc(loc) ?? null;
|
|
21202
21497
|
return node;
|
|
21203
21498
|
}
|
|
21499
|
+
function serializeHookReturnInfo(info) {
|
|
21500
|
+
const objectProps = info.objectProps ? Object.fromEntries(info.objectProps.entries()) : void 0;
|
|
21501
|
+
const arrayProps = info.arrayProps ? Object.fromEntries(Array.from(info.arrayProps.entries()).map(([k, v]) => [String(k), v])) : void 0;
|
|
21502
|
+
return {
|
|
21503
|
+
objectProps,
|
|
21504
|
+
arrayProps,
|
|
21505
|
+
directAccessor: info.directAccessor
|
|
21506
|
+
};
|
|
21507
|
+
}
|
|
21508
|
+
function deserializeHookReturnInfo(info) {
|
|
21509
|
+
const objectProps = info.objectProps ? new Map(Object.entries(info.objectProps)) : void 0;
|
|
21510
|
+
const arrayProps = info.arrayProps ? new Map(Object.entries(info.arrayProps).map(([k, v]) => [Number.parseInt(k, 10), v])) : void 0;
|
|
21511
|
+
return {
|
|
21512
|
+
objectProps,
|
|
21513
|
+
arrayProps,
|
|
21514
|
+
directAccessor: info.directAccessor
|
|
21515
|
+
};
|
|
21516
|
+
}
|
|
21204
21517
|
function propagateHookResultAlias(targetBase, value, ctx) {
|
|
21205
21518
|
const mapSource = (source) => {
|
|
21206
21519
|
const hookName = ctx.hookResultVarMap?.get(source);
|
|
@@ -21224,6 +21537,15 @@ function propagateHookResultAlias(targetBase, value, ctx) {
|
|
|
21224
21537
|
mapSource(deSSAVarName(firstArg.name));
|
|
21225
21538
|
}
|
|
21226
21539
|
}
|
|
21540
|
+
if (value.kind === "SequenceExpression" && value.expressions.length > 0) {
|
|
21541
|
+
const last = value.expressions[value.expressions.length - 1];
|
|
21542
|
+
if (last && last.kind === "CallExpression" && last.callee.kind === "Identifier" && last.callee.name === "__fictPropsRest") {
|
|
21543
|
+
const firstArg = last.arguments[0];
|
|
21544
|
+
if (firstArg && firstArg.kind === "Identifier") {
|
|
21545
|
+
mapSource(deSSAVarName(firstArg.name));
|
|
21546
|
+
}
|
|
21547
|
+
}
|
|
21548
|
+
}
|
|
21227
21549
|
}
|
|
21228
21550
|
function applyRegionToContext(ctx, region) {
|
|
21229
21551
|
const prevRegion = ctx.currentRegion;
|
|
@@ -21530,6 +21852,7 @@ function createCodegenContext(t4) {
|
|
|
21530
21852
|
aliasVars: /* @__PURE__ */ new Set(),
|
|
21531
21853
|
externalTracked: /* @__PURE__ */ new Set(),
|
|
21532
21854
|
storeVars: /* @__PURE__ */ new Set(),
|
|
21855
|
+
importedNamespaces: /* @__PURE__ */ new Map(),
|
|
21533
21856
|
signalVars: /* @__PURE__ */ new Set(),
|
|
21534
21857
|
functionVars: /* @__PURE__ */ new Set(),
|
|
21535
21858
|
memoVars: /* @__PURE__ */ new Set(),
|
|
@@ -22477,6 +22800,12 @@ function extractKeyFromMapCallback(callback) {
|
|
|
22477
22800
|
if (!jsx) return void 0;
|
|
22478
22801
|
return extractKeyFromAttributes(jsx.attributes);
|
|
22479
22802
|
}
|
|
22803
|
+
function buildOutputParams(fn, t4) {
|
|
22804
|
+
if (fn.rawParams && fn.rawParams.length > 0) {
|
|
22805
|
+
return fn.rawParams.map((param) => t4.cloneNode(param, true));
|
|
22806
|
+
}
|
|
22807
|
+
return fn.params.map((p) => t4.identifier(deSSAVarName(p.name)));
|
|
22808
|
+
}
|
|
22480
22809
|
function lowerTrackedExpression(expr, ctx) {
|
|
22481
22810
|
const regionOverride = ctx.inReturn && ctx.currentFnIsHook ? null : ctx.currentRegion ?? (ctx.trackedVars.size ? {
|
|
22482
22811
|
id: -1,
|
|
@@ -22770,6 +23099,171 @@ function collectRuntimeImportNames(body, t4) {
|
|
|
22770
23099
|
}
|
|
22771
23100
|
return imported;
|
|
22772
23101
|
}
|
|
23102
|
+
function addImportedReactiveBinding(name, kind, ctx) {
|
|
23103
|
+
const base = deSSAVarName(name);
|
|
23104
|
+
if (kind === "signal") {
|
|
23105
|
+
ctx.signalVars?.add(base);
|
|
23106
|
+
} else if (kind === "store") {
|
|
23107
|
+
ctx.storeVars?.add(base);
|
|
23108
|
+
} else if (kind === "memo") {
|
|
23109
|
+
ctx.memoVars?.add(base);
|
|
23110
|
+
}
|
|
23111
|
+
ctx.trackedVars.add(base);
|
|
23112
|
+
}
|
|
23113
|
+
function applyImportedReactiveMetadata(body, ctx, t4, options) {
|
|
23114
|
+
const importer = options?.filename;
|
|
23115
|
+
const namespaces = /* @__PURE__ */ new Map();
|
|
23116
|
+
for (const stmt of body) {
|
|
23117
|
+
if (!t4.isImportDeclaration(stmt)) continue;
|
|
23118
|
+
const meta = resolveModuleMetadata(stmt.source.value, importer, options);
|
|
23119
|
+
if (!meta) continue;
|
|
23120
|
+
for (const spec of stmt.specifiers) {
|
|
23121
|
+
if (t4.isImportSpecifier(spec)) {
|
|
23122
|
+
const importedName = t4.isIdentifier(spec.imported) ? spec.imported.name : String(spec.imported.value);
|
|
23123
|
+
const localName = spec.local.name;
|
|
23124
|
+
const kind = meta.exports[importedName];
|
|
23125
|
+
if (kind) {
|
|
23126
|
+
addImportedReactiveBinding(localName, kind, ctx);
|
|
23127
|
+
}
|
|
23128
|
+
const hookInfo = meta.hooks?.[importedName];
|
|
23129
|
+
if (hookInfo) {
|
|
23130
|
+
ctx.hookReturnInfo = ctx.hookReturnInfo ?? /* @__PURE__ */ new Map();
|
|
23131
|
+
ctx.hookReturnInfo.set(localName, deserializeHookReturnInfo(hookInfo));
|
|
23132
|
+
}
|
|
23133
|
+
continue;
|
|
23134
|
+
}
|
|
23135
|
+
if (t4.isImportDefaultSpecifier(spec)) {
|
|
23136
|
+
const localName = spec.local.name;
|
|
23137
|
+
const kind = meta.exports.default;
|
|
23138
|
+
if (kind) {
|
|
23139
|
+
addImportedReactiveBinding(localName, kind, ctx);
|
|
23140
|
+
}
|
|
23141
|
+
const hookInfo = meta.hooks?.default;
|
|
23142
|
+
if (hookInfo) {
|
|
23143
|
+
ctx.hookReturnInfo = ctx.hookReturnInfo ?? /* @__PURE__ */ new Map();
|
|
23144
|
+
ctx.hookReturnInfo.set(localName, deserializeHookReturnInfo(hookInfo));
|
|
23145
|
+
}
|
|
23146
|
+
continue;
|
|
23147
|
+
}
|
|
23148
|
+
if (t4.isImportNamespaceSpecifier(spec)) {
|
|
23149
|
+
namespaces.set(spec.local.name, meta);
|
|
23150
|
+
}
|
|
23151
|
+
}
|
|
23152
|
+
}
|
|
23153
|
+
if (namespaces.size > 0) {
|
|
23154
|
+
ctx.importedNamespaces = namespaces;
|
|
23155
|
+
}
|
|
23156
|
+
}
|
|
23157
|
+
function classifyReactiveExport(name, ctx) {
|
|
23158
|
+
const base = deSSAVarName(name);
|
|
23159
|
+
if (ctx.storeVars?.has(base)) return "store";
|
|
23160
|
+
if (ctx.signalVars?.has(base)) return "signal";
|
|
23161
|
+
if (ctx.aliasVars?.has(base)) return "signal";
|
|
23162
|
+
if (ctx.memoVars?.has(base)) return "memo";
|
|
23163
|
+
return null;
|
|
23164
|
+
}
|
|
23165
|
+
function buildModuleReactiveMetadata(body, ctx, t4, options, stateMacroNames, memoMacroNames) {
|
|
23166
|
+
const metadata = { exports: {} };
|
|
23167
|
+
const hookExports = {};
|
|
23168
|
+
const addExport = (exportName, localName) => {
|
|
23169
|
+
const kind = classifyReactiveExport(localName, ctx);
|
|
23170
|
+
if (kind) {
|
|
23171
|
+
metadata.exports[exportName] = kind;
|
|
23172
|
+
}
|
|
23173
|
+
const hookInfo = getHookReturnInfo(localName, ctx);
|
|
23174
|
+
if (hookInfo) {
|
|
23175
|
+
hookExports[exportName] = serializeHookReturnInfo(hookInfo);
|
|
23176
|
+
}
|
|
23177
|
+
};
|
|
23178
|
+
const addExportFromSource = (source, importedName, exportName) => {
|
|
23179
|
+
const sourceMeta = resolveModuleMetadata(source, options?.filename, options);
|
|
23180
|
+
if (!sourceMeta) return;
|
|
23181
|
+
const kind = sourceMeta.exports[importedName];
|
|
23182
|
+
if (kind) {
|
|
23183
|
+
metadata.exports[exportName] = kind;
|
|
23184
|
+
}
|
|
23185
|
+
const hookInfo = sourceMeta.hooks?.[importedName];
|
|
23186
|
+
if (hookInfo) {
|
|
23187
|
+
hookExports[exportName] = hookInfo;
|
|
23188
|
+
}
|
|
23189
|
+
};
|
|
23190
|
+
const addDefaultExportKind = (kind) => {
|
|
23191
|
+
if (kind) {
|
|
23192
|
+
metadata.exports.default = kind;
|
|
23193
|
+
}
|
|
23194
|
+
};
|
|
23195
|
+
for (const stmt of body) {
|
|
23196
|
+
if (t4.isExportNamedDeclaration(stmt)) {
|
|
23197
|
+
if (stmt.source && stmt.specifiers.length > 0) {
|
|
23198
|
+
for (const spec of stmt.specifiers) {
|
|
23199
|
+
if (!t4.isExportSpecifier(spec)) continue;
|
|
23200
|
+
const importedName = spec.local.name;
|
|
23201
|
+
const exportName = t4.isIdentifier(spec.exported) ? spec.exported.name : t4.isStringLiteral(spec.exported) ? spec.exported.value : String(spec.exported);
|
|
23202
|
+
addExportFromSource(stmt.source.value, importedName, exportName);
|
|
23203
|
+
}
|
|
23204
|
+
continue;
|
|
23205
|
+
}
|
|
23206
|
+
if (stmt.declaration) {
|
|
23207
|
+
const decl = stmt.declaration;
|
|
23208
|
+
if (t4.isFunctionDeclaration(decl) && decl.id) {
|
|
23209
|
+
addExport(decl.id.name, decl.id.name);
|
|
23210
|
+
} else if (t4.isClassDeclaration(decl) && decl.id) {
|
|
23211
|
+
addExport(decl.id.name, decl.id.name);
|
|
23212
|
+
} else if (t4.isVariableDeclaration(decl)) {
|
|
23213
|
+
for (const v of decl.declarations) {
|
|
23214
|
+
if (t4.isIdentifier(v.id)) {
|
|
23215
|
+
addExport(v.id.name, v.id.name);
|
|
23216
|
+
}
|
|
23217
|
+
}
|
|
23218
|
+
}
|
|
23219
|
+
} else {
|
|
23220
|
+
for (const spec of stmt.specifiers) {
|
|
23221
|
+
if (!t4.isExportSpecifier(spec)) continue;
|
|
23222
|
+
const localName = spec.local.name;
|
|
23223
|
+
const exportName = t4.isIdentifier(spec.exported) ? spec.exported.name : t4.isStringLiteral(spec.exported) ? spec.exported.value : String(spec.exported);
|
|
23224
|
+
addExport(exportName, localName);
|
|
23225
|
+
}
|
|
23226
|
+
}
|
|
23227
|
+
continue;
|
|
23228
|
+
}
|
|
23229
|
+
if (t4.isExportAllDeclaration(stmt)) {
|
|
23230
|
+
const sourceMeta = resolveModuleMetadata(stmt.source.value, options?.filename, options);
|
|
23231
|
+
if (!sourceMeta) continue;
|
|
23232
|
+
for (const [exportName, kind] of Object.entries(sourceMeta.exports)) {
|
|
23233
|
+
if (exportName === "default") continue;
|
|
23234
|
+
metadata.exports[exportName] = kind;
|
|
23235
|
+
}
|
|
23236
|
+
if (sourceMeta.hooks) {
|
|
23237
|
+
for (const [exportName, info] of Object.entries(sourceMeta.hooks)) {
|
|
23238
|
+
if (exportName === "default") continue;
|
|
23239
|
+
hookExports[exportName] = info;
|
|
23240
|
+
}
|
|
23241
|
+
}
|
|
23242
|
+
continue;
|
|
23243
|
+
}
|
|
23244
|
+
if (t4.isExportDefaultDeclaration(stmt)) {
|
|
23245
|
+
const decl = stmt.declaration;
|
|
23246
|
+
if (t4.isIdentifier(decl)) {
|
|
23247
|
+
addExport("default", decl.name);
|
|
23248
|
+
} else if (t4.isFunctionDeclaration(decl) && decl.id) {
|
|
23249
|
+
addExport("default", decl.id.name);
|
|
23250
|
+
} else if (t4.isClassDeclaration(decl) && decl.id) {
|
|
23251
|
+
addExport("default", decl.id.name);
|
|
23252
|
+
} else if (t4.isCallExpression(decl) && t4.isIdentifier(decl.callee)) {
|
|
23253
|
+
const callee = decl.callee.name;
|
|
23254
|
+
if (stateMacroNames.has(callee) || callee === "$store") {
|
|
23255
|
+
addDefaultExportKind(callee === "$store" ? "store" : "signal");
|
|
23256
|
+
} else if (memoMacroNames.has(callee)) {
|
|
23257
|
+
addDefaultExportKind("memo");
|
|
23258
|
+
}
|
|
23259
|
+
}
|
|
23260
|
+
}
|
|
23261
|
+
}
|
|
23262
|
+
if (Object.keys(hookExports).length > 0) {
|
|
23263
|
+
metadata.hooks = hookExports;
|
|
23264
|
+
}
|
|
23265
|
+
return metadata;
|
|
23266
|
+
}
|
|
22773
23267
|
function collectLocalDeclaredNames(params, blocks, t4) {
|
|
22774
23268
|
const declared = /* @__PURE__ */ new Set();
|
|
22775
23269
|
const addPatternNames = (pattern) => {
|
|
@@ -23078,6 +23572,24 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
|
23078
23572
|
if (matchesListKeyPattern(expr, ctx)) {
|
|
23079
23573
|
return t4.identifier(ctx.listKeyParamName);
|
|
23080
23574
|
}
|
|
23575
|
+
if (expr.object.kind === "Identifier") {
|
|
23576
|
+
const nsMeta = ctx.importedNamespaces?.get(deSSAVarName(expr.object.name));
|
|
23577
|
+
if (nsMeta) {
|
|
23578
|
+
const propName = getStaticPropName(expr.property, expr.computed);
|
|
23579
|
+
if (typeof propName === "string") {
|
|
23580
|
+
const kind = nsMeta.exports[propName];
|
|
23581
|
+
if (kind === "signal" || kind === "memo") {
|
|
23582
|
+
const member = t4.memberExpression(
|
|
23583
|
+
t4.identifier(deSSAVarName(expr.object.name)),
|
|
23584
|
+
expr.computed ? t4.stringLiteral(propName) : t4.identifier(propName),
|
|
23585
|
+
expr.computed,
|
|
23586
|
+
expr.optional
|
|
23587
|
+
);
|
|
23588
|
+
return t4.callExpression(member, []);
|
|
23589
|
+
}
|
|
23590
|
+
}
|
|
23591
|
+
}
|
|
23592
|
+
}
|
|
23081
23593
|
if (expr.object.kind === "Identifier" && ctx.hookResultVarMap?.has(deSSAVarName(expr.object.name))) {
|
|
23082
23594
|
const hookName = ctx.hookResultVarMap.get(deSSAVarName(expr.object.name));
|
|
23083
23595
|
const info = getHookReturnInfo(hookName, ctx);
|
|
@@ -23569,8 +24081,8 @@ function collectExpressionDependencies(expr, deps) {
|
|
|
23569
24081
|
return;
|
|
23570
24082
|
}
|
|
23571
24083
|
if (expr.kind === "MemberExpression") {
|
|
23572
|
-
const
|
|
23573
|
-
if (
|
|
24084
|
+
const path2 = getMemberDependencyPath(expr);
|
|
24085
|
+
if (path2) deps.add(path2);
|
|
23574
24086
|
collectExpressionDependencies(expr.object, deps);
|
|
23575
24087
|
if (expr.computed && expr.property.kind !== "Literal") {
|
|
23576
24088
|
collectExpressionDependencies(expr.property, deps);
|
|
@@ -23755,9 +24267,9 @@ function replaceIdentifiersWithOverrides(node, overrides, t4, parentKind, parent
|
|
|
23755
24267
|
if (!skipCurrentNode && (t4.isMemberExpression(node) || t4.isOptionalMemberExpression(node))) {
|
|
23756
24268
|
const propertyNode = node.property;
|
|
23757
24269
|
const isDynamicComputed = (node.computed ?? false) && !t4.isStringLiteral(propertyNode) && !t4.isNumericLiteral(propertyNode);
|
|
23758
|
-
const
|
|
23759
|
-
const normalized =
|
|
23760
|
-
const override = normalized && overrides[normalized] || (
|
|
24270
|
+
const path2 = getDependencyPathFromNode(node, t4);
|
|
24271
|
+
const normalized = path2 ? normalizeDependencyKey2(path2) : null;
|
|
24272
|
+
const override = normalized && overrides[normalized] || (path2 ? overrides[path2] : void 0);
|
|
23761
24273
|
if (override && !isCallTarget && !isDynamicComputed) {
|
|
23762
24274
|
const replacement = override();
|
|
23763
24275
|
Object.assign(node, replacement);
|
|
@@ -24488,11 +25000,11 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
24488
25000
|
}
|
|
24489
25001
|
return t4.callExpression(t4.arrowFunctionExpression([], body), []);
|
|
24490
25002
|
}
|
|
24491
|
-
function resolveHIRBindingPath(
|
|
24492
|
-
const key =
|
|
25003
|
+
function resolveHIRBindingPath(path2, cache, statements, ctx) {
|
|
25004
|
+
const key = path2.join(",");
|
|
24493
25005
|
if (cache.has(key)) return cache.get(key);
|
|
24494
25006
|
const { t: t4 } = ctx;
|
|
24495
|
-
const ancestorPath = [...
|
|
25007
|
+
const ancestorPath = [...path2];
|
|
24496
25008
|
let ancestorId;
|
|
24497
25009
|
let relativePath = [];
|
|
24498
25010
|
while (ancestorPath.length > 0) {
|
|
@@ -24500,13 +25012,13 @@ function resolveHIRBindingPath(path, cache, statements, ctx) {
|
|
|
24500
25012
|
const ancestorKey = ancestorPath.join(",");
|
|
24501
25013
|
if (cache.has(ancestorKey)) {
|
|
24502
25014
|
ancestorId = cache.get(ancestorKey);
|
|
24503
|
-
relativePath =
|
|
25015
|
+
relativePath = path2.slice(ancestorPath.length);
|
|
24504
25016
|
break;
|
|
24505
25017
|
}
|
|
24506
25018
|
}
|
|
24507
25019
|
if (!ancestorId) {
|
|
24508
25020
|
ancestorId = cache.get("");
|
|
24509
|
-
relativePath =
|
|
25021
|
+
relativePath = path2;
|
|
24510
25022
|
}
|
|
24511
25023
|
let currentExpr = ancestorId;
|
|
24512
25024
|
for (const index of relativePath) {
|
|
@@ -25315,6 +25827,7 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
|
|
|
25315
25827
|
const originalBody = program.originalBody ?? [];
|
|
25316
25828
|
ctx.moduleDeclaredNames = collectDeclaredNames(originalBody, t4);
|
|
25317
25829
|
ctx.moduleRuntimeNames = collectRuntimeImportNames(originalBody, t4);
|
|
25830
|
+
applyImportedReactiveMetadata(originalBody, ctx, t4, options);
|
|
25318
25831
|
const stateMacroNames = /* @__PURE__ */ new Set(["$state", ...macroAliases?.state ?? []]);
|
|
25319
25832
|
const memoMacroNames = new Set(macroAliases?.memo ?? ctx.memoMacroNames ?? []);
|
|
25320
25833
|
if (!memoMacroNames.has("$memo")) memoMacroNames.add("$memo");
|
|
@@ -25554,6 +26067,15 @@ function lowerHIRWithRegions(program, t4, options, macroAliases) {
|
|
|
25554
26067
|
ctx.helpersUsed.add("popContext");
|
|
25555
26068
|
body.push(t4.expressionStatement(t4.callExpression(t4.identifier(RUNTIME_ALIASES.popContext), [])));
|
|
25556
26069
|
}
|
|
26070
|
+
const moduleMeta = buildModuleReactiveMetadata(
|
|
26071
|
+
originalBody,
|
|
26072
|
+
ctx,
|
|
26073
|
+
t4,
|
|
26074
|
+
options,
|
|
26075
|
+
stateMacroNames,
|
|
26076
|
+
memoMacroNames
|
|
26077
|
+
);
|
|
26078
|
+
setModuleMetadata(options?.filename, moduleMeta, options);
|
|
25557
26079
|
return t4.file(t4.program(attachHelperImports(ctx, body, t4)));
|
|
25558
26080
|
}
|
|
25559
26081
|
function lowerTopLevelStatementBlock(statements, ctx, t4, name = "__module_segment", existingAliases) {
|
|
@@ -26034,7 +26556,7 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
26034
26556
|
if (!hasComplexControlFlow && !isAsync) {
|
|
26035
26557
|
const pureDeclaredVars = /* @__PURE__ */ new Set();
|
|
26036
26558
|
const pureStatements = lowerStructuredNodeWithoutRegions(structured, t4, ctx, pureDeclaredVars);
|
|
26037
|
-
const params2 = fn
|
|
26559
|
+
const params2 = buildOutputParams(fn, t4);
|
|
26038
26560
|
const funcDecl2 = setNodeLoc(
|
|
26039
26561
|
t4.functionDeclaration(
|
|
26040
26562
|
t4.identifier(fn.name ?? "fn"),
|
|
@@ -26109,13 +26631,31 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
26109
26631
|
)
|
|
26110
26632
|
);
|
|
26111
26633
|
}
|
|
26112
|
-
let finalParams = fn
|
|
26634
|
+
let finalParams = buildOutputParams(fn, t4);
|
|
26113
26635
|
const propsDestructuring = [];
|
|
26114
26636
|
if (isComponent && fn.rawParams && fn.rawParams.length === 1) {
|
|
26115
26637
|
const rawParam = fn.rawParams[0];
|
|
26116
26638
|
if (rawParam && (rawParam.type === "ObjectPattern" || rawParam.type === "AssignmentPattern" && rawParam.left?.type === "ObjectPattern")) {
|
|
26117
|
-
finalParams = [t4.identifier("__props")];
|
|
26118
26639
|
const pattern = rawParam.type === "AssignmentPattern" ? rawParam.left : rawParam;
|
|
26640
|
+
const defaultExpr = rawParam.type === "AssignmentPattern" ? rawParam.right : null;
|
|
26641
|
+
if (defaultExpr) {
|
|
26642
|
+
const propsParamName = "__propsParam";
|
|
26643
|
+
finalParams = [t4.identifier(propsParamName)];
|
|
26644
|
+
propsDestructuring.push(
|
|
26645
|
+
t4.variableDeclaration("const", [
|
|
26646
|
+
t4.variableDeclarator(
|
|
26647
|
+
t4.identifier("__props"),
|
|
26648
|
+
t4.conditionalExpression(
|
|
26649
|
+
t4.binaryExpression("===", t4.identifier(propsParamName), t4.identifier("undefined")),
|
|
26650
|
+
t4.cloneNode(defaultExpr, true),
|
|
26651
|
+
t4.identifier(propsParamName)
|
|
26652
|
+
)
|
|
26653
|
+
)
|
|
26654
|
+
])
|
|
26655
|
+
);
|
|
26656
|
+
} else {
|
|
26657
|
+
finalParams = [t4.identifier("__props")];
|
|
26658
|
+
}
|
|
26119
26659
|
if (propsDestructurePlan) {
|
|
26120
26660
|
if (propsDestructurePlan.usesProp) {
|
|
26121
26661
|
ctx.helpersUsed.add("prop");
|
|
@@ -26273,7 +26813,7 @@ function optimizeHIR(program, options = {}) {
|
|
|
26273
26813
|
originalBody: []
|
|
26274
26814
|
});
|
|
26275
26815
|
const ssaFn = ssaProgram.functions[0];
|
|
26276
|
-
return ssaFn ? optimizeSSAFunction(ssaFn) : fn;
|
|
26816
|
+
return ssaFn ? optimizeSSAFunction(ssaFn, options) : fn;
|
|
26277
26817
|
}
|
|
26278
26818
|
if (isReactiveOptimizationCandidate(fn)) {
|
|
26279
26819
|
return optimizeReactiveFunction(fn, exportedNames, options);
|
|
@@ -26285,9 +26825,9 @@ function optimizeHIR(program, options = {}) {
|
|
|
26285
26825
|
functions
|
|
26286
26826
|
};
|
|
26287
26827
|
}
|
|
26288
|
-
function optimizeSSAFunction(fn) {
|
|
26828
|
+
function optimizeSSAFunction(fn, options) {
|
|
26289
26829
|
let current = fn;
|
|
26290
|
-
current = propagateConstants(current);
|
|
26830
|
+
current = propagateConstants(current, options);
|
|
26291
26831
|
const purity = buildPurityContext(current);
|
|
26292
26832
|
current = eliminateCommonSubexpressions(current, purity);
|
|
26293
26833
|
current = inlineSingleUse(current, purity);
|
|
@@ -26912,7 +27452,9 @@ function optimizeReactiveFunction(fn, exportedNames, options) {
|
|
|
26912
27452
|
const reactive = buildReactiveContext(fn);
|
|
26913
27453
|
const purity = buildPurityContext(fn);
|
|
26914
27454
|
const hookLike = isHookLikeFunction(fn);
|
|
26915
|
-
const transformedBlocks = fn.blocks.map(
|
|
27455
|
+
const transformedBlocks = fn.blocks.map(
|
|
27456
|
+
(block) => optimizeReactiveBlock(block, reactive, purity, options)
|
|
27457
|
+
);
|
|
26916
27458
|
let transformed = { ...fn, blocks: transformedBlocks };
|
|
26917
27459
|
if (isCrossBlockConstPropagationEnabled()) {
|
|
26918
27460
|
transformed = propagateCrossBlockConstants(transformed, reactive, purity, scopeResult);
|
|
@@ -26947,7 +27489,7 @@ function optimizeReactiveFunction(fn, exportedNames, options) {
|
|
|
26947
27489
|
});
|
|
26948
27490
|
return { ...transformed, blocks };
|
|
26949
27491
|
}
|
|
26950
|
-
function optimizeReactiveBlock(block, reactive, purity) {
|
|
27492
|
+
function optimizeReactiveBlock(block, reactive, purity, options) {
|
|
26951
27493
|
const constants = /* @__PURE__ */ new Map();
|
|
26952
27494
|
const constObjects = /* @__PURE__ */ new Map();
|
|
26953
27495
|
const constArrays = /* @__PURE__ */ new Map();
|
|
@@ -26985,7 +27527,7 @@ function optimizeReactiveBlock(block, reactive, purity) {
|
|
|
26985
27527
|
constArrays.delete(name);
|
|
26986
27528
|
}
|
|
26987
27529
|
const dependsOnReactiveValue = expressionDependsOnReactive(instr.value, reactive);
|
|
26988
|
-
let value = dependsOnReactiveValue ? instr.value : foldExpressionWithConstants(instr.value, constants, constObjects, constArrays);
|
|
27530
|
+
let value = dependsOnReactiveValue ? instr.value : foldExpressionWithConstants(instr.value, constants, options, constObjects, constArrays);
|
|
26989
27531
|
const allowCSE = isCompilerGeneratedName(target) && (!declKind || declKind === "const");
|
|
26990
27532
|
if (allowCSE && isPureExpression(value, purity) && !isExplicitMemoCall(value, purity) && !dependsOnReactiveValue && isCSESafeExpression(value, purity)) {
|
|
26991
27533
|
const deps = collectExpressionIdentifiers2(value, true);
|
|
@@ -27033,7 +27575,7 @@ function optimizeReactiveBlock(block, reactive, purity) {
|
|
|
27033
27575
|
constArrays.delete(name);
|
|
27034
27576
|
}
|
|
27035
27577
|
const dependsOnReactiveValue = expressionDependsOnReactive(instr.value, reactive);
|
|
27036
|
-
const value = dependsOnReactiveValue ? instr.value : foldExpressionWithConstants(instr.value, constants, constObjects, constArrays);
|
|
27578
|
+
const value = dependsOnReactiveValue ? instr.value : foldExpressionWithConstants(instr.value, constants, options, constObjects, constArrays);
|
|
27037
27579
|
instructions.push(value === instr.value ? instr : { ...instr, value });
|
|
27038
27580
|
continue;
|
|
27039
27581
|
}
|
|
@@ -27042,6 +27584,7 @@ function optimizeReactiveBlock(block, reactive, purity) {
|
|
|
27042
27584
|
const terminator = foldTerminatorWithConstants(
|
|
27043
27585
|
block.terminator,
|
|
27044
27586
|
constants,
|
|
27587
|
+
options,
|
|
27045
27588
|
reactive,
|
|
27046
27589
|
constObjects,
|
|
27047
27590
|
constArrays
|
|
@@ -27973,7 +28516,7 @@ function blocksContainImpureMarkers(blocks) {
|
|
|
27973
28516
|
}
|
|
27974
28517
|
return false;
|
|
27975
28518
|
}
|
|
27976
|
-
function propagateConstants(fn) {
|
|
28519
|
+
function propagateConstants(fn, options) {
|
|
27977
28520
|
const constants = computeConstantMap(fn);
|
|
27978
28521
|
if (constants.size === 0) return fn;
|
|
27979
28522
|
const blocks = fn.blocks.map((block) => ({
|
|
@@ -27981,12 +28524,12 @@ function propagateConstants(fn) {
|
|
|
27981
28524
|
instructions: block.instructions.map((instr) => {
|
|
27982
28525
|
if (instr.kind === "Assign") {
|
|
27983
28526
|
const replaced = replaceIdentifiersWithConstants(instr.value, constants);
|
|
27984
|
-
const folded = foldExpression(replaced, constants);
|
|
28527
|
+
const folded = foldExpression(replaced, constants, options);
|
|
27985
28528
|
return { ...instr, value: folded };
|
|
27986
28529
|
}
|
|
27987
28530
|
if (instr.kind === "Expression") {
|
|
27988
28531
|
const replaced = replaceIdentifiersWithConstants(instr.value, constants);
|
|
27989
|
-
const folded = foldExpression(replaced, constants);
|
|
28532
|
+
const folded = foldExpression(replaced, constants, options);
|
|
27990
28533
|
return { ...instr, value: folded };
|
|
27991
28534
|
}
|
|
27992
28535
|
if (instr.kind === "Phi") {
|
|
@@ -28386,15 +28929,18 @@ function evaluateBinary(operator, left, right) {
|
|
|
28386
28929
|
return UNKNOWN_CONST;
|
|
28387
28930
|
}
|
|
28388
28931
|
}
|
|
28389
|
-
function foldExpression(expr, constants) {
|
|
28932
|
+
function foldExpression(expr, constants, options) {
|
|
28390
28933
|
const value = evaluateConstant(expr, constants);
|
|
28391
28934
|
if (value === UNKNOWN_CONST) {
|
|
28392
|
-
return simplifyAlgebraically(expr, constants);
|
|
28935
|
+
return simplifyAlgebraically(expr, constants, options);
|
|
28393
28936
|
}
|
|
28394
28937
|
return { kind: "Literal", value, loc: expr.loc };
|
|
28395
28938
|
}
|
|
28396
|
-
function simplifyAlgebraically(expr, constants) {
|
|
28397
|
-
const simplified = simplifyChildren(expr, constants);
|
|
28939
|
+
function simplifyAlgebraically(expr, constants, options) {
|
|
28940
|
+
const simplified = simplifyChildren(expr, constants, options);
|
|
28941
|
+
if (options.optimizeLevel === "safe") {
|
|
28942
|
+
return simplified;
|
|
28943
|
+
}
|
|
28398
28944
|
if (simplified.kind === "BinaryExpression") {
|
|
28399
28945
|
const { operator, left, right, loc } = simplified;
|
|
28400
28946
|
switch (operator) {
|
|
@@ -28473,37 +29019,37 @@ function simplifyAlgebraically(expr, constants) {
|
|
|
28473
29019
|
}
|
|
28474
29020
|
return simplified;
|
|
28475
29021
|
}
|
|
28476
|
-
function simplifyChildren(expr, constants) {
|
|
29022
|
+
function simplifyChildren(expr, constants, options) {
|
|
28477
29023
|
switch (expr.kind) {
|
|
28478
29024
|
case "BinaryExpression":
|
|
28479
29025
|
return {
|
|
28480
29026
|
...expr,
|
|
28481
|
-
left: simplifyAlgebraically(expr.left, constants),
|
|
28482
|
-
right: simplifyAlgebraically(expr.right, constants)
|
|
29027
|
+
left: simplifyAlgebraically(expr.left, constants, options),
|
|
29028
|
+
right: simplifyAlgebraically(expr.right, constants, options)
|
|
28483
29029
|
};
|
|
28484
29030
|
case "LogicalExpression":
|
|
28485
29031
|
return {
|
|
28486
29032
|
...expr,
|
|
28487
|
-
left: simplifyAlgebraically(expr.left, constants),
|
|
28488
|
-
right: simplifyAlgebraically(expr.right, constants)
|
|
29033
|
+
left: simplifyAlgebraically(expr.left, constants, options),
|
|
29034
|
+
right: simplifyAlgebraically(expr.right, constants, options)
|
|
28489
29035
|
};
|
|
28490
29036
|
case "UnaryExpression":
|
|
28491
29037
|
return {
|
|
28492
29038
|
...expr,
|
|
28493
|
-
argument: simplifyAlgebraically(expr.argument, constants)
|
|
29039
|
+
argument: simplifyAlgebraically(expr.argument, constants, options)
|
|
28494
29040
|
};
|
|
28495
29041
|
case "ConditionalExpression":
|
|
28496
29042
|
return {
|
|
28497
29043
|
...expr,
|
|
28498
|
-
test: simplifyAlgebraically(expr.test, constants),
|
|
28499
|
-
consequent: simplifyAlgebraically(expr.consequent, constants),
|
|
28500
|
-
alternate: simplifyAlgebraically(expr.alternate, constants)
|
|
29044
|
+
test: simplifyAlgebraically(expr.test, constants, options),
|
|
29045
|
+
consequent: simplifyAlgebraically(expr.consequent, constants, options),
|
|
29046
|
+
alternate: simplifyAlgebraically(expr.alternate, constants, options)
|
|
28501
29047
|
};
|
|
28502
29048
|
case "ArrayExpression":
|
|
28503
29049
|
return {
|
|
28504
29050
|
...expr,
|
|
28505
29051
|
elements: expr.elements.map(
|
|
28506
|
-
(el) => el ? simplifyAlgebraically(el, constants) : el
|
|
29052
|
+
(el) => el ? simplifyAlgebraically(el, constants, options) : el
|
|
28507
29053
|
)
|
|
28508
29054
|
};
|
|
28509
29055
|
case "ObjectExpression":
|
|
@@ -28513,13 +29059,13 @@ function simplifyChildren(expr, constants) {
|
|
|
28513
29059
|
if (prop.kind === "Property") {
|
|
28514
29060
|
return {
|
|
28515
29061
|
...prop,
|
|
28516
|
-
value: simplifyAlgebraically(prop.value, constants)
|
|
29062
|
+
value: simplifyAlgebraically(prop.value, constants, options)
|
|
28517
29063
|
};
|
|
28518
29064
|
}
|
|
28519
29065
|
if (prop.kind === "SpreadElement") {
|
|
28520
29066
|
return {
|
|
28521
29067
|
...prop,
|
|
28522
|
-
argument: simplifyAlgebraically(prop.argument, constants)
|
|
29068
|
+
argument: simplifyAlgebraically(prop.argument, constants, options)
|
|
28523
29069
|
};
|
|
28524
29070
|
}
|
|
28525
29071
|
return prop;
|
|
@@ -28529,35 +29075,35 @@ function simplifyChildren(expr, constants) {
|
|
|
28529
29075
|
case "OptionalCallExpression":
|
|
28530
29076
|
return {
|
|
28531
29077
|
...expr,
|
|
28532
|
-
arguments: expr.arguments.map((arg) => simplifyAlgebraically(arg, constants))
|
|
29078
|
+
arguments: expr.arguments.map((arg) => simplifyAlgebraically(arg, constants, options))
|
|
28533
29079
|
};
|
|
28534
29080
|
case "ImportExpression":
|
|
28535
29081
|
return {
|
|
28536
29082
|
...expr,
|
|
28537
|
-
source: simplifyAlgebraically(expr.source, constants)
|
|
29083
|
+
source: simplifyAlgebraically(expr.source, constants, options)
|
|
28538
29084
|
};
|
|
28539
29085
|
case "MemberExpression":
|
|
28540
29086
|
case "OptionalMemberExpression":
|
|
28541
29087
|
return {
|
|
28542
29088
|
...expr,
|
|
28543
|
-
object: simplifyAlgebraically(expr.object, constants),
|
|
28544
|
-
property: expr.computed ? simplifyAlgebraically(expr.property, constants) : expr.property
|
|
29089
|
+
object: simplifyAlgebraically(expr.object, constants, options),
|
|
29090
|
+
property: expr.computed ? simplifyAlgebraically(expr.property, constants, options) : expr.property
|
|
28545
29091
|
};
|
|
28546
29092
|
default:
|
|
28547
29093
|
return expr;
|
|
28548
29094
|
}
|
|
28549
29095
|
}
|
|
28550
|
-
function foldExpressionWithConstants(expr, constants, constObjects, constArrays) {
|
|
29096
|
+
function foldExpressionWithConstants(expr, constants, options, constObjects, constArrays) {
|
|
28551
29097
|
const replaced = replaceIdentifiersWithConstants(expr, constants);
|
|
28552
29098
|
if (!constObjects && !constArrays) {
|
|
28553
|
-
return foldExpression(replaced, constants);
|
|
29099
|
+
return foldExpression(replaced, constants, options);
|
|
28554
29100
|
}
|
|
28555
29101
|
const memberReplaced = replaceConstMemberExpressions(
|
|
28556
29102
|
replaced,
|
|
28557
29103
|
constObjects ?? /* @__PURE__ */ new Map(),
|
|
28558
29104
|
constArrays ?? /* @__PURE__ */ new Map()
|
|
28559
29105
|
);
|
|
28560
|
-
return foldExpression(memberReplaced, constants);
|
|
29106
|
+
return foldExpression(memberReplaced, constants, options);
|
|
28561
29107
|
}
|
|
28562
29108
|
function replaceIdentifiersWithConstants(expr, constants, context = {}) {
|
|
28563
29109
|
switch (expr.kind) {
|
|
@@ -28719,10 +29265,10 @@ function replaceConstantsInTerminator(term, constants) {
|
|
|
28719
29265
|
return term;
|
|
28720
29266
|
}
|
|
28721
29267
|
}
|
|
28722
|
-
function foldTerminatorWithConstants(term, constants, reactive, constObjects, constArrays) {
|
|
29268
|
+
function foldTerminatorWithConstants(term, constants, options, reactive, constObjects, constArrays) {
|
|
28723
29269
|
const fold = (expr) => {
|
|
28724
29270
|
if (reactive && expressionDependsOnReactive(expr, reactive)) return expr;
|
|
28725
|
-
return foldExpressionWithConstants(expr, constants, constObjects, constArrays);
|
|
29271
|
+
return foldExpressionWithConstants(expr, constants, options, constObjects, constArrays);
|
|
28726
29272
|
};
|
|
28727
29273
|
switch (term.kind) {
|
|
28728
29274
|
case "Return":
|
|
@@ -28839,11 +29385,14 @@ function hasSideEffectsBetween(instructions, start, end, purity) {
|
|
|
28839
29385
|
function eliminateDeadCode(fn, purity) {
|
|
28840
29386
|
const depsByVar = buildDependencyGraph(fn);
|
|
28841
29387
|
const live = computeLiveVariables(fn, depsByVar, purity);
|
|
29388
|
+
const baseLive = /* @__PURE__ */ new Set();
|
|
29389
|
+
live.forEach((name) => baseLive.add(getSSABaseName(name)));
|
|
28842
29390
|
const blocks = fn.blocks.map((block) => {
|
|
28843
29391
|
const instructions = block.instructions.filter((instr) => {
|
|
28844
29392
|
if (instr.kind === "Assign") {
|
|
28845
29393
|
const name = instr.target.name;
|
|
28846
29394
|
if (live.has(name)) return true;
|
|
29395
|
+
if (instr.declarationKind && baseLive.has(getSSABaseName(name))) return true;
|
|
28847
29396
|
return !isPureExpression(instr.value, purity) || isExplicitMemoCall(instr.value, purity);
|
|
28848
29397
|
}
|
|
28849
29398
|
if (instr.kind === "Phi") {
|
|
@@ -29855,8 +30404,8 @@ function getRootIdentifier(expr, t4) {
|
|
|
29855
30404
|
}
|
|
29856
30405
|
|
|
29857
30406
|
// src/index.ts
|
|
29858
|
-
function stripMacroImports(
|
|
29859
|
-
|
|
30407
|
+
function stripMacroImports(path2, t4) {
|
|
30408
|
+
path2.traverse({
|
|
29860
30409
|
ImportDeclaration(importPath) {
|
|
29861
30410
|
if (importPath.node.source.value !== "fict" && importPath.node.source.value !== "fict/slim")
|
|
29862
30411
|
return;
|
|
@@ -29874,19 +30423,19 @@ function stripMacroImports(path, t4) {
|
|
|
29874
30423
|
}
|
|
29875
30424
|
});
|
|
29876
30425
|
}
|
|
29877
|
-
function isInsideLoop(
|
|
29878
|
-
return !!
|
|
30426
|
+
function isInsideLoop(path2) {
|
|
30427
|
+
return !!path2.findParent(
|
|
29879
30428
|
(p) => p.isForStatement?.() || p.isWhileStatement?.() || p.isDoWhileStatement?.() || p.isForInStatement?.() || p.isForOfStatement?.()
|
|
29880
30429
|
);
|
|
29881
30430
|
}
|
|
29882
|
-
function isInsideConditional(
|
|
29883
|
-
return !!
|
|
30431
|
+
function isInsideConditional(path2) {
|
|
30432
|
+
return !!path2.findParent(
|
|
29884
30433
|
(p) => p.isIfStatement?.() || p.isConditionalExpression?.() || p.isSwitchCase?.()
|
|
29885
30434
|
);
|
|
29886
30435
|
}
|
|
29887
|
-
function isInsideNestedFunction(
|
|
30436
|
+
function isInsideNestedFunction(path2) {
|
|
29888
30437
|
let depth = 0;
|
|
29889
|
-
let current =
|
|
30438
|
+
let current = path2;
|
|
29890
30439
|
while (current) {
|
|
29891
30440
|
if (current.isFunction?.()) {
|
|
29892
30441
|
depth++;
|
|
@@ -29896,8 +30445,8 @@ function isInsideNestedFunction(path) {
|
|
|
29896
30445
|
}
|
|
29897
30446
|
return false;
|
|
29898
30447
|
}
|
|
29899
|
-
function isInsideJSX(
|
|
29900
|
-
return !!
|
|
30448
|
+
function isInsideJSX(path2) {
|
|
30449
|
+
return !!path2.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
29901
30450
|
}
|
|
29902
30451
|
function parseSuppressionCodes(raw) {
|
|
29903
30452
|
if (!raw) return void 0;
|
|
@@ -29926,12 +30475,42 @@ function shouldSuppressWarning(suppressions, code, line) {
|
|
|
29926
30475
|
return entry.codes.has(code);
|
|
29927
30476
|
});
|
|
29928
30477
|
}
|
|
29929
|
-
function
|
|
29930
|
-
if (
|
|
30478
|
+
function hasErrorEscalation(options) {
|
|
30479
|
+
if (options.warningsAsErrors === true) return true;
|
|
30480
|
+
if (Array.isArray(options.warningsAsErrors) && options.warningsAsErrors.length > 0) return true;
|
|
30481
|
+
if (options.warningLevels) {
|
|
30482
|
+
return Object.values(options.warningLevels).some((level) => level === "error");
|
|
30483
|
+
}
|
|
30484
|
+
return false;
|
|
30485
|
+
}
|
|
30486
|
+
function resolveWarningLevel(code, options) {
|
|
30487
|
+
const override = options.warningLevels?.[code];
|
|
30488
|
+
if (override) return override;
|
|
30489
|
+
if (options.warningsAsErrors === true) return "error";
|
|
30490
|
+
if (Array.isArray(options.warningsAsErrors) && options.warningsAsErrors.includes(code)) {
|
|
30491
|
+
return "error";
|
|
30492
|
+
}
|
|
30493
|
+
return "warn";
|
|
30494
|
+
}
|
|
30495
|
+
function formatWarningAsError(warning) {
|
|
30496
|
+
const location = warning.line > 0 ? `${warning.fileName}:${warning.line}:${warning.column}` : warning.fileName;
|
|
30497
|
+
return `Fict warning treated as error (${warning.code}): ${warning.message}
|
|
30498
|
+
at ${location}`;
|
|
30499
|
+
}
|
|
30500
|
+
function createWarningDispatcher(onWarn, suppressions, options, dev) {
|
|
30501
|
+
const hasEscalation = hasErrorEscalation(options);
|
|
30502
|
+
if (!dev && !hasEscalation) return () => {
|
|
29931
30503
|
};
|
|
29932
30504
|
return (warning) => {
|
|
29933
30505
|
if (shouldSuppressWarning(suppressions, warning.code, warning.line)) return;
|
|
29934
|
-
|
|
30506
|
+
const level = resolveWarningLevel(warning.code, options);
|
|
30507
|
+
if (level === "off") return;
|
|
30508
|
+
if (level === "error") {
|
|
30509
|
+
throw new Error(formatWarningAsError(warning));
|
|
30510
|
+
}
|
|
30511
|
+
if (dev && onWarn) {
|
|
30512
|
+
onWarn(warning);
|
|
30513
|
+
}
|
|
29935
30514
|
};
|
|
29936
30515
|
}
|
|
29937
30516
|
function emitWarning(node, code, message, warn, fileName) {
|
|
@@ -30031,13 +30610,13 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30031
30610
|
};
|
|
30032
30611
|
const reactiveNames = /* @__PURE__ */ new Set([...stateVars, ...derivedVars]);
|
|
30033
30612
|
programPath.traverse({
|
|
30034
|
-
AssignmentExpression(
|
|
30035
|
-
const { left } =
|
|
30613
|
+
AssignmentExpression(path2) {
|
|
30614
|
+
const { left } = path2.node;
|
|
30036
30615
|
if (t4.isIdentifier(left)) return;
|
|
30037
30616
|
if (t4.isMemberExpression(left) || t4.isOptionalMemberExpression(left)) {
|
|
30038
30617
|
if (isStateRoot(left.object)) {
|
|
30039
30618
|
emitWarning(
|
|
30040
|
-
|
|
30619
|
+
path2.node,
|
|
30041
30620
|
"FICT-M",
|
|
30042
30621
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
30043
30622
|
warn,
|
|
@@ -30045,7 +30624,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30045
30624
|
);
|
|
30046
30625
|
if (isDynamicPropertyAccess(left, t4)) {
|
|
30047
30626
|
emitWarning(
|
|
30048
|
-
|
|
30627
|
+
path2.node,
|
|
30049
30628
|
"FICT-H",
|
|
30050
30629
|
"Dynamic property access widens dependency tracking",
|
|
30051
30630
|
warn,
|
|
@@ -30055,12 +30634,12 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30055
30634
|
}
|
|
30056
30635
|
}
|
|
30057
30636
|
},
|
|
30058
|
-
UpdateExpression(
|
|
30059
|
-
const arg =
|
|
30637
|
+
UpdateExpression(path2) {
|
|
30638
|
+
const arg = path2.node.argument;
|
|
30060
30639
|
if (t4.isMemberExpression(arg) || t4.isOptionalMemberExpression(arg)) {
|
|
30061
30640
|
if (isStateRoot(arg.object)) {
|
|
30062
30641
|
emitWarning(
|
|
30063
|
-
|
|
30642
|
+
path2.node,
|
|
30064
30643
|
"FICT-M",
|
|
30065
30644
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
30066
30645
|
warn,
|
|
@@ -30068,7 +30647,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30068
30647
|
);
|
|
30069
30648
|
if (isDynamicPropertyAccess(arg, t4)) {
|
|
30070
30649
|
emitWarning(
|
|
30071
|
-
|
|
30650
|
+
path2.node,
|
|
30072
30651
|
"FICT-H",
|
|
30073
30652
|
"Dynamic property access widens dependency tracking",
|
|
30074
30653
|
warn,
|
|
@@ -30078,13 +30657,13 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30078
30657
|
}
|
|
30079
30658
|
}
|
|
30080
30659
|
},
|
|
30081
|
-
MemberExpression(
|
|
30082
|
-
if (!
|
|
30083
|
-
if (
|
|
30084
|
-
if (
|
|
30085
|
-
if (isDynamicPropertyAccess(
|
|
30660
|
+
MemberExpression(path2) {
|
|
30661
|
+
if (!path2.node.computed) return;
|
|
30662
|
+
if (path2.parentPath.isAssignmentExpression({ left: path2.node })) return;
|
|
30663
|
+
if (path2.parentPath.isUpdateExpression({ argument: path2.node })) return;
|
|
30664
|
+
if (isDynamicPropertyAccess(path2.node, t4) && isStateRoot(path2.node.object)) {
|
|
30086
30665
|
emitWarning(
|
|
30087
|
-
|
|
30666
|
+
path2.node,
|
|
30088
30667
|
"FICT-H",
|
|
30089
30668
|
"Dynamic property access widens dependency tracking",
|
|
30090
30669
|
warn,
|
|
@@ -30092,12 +30671,12 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30092
30671
|
);
|
|
30093
30672
|
}
|
|
30094
30673
|
},
|
|
30095
|
-
Function(
|
|
30674
|
+
Function(path2) {
|
|
30096
30675
|
const captured = /* @__PURE__ */ new Set();
|
|
30097
|
-
|
|
30676
|
+
path2.traverse(
|
|
30098
30677
|
{
|
|
30099
30678
|
Function(inner) {
|
|
30100
|
-
if (inner ===
|
|
30679
|
+
if (inner === path2) return;
|
|
30101
30680
|
inner.skip();
|
|
30102
30681
|
},
|
|
30103
30682
|
Identifier(idPath) {
|
|
@@ -30105,7 +30684,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30105
30684
|
if (!reactiveNames.has(name)) return;
|
|
30106
30685
|
const binding = idPath.scope.getBinding(name);
|
|
30107
30686
|
if (!binding) return;
|
|
30108
|
-
if (binding.scope === idPath.scope || binding.scope ===
|
|
30687
|
+
if (binding.scope === idPath.scope || binding.scope === path2.scope) return;
|
|
30109
30688
|
captured.add(name);
|
|
30110
30689
|
}
|
|
30111
30690
|
},
|
|
@@ -30113,7 +30692,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30113
30692
|
);
|
|
30114
30693
|
if (captured.size > 0) {
|
|
30115
30694
|
emitWarning(
|
|
30116
|
-
|
|
30695
|
+
path2.node,
|
|
30117
30696
|
"FICT-R005",
|
|
30118
30697
|
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
30119
30698
|
warn,
|
|
@@ -30121,9 +30700,9 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30121
30700
|
);
|
|
30122
30701
|
}
|
|
30123
30702
|
},
|
|
30124
|
-
CallExpression(
|
|
30125
|
-
if (t4.isIdentifier(
|
|
30126
|
-
const argPath =
|
|
30703
|
+
CallExpression(path2) {
|
|
30704
|
+
if (t4.isIdentifier(path2.node.callee, { name: "$effect" })) {
|
|
30705
|
+
const argPath = path2.get("arguments.0");
|
|
30127
30706
|
if (argPath?.isFunctionExpression() || argPath?.isArrowFunctionExpression()) {
|
|
30128
30707
|
let hasReactiveDependency = false;
|
|
30129
30708
|
argPath.traverse({
|
|
@@ -30144,7 +30723,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30144
30723
|
});
|
|
30145
30724
|
if (!hasReactiveDependency) {
|
|
30146
30725
|
emitWarning(
|
|
30147
|
-
|
|
30726
|
+
path2.node,
|
|
30148
30727
|
"FICT-E001",
|
|
30149
30728
|
"Effect has no reactive reads; it will run once. Consider removing $effect or adding dependencies.",
|
|
30150
30729
|
warn,
|
|
@@ -30154,7 +30733,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30154
30733
|
}
|
|
30155
30734
|
return;
|
|
30156
30735
|
}
|
|
30157
|
-
const callee =
|
|
30736
|
+
const callee = path2.node.callee;
|
|
30158
30737
|
let calleeName = "";
|
|
30159
30738
|
if (t4.isIdentifier(callee)) {
|
|
30160
30739
|
calleeName = callee.name;
|
|
@@ -30166,7 +30745,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30166
30745
|
}
|
|
30167
30746
|
const isSafe = calleeName && SAFE_FUNCTIONS.has(calleeName);
|
|
30168
30747
|
if (isSafe) return;
|
|
30169
|
-
for (const arg of
|
|
30748
|
+
for (const arg of path2.node.arguments) {
|
|
30170
30749
|
if (!t4.isExpression(arg)) continue;
|
|
30171
30750
|
if (isStateRoot(arg)) {
|
|
30172
30751
|
emitWarning(
|
|
@@ -30180,13 +30759,13 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
30180
30759
|
}
|
|
30181
30760
|
}
|
|
30182
30761
|
},
|
|
30183
|
-
OptionalMemberExpression(
|
|
30184
|
-
if (!
|
|
30185
|
-
if (
|
|
30186
|
-
if (
|
|
30187
|
-
if (isDynamicPropertyAccess(
|
|
30762
|
+
OptionalMemberExpression(path2) {
|
|
30763
|
+
if (!path2.node.computed) return;
|
|
30764
|
+
if (path2.parentPath.isAssignmentExpression({ left: path2.node })) return;
|
|
30765
|
+
if (path2.parentPath.isUpdateExpression({ argument: path2.node })) return;
|
|
30766
|
+
if (isDynamicPropertyAccess(path2.node, t4) && isStateRoot(path2.node.object)) {
|
|
30188
30767
|
emitWarning(
|
|
30189
|
-
|
|
30768
|
+
path2.node,
|
|
30190
30769
|
"FICT-H",
|
|
30191
30770
|
"Dynamic property access widens dependency tracking",
|
|
30192
30771
|
warn,
|
|
@@ -30237,14 +30816,17 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
30237
30816
|
};
|
|
30238
30817
|
return {
|
|
30239
30818
|
Program: {
|
|
30240
|
-
exit(
|
|
30241
|
-
const fileName =
|
|
30242
|
-
const comments =
|
|
30819
|
+
exit(path2) {
|
|
30820
|
+
const fileName = path2.hub?.file?.opts?.filename || "<unknown>";
|
|
30821
|
+
const comments = path2.hub?.file?.ast?.comments || [];
|
|
30243
30822
|
const suppressions = parseSuppressions(comments);
|
|
30244
30823
|
const dev = options.dev !== false;
|
|
30245
|
-
const warn =
|
|
30824
|
+
const warn = createWarningDispatcher(options.onWarn, suppressions, options, dev);
|
|
30825
|
+
const optionsWithWarnings = {
|
|
30826
|
+
...options,
|
|
30827
|
+
onWarn: warn,
|
|
30828
|
+
filename: fileName
|
|
30246
30829
|
};
|
|
30247
|
-
const optionsWithWarnings = dev ? { ...options, onWarn: warn } : { ...options, onWarn: void 0 };
|
|
30248
30830
|
const isHookName2 = (name) => !!name && /^use[A-Z]/.test(name);
|
|
30249
30831
|
const getFunctionName = (fnPath) => {
|
|
30250
30832
|
return fnPath.isFunctionDeclaration() && fnPath.node.id ? fnPath.node.id.name : fnPath.isFunctionExpression() && fnPath.node.id ? fnPath.node.id.name : fnPath.parentPath.isVariableDeclarator() && t4.isIdentifier(fnPath.parentPath.node.id) && fnPath.parentPath.node.init === fnPath.node ? fnPath.parentPath.node.id.name : void 0;
|
|
@@ -30345,7 +30927,7 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
30345
30927
|
};
|
|
30346
30928
|
return checkNode(fn.body);
|
|
30347
30929
|
};
|
|
30348
|
-
|
|
30930
|
+
path2.traverse({
|
|
30349
30931
|
FunctionDeclaration(fnPath) {
|
|
30350
30932
|
const name = fnPath.node.id?.name;
|
|
30351
30933
|
if (!isComponentName2(name)) return;
|
|
@@ -30382,7 +30964,7 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
30382
30964
|
const stateMacroNames = /* @__PURE__ */ new Set(["$state"]);
|
|
30383
30965
|
const effectMacroNames = /* @__PURE__ */ new Set(["$effect"]);
|
|
30384
30966
|
const memoMacroNames = /* @__PURE__ */ new Set(["$memo", "createMemo"]);
|
|
30385
|
-
|
|
30967
|
+
path2.traverse({
|
|
30386
30968
|
ImportDeclaration(importPath) {
|
|
30387
30969
|
if (importPath.node.source.value !== "fict" && importPath.node.source.value !== "fict/slim")
|
|
30388
30970
|
return;
|
|
@@ -30402,7 +30984,7 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
30402
30984
|
}
|
|
30403
30985
|
}
|
|
30404
30986
|
});
|
|
30405
|
-
|
|
30987
|
+
path2.traverse({
|
|
30406
30988
|
JSXExpressionContainer(exprPath) {
|
|
30407
30989
|
const expr = exprPath.node.expression;
|
|
30408
30990
|
if (!t4.isCallExpression(expr)) return;
|
|
@@ -30447,7 +31029,7 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
30447
31029
|
const stateVars = /* @__PURE__ */ new Set();
|
|
30448
31030
|
const derivedVars = /* @__PURE__ */ new Set();
|
|
30449
31031
|
const destructuredAliases = /* @__PURE__ */ new Set();
|
|
30450
|
-
|
|
31032
|
+
path2.traverse({
|
|
30451
31033
|
VariableDeclarator(varPath) {
|
|
30452
31034
|
const init = varPath.node.init;
|
|
30453
31035
|
if (!init) return;
|
|
@@ -30696,7 +31278,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
30696
31278
|
return usesState;
|
|
30697
31279
|
};
|
|
30698
31280
|
debugLog("alias", "state vars", Array.from(stateVars));
|
|
30699
|
-
|
|
31281
|
+
path2.traverse({
|
|
30700
31282
|
Function: {
|
|
30701
31283
|
enter() {
|
|
30702
31284
|
aliasStack.push(/* @__PURE__ */ new Set());
|
|
@@ -30754,7 +31336,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
30754
31336
|
}
|
|
30755
31337
|
});
|
|
30756
31338
|
if (derivedVars.size > 0) {
|
|
30757
|
-
|
|
31339
|
+
path2.traverse({
|
|
30758
31340
|
AssignmentExpression(assignPath) {
|
|
30759
31341
|
const { left } = assignPath.node;
|
|
30760
31342
|
if (t4.isIdentifier(left) && derivedVars.has(left.name)) {
|
|
@@ -30775,7 +31357,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
30775
31357
|
});
|
|
30776
31358
|
}
|
|
30777
31359
|
if (destructuredAliases.size > 0) {
|
|
30778
|
-
|
|
31360
|
+
path2.traverse({
|
|
30779
31361
|
AssignmentExpression(assignPath) {
|
|
30780
31362
|
const { left } = assignPath.node;
|
|
30781
31363
|
if (t4.isIdentifier(left) && destructuredAliases.has(left.name)) {
|
|
@@ -30803,10 +31385,11 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
30803
31385
|
}
|
|
30804
31386
|
});
|
|
30805
31387
|
}
|
|
30806
|
-
|
|
30807
|
-
|
|
31388
|
+
const shouldRunWarnings = dev || hasErrorEscalation(options);
|
|
31389
|
+
if (shouldRunWarnings) {
|
|
31390
|
+
runWarningPass(path2, stateVars, derivedVars, warn, fileName, t4);
|
|
30808
31391
|
}
|
|
30809
|
-
const fileAst = t4.file(
|
|
31392
|
+
const fileAst = t4.file(path2.node);
|
|
30810
31393
|
const hir = buildHIR(
|
|
30811
31394
|
fileAst,
|
|
30812
31395
|
{
|
|
@@ -30821,19 +31404,20 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
30821
31404
|
);
|
|
30822
31405
|
const optimized = optionsWithWarnings.optimize ? optimizeHIR(hir, {
|
|
30823
31406
|
memoMacroNames,
|
|
30824
|
-
inlineDerivedMemos: optionsWithWarnings.inlineDerivedMemos ?? true
|
|
31407
|
+
inlineDerivedMemos: optionsWithWarnings.inlineDerivedMemos ?? true,
|
|
31408
|
+
optimizeLevel: optionsWithWarnings.optimizeLevel ?? "safe"
|
|
30825
31409
|
}) : hir;
|
|
30826
31410
|
const lowered = lowerHIRWithRegions(optimized, t4, optionsWithWarnings, {
|
|
30827
31411
|
state: stateMacroNames,
|
|
30828
31412
|
effect: effectMacroNames,
|
|
30829
31413
|
memo: memoMacroNames
|
|
30830
31414
|
});
|
|
30831
|
-
|
|
30832
|
-
|
|
31415
|
+
path2.node.body = lowered.program.body;
|
|
31416
|
+
path2.node.directives = lowered.program.directives;
|
|
30833
31417
|
if (!process.env.FICT_SKIP_SCOPE_CRAWL) {
|
|
30834
|
-
|
|
31418
|
+
path2.scope.crawl();
|
|
30835
31419
|
}
|
|
30836
|
-
stripMacroImports(
|
|
31420
|
+
stripMacroImports(path2, t4);
|
|
30837
31421
|
}
|
|
30838
31422
|
}
|
|
30839
31423
|
};
|
|
@@ -30846,6 +31430,7 @@ var createFictPlugin = declare(
|
|
|
30846
31430
|
...options,
|
|
30847
31431
|
fineGrainedDom: options.fineGrainedDom ?? true,
|
|
30848
31432
|
optimize: options.optimize ?? true,
|
|
31433
|
+
optimizeLevel: options.optimizeLevel ?? "safe",
|
|
30849
31434
|
inlineDerivedMemos: options.inlineDerivedMemos ?? true,
|
|
30850
31435
|
dev: options.dev ?? (process.env.NODE_ENV !== "production" && process.env.NODE_ENV !== "test")
|
|
30851
31436
|
};
|
|
@@ -30857,6 +31442,9 @@ var createFictPlugin = declare(
|
|
|
30857
31442
|
);
|
|
30858
31443
|
var index_default = createFictPlugin;
|
|
30859
31444
|
export {
|
|
31445
|
+
clearModuleMetadata,
|
|
30860
31446
|
createFictPlugin,
|
|
30861
|
-
index_default as default
|
|
31447
|
+
index_default as default,
|
|
31448
|
+
resolveModuleMetadata,
|
|
31449
|
+
setModuleMetadata
|
|
30862
31450
|
};
|