@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.85
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/expr-shape.cjs +62 -1
- package/dist/analyze/expr-shape.d.cts +14 -0
- package/dist/analyze/expr-shape.d.ts +2 -2
- package/dist/analyze/expr-shape.js +1 -1
- package/dist/analyze/expr-shape.mjs +41 -1
- package/dist/analyze/intrinsics.cjs +80 -1
- package/dist/analyze/intrinsics.d.cts +66 -0
- package/dist/analyze/intrinsics.d.ts +7 -7
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +3 -3
- package/dist/analyze/intrinsics.mjs +59 -1
- package/dist/analyze/paren.cjs +134 -0
- package/dist/analyze/paren.d.cts +23 -0
- package/dist/analyze/paren.d.ts +24 -0
- package/dist/analyze/paren.d.ts.map +1 -0
- package/dist/analyze/paren.js +168 -0
- package/dist/analyze/paren.mjs +113 -0
- package/dist/analyze/props-destructure.cjs +226 -1
- package/dist/analyze/props-destructure.d.cts +83 -0
- package/dist/analyze/props-destructure.d.ts +3 -3
- package/dist/analyze/props-destructure.d.ts.map +1 -1
- package/dist/analyze/props-destructure.js +4 -4
- package/dist/analyze/props-destructure.mjs +205 -1
- package/dist/analyze/reactive-bindings.cjs +190 -1
- package/dist/analyze/reactive-bindings.d.cts +42 -0
- package/dist/analyze/reactive-bindings.d.ts +1 -1
- package/dist/analyze/reactive-bindings.js +2 -2
- package/dist/analyze/reactive-bindings.mjs +167 -1
- package/dist/analyze/reactive-expr.cjs +38 -1
- package/dist/analyze/reactive-expr.d.cts +38 -0
- package/dist/analyze/reactive-expr.d.ts +4 -4
- package/dist/analyze/reactive-expr.d.ts.map +1 -1
- package/dist/analyze/reactive-expr.js +2 -2
- package/dist/analyze/reactive-expr.mjs +17 -1
- package/dist/analyze/static-graph.cjs +811 -1
- package/dist/analyze/static-graph.d.cts +102 -0
- package/dist/analyze/static-graph.d.ts +1 -1
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +11 -11
- package/dist/analyze/static-graph.mjs +793 -1
- package/dist/babel-TGY76XJ7.mjs +636 -0
- package/dist/chunk-4PLHS2FP.mjs +158 -0
- package/dist/chunk-6DB5FXS4.mjs +1718 -0
- package/dist/chunk-F74GFKSL.mjs +16 -0
- package/dist/chunk-G6QC2WRJ.mjs +11 -0
- package/dist/chunk-RUDJDZAA.mjs +1078 -0
- package/dist/codegen/backend.cjs +18 -1
- package/dist/codegen/backend.d.cts +35 -0
- package/dist/codegen/backends/imperative.cjs +542 -1
- package/dist/codegen/backends/imperative.d.cts +11 -0
- package/dist/codegen/backends/imperative.d.ts +1 -1
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +24 -20
- package/dist/codegen/backends/imperative.mjs +519 -1
- package/dist/codegen/contract.cjs +52 -1
- package/dist/codegen/contract.d.cts +24 -0
- package/dist/codegen/contract.d.ts +2 -2
- package/dist/codegen/contract.js +2 -2
- package/dist/codegen/contract.mjs +31 -1
- package/dist/codegen/partial-template.cjs +176 -1
- package/dist/codegen/partial-template.d.cts +61 -0
- package/dist/codegen/partial-template.d.ts +4 -4
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +153 -1
- package/dist/codegen/serialize-static.cjs +125 -1
- package/dist/codegen/serialize-static.d.cts +38 -0
- package/dist/codegen/serialize-static.d.ts +3 -3
- package/dist/codegen/serialize-static.js +6 -6
- package/dist/codegen/serialize-static.mjs +104 -1
- package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
- package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
- package/dist/frontend/babel/build-ir-lit.d.ts +2 -2
- package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
- package/dist/frontend/babel/build-ir.cjs +1524 -1
- package/dist/frontend/babel/build-ir.d.cts +35 -0
- package/dist/frontend/babel/build-ir.d.ts +2 -2
- package/dist/frontend/babel/build-ir.js +2 -2
- package/dist/frontend/babel/build-ir.mjs +1495 -1
- package/dist/frontend/babel/index.cjs +2186 -1
- package/dist/frontend/babel/index.d.cts +33 -0
- package/dist/frontend/babel/index.d.ts +1 -1
- package/dist/frontend/babel/index.js +1 -1
- package/dist/frontend/babel/index.mjs +2156 -1
- package/dist/frontend/babel/lower-template.cjs +1507 -1
- package/dist/frontend/babel/lower-template.d.cts +23 -0
- package/dist/frontend/babel/lower-template.d.ts +1 -1
- package/dist/frontend/babel/lower-template.js +2 -2
- package/dist/frontend/babel/lower-template.mjs +1478 -1
- package/dist/frontend/babel/plugin.cjs +2132 -1
- package/dist/frontend/babel/plugin.d.cts +95 -0
- package/dist/frontend/babel/plugin.d.ts +5 -5
- package/dist/frontend/babel/plugin.d.ts.map +1 -1
- package/dist/frontend/babel/plugin.js +14 -14
- package/dist/frontend/babel/plugin.mjs +2103 -1
- package/dist/frontend/babel/server-functions.cjs +110 -1
- package/dist/frontend/babel/server-functions.d.cts +10 -0
- package/dist/frontend/babel/server-functions.mjs +89 -1
- package/dist/frontend/babel/types.cjs +18 -1
- package/dist/frontend/babel/types.d.cts +33 -0
- package/dist/frontend/types.cjs +18 -1
- package/dist/frontend/types.d.cts +25 -0
- package/dist/frontend/vocabulary.cjs +98 -0
- package/dist/frontend/vocabulary.d.cts +79 -0
- package/dist/frontend/vocabulary.d.ts +80 -0
- package/dist/frontend/vocabulary.d.ts.map +1 -0
- package/dist/frontend/vocabulary.js +124 -0
- package/dist/frontend/vocabulary.mjs +77 -0
- package/dist/index.cjs +1595 -14
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/index.mjs +1575 -14
- package/dist/integrations.cjs +4312 -26
- package/dist/integrations.d.cts +215 -0
- package/dist/integrations.d.ts +9 -9
- package/dist/integrations.d.ts.map +1 -1
- package/dist/integrations.js +29 -8
- package/dist/integrations.mjs +536 -18
- package/dist/ir/nodes.cjs +18 -1
- package/dist/ir/nodes.d.cts +168 -0
- package/dist/ir/nodes.d.ts +6 -6
- package/dist/lower/compile-template.cjs +1356 -1
- package/dist/lower/compile-template.d.cts +69 -0
- package/dist/lower/compile-template.d.ts +3 -3
- package/dist/lower/compile-template.js +1 -1
- package/dist/lower/compile-template.mjs +1336 -1
- package/dist/lower/jsx.cjs +529 -1
- package/dist/lower/jsx.d.cts +25 -0
- package/dist/lower/jsx.d.ts +1 -1
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +6 -5
- package/dist/lower/jsx.mjs +506 -1
- package/dist/lower/template.cjs +1061 -1
- package/dist/lower/template.d.cts +53 -0
- package/dist/lower/template.d.ts +3 -3
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +12 -11
- package/dist/lower/template.mjs +1042 -1
- package/dist/lower/text.cjs +42 -1
- package/dist/lower/text.d.cts +10 -0
- package/dist/lower/text.d.ts +2 -2
- package/dist/lower/text.d.ts.map +1 -1
- package/dist/lower/text.js +2 -2
- package/dist/lower/text.mjs +21 -1
- package/dist/optimize/analyze-static.cjs +112 -1
- package/dist/optimize/analyze-static.d.cts +39 -0
- package/dist/optimize/analyze-static.d.ts +2 -2
- package/dist/optimize/analyze-static.js +2 -2
- package/dist/optimize/analyze-static.mjs +91 -1
- package/dist/optimize/collapse-strategies.cjs +90 -1
- package/dist/optimize/collapse-strategies.d.cts +30 -0
- package/dist/optimize/collapse-strategies.d.ts +3 -3
- package/dist/optimize/collapse-strategies.mjs +67 -1
- package/dist/options.cjs +33 -1
- package/dist/options.d.cts +39 -0
- package/dist/options.d.ts +2 -2
- package/dist/options.mjs +12 -1
- package/dist/resolve/builtins.cjs +73 -1
- package/dist/resolve/builtins.d.cts +68 -0
- package/dist/resolve/builtins.d.ts +8 -8
- package/dist/resolve/builtins.d.ts.map +1 -1
- package/dist/resolve/builtins.js +4 -4
- package/dist/resolve/builtins.mjs +53 -1
- package/dist/resolve/component-globals.cjs +234 -14
- package/dist/resolve/component-globals.d.cts +80 -0
- package/dist/resolve/component-globals.d.ts +5 -5
- package/dist/resolve/component-globals.js +10 -10
- package/dist/resolve/component-globals.mjs +211 -14
- package/dist/resolve/component-resolver.cjs +80 -1
- package/dist/resolve/component-resolver.d.cts +68 -0
- package/dist/resolve/component-resolver.d.ts +3 -3
- package/dist/resolve/component-resolver.d.ts.map +1 -1
- package/dist/resolve/component-resolver.js +3 -3
- package/dist/resolve/component-resolver.mjs +59 -1
- package/dist/resolve/load-directive.cjs +93 -1
- package/dist/resolve/load-directive.d.cts +53 -0
- package/dist/resolve/load-directive.d.ts +5 -5
- package/dist/resolve/load-directive.js +6 -6
- package/dist/resolve/load-directive.mjs +72 -1
- package/dist/resolve/resolve-ir.cjs +108 -1
- package/dist/resolve/resolve-ir.d.cts +53 -0
- package/dist/resolve/resolve-ir.d.ts +6 -6
- package/dist/resolve/resolve-ir.d.ts.map +1 -1
- package/dist/resolve/resolve-ir.js +1 -1
- package/dist/resolve/resolve-ir.mjs +85 -1
- package/dist/resolve/write-globals.cjs +319 -14
- package/dist/resolve/write-globals.d.cts +30 -0
- package/dist/resolve/write-globals.js +2 -2
- package/dist/resolve/write-globals.mjs +298 -14
- package/dist/server-fns-ZYWQTSZU.mjs +78 -0
- package/dist/server-functions-PCERFA7A.mjs +82 -0
- package/dist/transform/bindings.cjs +71 -1
- package/dist/transform/bindings.d.cts +16 -0
- package/dist/transform/bindings.d.ts +1 -1
- package/dist/transform/bindings.js +1 -1
- package/dist/transform/bindings.mjs +50 -1
- package/dist/transform/index.cjs +2732 -8
- package/dist/transform/index.d.cts +15 -0
- package/dist/transform/index.mjs +3773 -17
- package/dist/transform/intrinsics.cjs +216 -3
- package/dist/transform/intrinsics.d.cts +21 -0
- package/dist/transform/intrinsics.js +1 -1
- package/dist/transform/intrinsics.mjs +193 -3
- package/dist/transform/props.cjs +441 -3
- package/dist/transform/props.d.cts +45 -0
- package/dist/transform/props.d.ts +1 -1
- package/dist/transform/props.d.ts.map +1 -1
- package/dist/transform/props.js +4 -4
- package/dist/transform/props.mjs +1482 -12
- package/dist/transform/server-fn-id.cjs +35 -1
- package/dist/transform/server-fn-id.d.cts +9 -0
- package/dist/transform/server-fn-id.d.ts +1 -1
- package/dist/transform/server-fn-id.js +2 -2
- package/dist/transform/server-fn-id.mjs +14 -1
- package/dist/transform/server-fns.cjs +114 -2
- package/dist/transform/server-fns.d.cts +12 -0
- package/dist/transform/server-fns.js +3 -3
- package/dist/transform/server-fns.mjs +1155 -11
- package/dist/transform/source-locations.cjs +330 -1
- package/dist/transform/source-locations.d.cts +43 -0
- package/dist/transform/source-locations.d.ts +1 -1
- package/dist/transform/source-locations.js +5 -5
- package/dist/transform/source-locations.mjs +307 -1
- package/dist/transform/templates.cjs +2701 -7
- package/dist/transform/templates.d.cts +69 -0
- package/dist/transform/templates.d.ts +2 -2
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +7 -7
- package/dist/transform/templates.mjs +3743 -16
- package/dist/transform-RWDTQUF5.mjs +893 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/dist/babel-VXKH6MRQ.mjs +0 -1
- package/dist/chunk-3SAEGOMQ.mjs +0 -1
- package/dist/chunk-5KMMN5QP.mjs +0 -1
- package/dist/chunk-IBRM4W7I.mjs +0 -10
- package/dist/chunk-OHHZCYIQ.mjs +0 -1
- package/dist/chunk-YKZ54NVE.mjs +0 -1
- package/dist/server-fns-6QM243HC.mjs +0 -2
- package/dist/server-functions-E3LKCZ4R.mjs +0 -1
- package/dist/transform-C4ZXRVGP.mjs +0 -8
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a raw expression slice has to be wrapped in parens before it is dropped
|
|
3
|
+
* into an object value, an argument list, a `return`, or an arrow's concise body.
|
|
4
|
+
*
|
|
5
|
+
* The compiler holds expressions as source text: `IRExpression.code` is deliberately
|
|
6
|
+
* a string (see ir/nodes.ts), so there is no printer to ask about precedence and the
|
|
7
|
+
* decision comes from the characters.
|
|
8
|
+
*
|
|
9
|
+
* Two things bind wrong. A top-level comma reads as a sequence or as an argument
|
|
10
|
+
* separator, and a leading `{` in an arrow body reads as a block. Everything else
|
|
11
|
+
* parses the same wrapped or bare.
|
|
12
|
+
*
|
|
13
|
+
* Wrapping unconditionally was the old answer, and it reached production: esbuild's
|
|
14
|
+
* minifier keeps redundant parens. Measured on the fluixi-ui playground, 3,320 of
|
|
15
|
+
* the 3,322 bytes the native build ran over the babel one were these.
|
|
16
|
+
*/
|
|
17
|
+
/** Index just past the closing quote, or -1 if the literal never closes. */
|
|
18
|
+
function skipQuoted(src, start) {
|
|
19
|
+
const quote = src[start];
|
|
20
|
+
for (let i = start + 1; i < src.length; i++) {
|
|
21
|
+
const c = src[i];
|
|
22
|
+
if (c === '\\')
|
|
23
|
+
i++;
|
|
24
|
+
else if (c === quote)
|
|
25
|
+
return i + 1;
|
|
26
|
+
else if (c === '\n')
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
return -1;
|
|
30
|
+
}
|
|
31
|
+
/** Index just past the closing backtick. Substitutions nest, so this recurses. */
|
|
32
|
+
function skipTemplate(src, start) {
|
|
33
|
+
let i = start + 1;
|
|
34
|
+
while (i < src.length) {
|
|
35
|
+
const c = src[i];
|
|
36
|
+
if (c === '\\') {
|
|
37
|
+
i += 2;
|
|
38
|
+
}
|
|
39
|
+
else if (c === '`') {
|
|
40
|
+
return i + 1;
|
|
41
|
+
}
|
|
42
|
+
else if (c === '$' && src[i + 1] === '{') {
|
|
43
|
+
let depth = 1;
|
|
44
|
+
i += 2;
|
|
45
|
+
while (i < src.length && depth > 0) {
|
|
46
|
+
const k = src[i];
|
|
47
|
+
if (k === '\\')
|
|
48
|
+
i += 2;
|
|
49
|
+
else if (k === '`') {
|
|
50
|
+
const end = skipTemplate(src, i);
|
|
51
|
+
if (end < 0)
|
|
52
|
+
return -1;
|
|
53
|
+
i = end;
|
|
54
|
+
}
|
|
55
|
+
else if (k === '"' || k === "'") {
|
|
56
|
+
const end = skipQuoted(src, i);
|
|
57
|
+
if (end < 0)
|
|
58
|
+
return -1;
|
|
59
|
+
i = end;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (k === '{')
|
|
63
|
+
depth++;
|
|
64
|
+
else if (k === '}')
|
|
65
|
+
depth--;
|
|
66
|
+
i++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return -1;
|
|
75
|
+
}
|
|
76
|
+
/** Index just past a regex literal's flags, or -1. */
|
|
77
|
+
function skipRegex(src, start) {
|
|
78
|
+
let inClass = false;
|
|
79
|
+
for (let i = start + 1; i < src.length; i++) {
|
|
80
|
+
const c = src[i];
|
|
81
|
+
if (c === '\\')
|
|
82
|
+
i++;
|
|
83
|
+
else if (c === '[')
|
|
84
|
+
inClass = true;
|
|
85
|
+
else if (c === ']')
|
|
86
|
+
inClass = false;
|
|
87
|
+
else if (c === '\n')
|
|
88
|
+
return -1;
|
|
89
|
+
else if (c === '/' && !inClass) {
|
|
90
|
+
let end = i + 1;
|
|
91
|
+
while (end < src.length && /[a-z]/i.test(src[end]))
|
|
92
|
+
end++;
|
|
93
|
+
return end;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return -1;
|
|
97
|
+
}
|
|
98
|
+
/** A `/` after one of these divides; anywhere else it opens a regex. */
|
|
99
|
+
function divides(prev) {
|
|
100
|
+
return prev !== '' && /[A-Za-z0-9_$)\]]/.test(prev);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* True when the text has a comma outside every bracket, string and substitution.
|
|
104
|
+
* Null when the scan cannot say, which the caller reads as "assume it does".
|
|
105
|
+
*/
|
|
106
|
+
export function topLevelComma(src) {
|
|
107
|
+
let depth = 0;
|
|
108
|
+
let prev = '';
|
|
109
|
+
let i = 0;
|
|
110
|
+
while (i < src.length) {
|
|
111
|
+
const c = src[i];
|
|
112
|
+
if (c === '"' || c === "'") {
|
|
113
|
+
const end = skipQuoted(src, i);
|
|
114
|
+
if (end < 0)
|
|
115
|
+
return null;
|
|
116
|
+
i = end;
|
|
117
|
+
prev = c;
|
|
118
|
+
}
|
|
119
|
+
else if (c === '`') {
|
|
120
|
+
const end = skipTemplate(src, i);
|
|
121
|
+
if (end < 0)
|
|
122
|
+
return null;
|
|
123
|
+
i = end;
|
|
124
|
+
prev = c;
|
|
125
|
+
}
|
|
126
|
+
else if (c === '/' && src[i + 1] === '/') {
|
|
127
|
+
// A line comment swallows whatever follows it, and a wrapper is no help.
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
else if (c === '/' && src[i + 1] === '*') {
|
|
131
|
+
const end = src.indexOf('*/', i + 2);
|
|
132
|
+
if (end < 0)
|
|
133
|
+
return null;
|
|
134
|
+
i = end + 2;
|
|
135
|
+
}
|
|
136
|
+
else if (c === '/' && !divides(prev)) {
|
|
137
|
+
const end = skipRegex(src, i);
|
|
138
|
+
if (end < 0)
|
|
139
|
+
return null;
|
|
140
|
+
i = end;
|
|
141
|
+
prev = '/';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
if (c === '(' || c === '[' || c === '{')
|
|
145
|
+
depth++;
|
|
146
|
+
else if (c === ')' || c === ']' || c === '}') {
|
|
147
|
+
depth--;
|
|
148
|
+
if (depth < 0)
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
else if (c === ',' && depth === 0)
|
|
152
|
+
return true;
|
|
153
|
+
if (!/\s/.test(c))
|
|
154
|
+
prev = c;
|
|
155
|
+
i++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return depth === 0 ? false : null;
|
|
159
|
+
}
|
|
160
|
+
/** Wrap a raw expression slice only where the characters say it has to be. */
|
|
161
|
+
export function paren(code, position) {
|
|
162
|
+
const src = code.trim();
|
|
163
|
+
if (src === '')
|
|
164
|
+
return `(${code})`;
|
|
165
|
+
if (position === 'arrowBody' && src[0] === '{')
|
|
166
|
+
return `(${code})`;
|
|
167
|
+
return topLevelComma(src) === false ? code : `(${code})`;
|
|
168
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// src/analyze/paren.ts
|
|
2
|
+
function skipQuoted(src, start) {
|
|
3
|
+
const quote = src[start];
|
|
4
|
+
for (let i = start + 1; i < src.length; i++) {
|
|
5
|
+
const c = src[i];
|
|
6
|
+
if (c === "\\") i++;
|
|
7
|
+
else if (c === quote) return i + 1;
|
|
8
|
+
else if (c === "\n") return -1;
|
|
9
|
+
}
|
|
10
|
+
return -1;
|
|
11
|
+
}
|
|
12
|
+
function skipTemplate(src, start) {
|
|
13
|
+
let i = start + 1;
|
|
14
|
+
while (i < src.length) {
|
|
15
|
+
const c = src[i];
|
|
16
|
+
if (c === "\\") {
|
|
17
|
+
i += 2;
|
|
18
|
+
} else if (c === "`") {
|
|
19
|
+
return i + 1;
|
|
20
|
+
} else if (c === "$" && src[i + 1] === "{") {
|
|
21
|
+
let depth = 1;
|
|
22
|
+
i += 2;
|
|
23
|
+
while (i < src.length && depth > 0) {
|
|
24
|
+
const k = src[i];
|
|
25
|
+
if (k === "\\") i += 2;
|
|
26
|
+
else if (k === "`") {
|
|
27
|
+
const end = skipTemplate(src, i);
|
|
28
|
+
if (end < 0) return -1;
|
|
29
|
+
i = end;
|
|
30
|
+
} else if (k === '"' || k === "'") {
|
|
31
|
+
const end = skipQuoted(src, i);
|
|
32
|
+
if (end < 0) return -1;
|
|
33
|
+
i = end;
|
|
34
|
+
} else {
|
|
35
|
+
if (k === "{") depth++;
|
|
36
|
+
else if (k === "}") depth--;
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
function skipRegex(src, start) {
|
|
47
|
+
let inClass = false;
|
|
48
|
+
for (let i = start + 1; i < src.length; i++) {
|
|
49
|
+
const c = src[i];
|
|
50
|
+
if (c === "\\") i++;
|
|
51
|
+
else if (c === "[") inClass = true;
|
|
52
|
+
else if (c === "]") inClass = false;
|
|
53
|
+
else if (c === "\n") return -1;
|
|
54
|
+
else if (c === "/" && !inClass) {
|
|
55
|
+
let end = i + 1;
|
|
56
|
+
while (end < src.length && /[a-z]/i.test(src[end])) end++;
|
|
57
|
+
return end;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return -1;
|
|
61
|
+
}
|
|
62
|
+
function divides(prev) {
|
|
63
|
+
return prev !== "" && /[A-Za-z0-9_$)\]]/.test(prev);
|
|
64
|
+
}
|
|
65
|
+
function topLevelComma(src) {
|
|
66
|
+
let depth = 0;
|
|
67
|
+
let prev = "";
|
|
68
|
+
let i = 0;
|
|
69
|
+
while (i < src.length) {
|
|
70
|
+
const c = src[i];
|
|
71
|
+
if (c === '"' || c === "'") {
|
|
72
|
+
const end = skipQuoted(src, i);
|
|
73
|
+
if (end < 0) return null;
|
|
74
|
+
i = end;
|
|
75
|
+
prev = c;
|
|
76
|
+
} else if (c === "`") {
|
|
77
|
+
const end = skipTemplate(src, i);
|
|
78
|
+
if (end < 0) return null;
|
|
79
|
+
i = end;
|
|
80
|
+
prev = c;
|
|
81
|
+
} else if (c === "/" && src[i + 1] === "/") {
|
|
82
|
+
return null;
|
|
83
|
+
} else if (c === "/" && src[i + 1] === "*") {
|
|
84
|
+
const end = src.indexOf("*/", i + 2);
|
|
85
|
+
if (end < 0) return null;
|
|
86
|
+
i = end + 2;
|
|
87
|
+
} else if (c === "/" && !divides(prev)) {
|
|
88
|
+
const end = skipRegex(src, i);
|
|
89
|
+
if (end < 0) return null;
|
|
90
|
+
i = end;
|
|
91
|
+
prev = "/";
|
|
92
|
+
} else {
|
|
93
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
94
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
95
|
+
depth--;
|
|
96
|
+
if (depth < 0) return null;
|
|
97
|
+
} else if (c === "," && depth === 0) return true;
|
|
98
|
+
if (!/\s/.test(c)) prev = c;
|
|
99
|
+
i++;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return depth === 0 ? false : null;
|
|
103
|
+
}
|
|
104
|
+
function paren(code, position) {
|
|
105
|
+
const src = code.trim();
|
|
106
|
+
if (src === "") return `(${code})`;
|
|
107
|
+
if (position === "arrowBody" && src[0] === "{") return `(${code})`;
|
|
108
|
+
return topLevelComma(src) === false ? code : `(${code})`;
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
paren,
|
|
112
|
+
topLevelComma
|
|
113
|
+
};
|
|
@@ -1 +1,226 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/analyze/props-destructure.ts
|
|
21
|
+
var props_destructure_exports = {};
|
|
22
|
+
__export(props_destructure_exports, {
|
|
23
|
+
explainBail: () => explainBail,
|
|
24
|
+
planPropsDestructure: () => planPropsDestructure
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(props_destructure_exports);
|
|
27
|
+
function patternNames(node, out) {
|
|
28
|
+
if (!node) return;
|
|
29
|
+
switch (node.type) {
|
|
30
|
+
case "Identifier":
|
|
31
|
+
out.add(node.name);
|
|
32
|
+
return;
|
|
33
|
+
case "ObjectPattern":
|
|
34
|
+
for (const p of node.properties) {
|
|
35
|
+
if (p.type === "RestElement") patternNames(p.argument, out);
|
|
36
|
+
else patternNames(p.value, out);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
case "ArrayPattern":
|
|
40
|
+
for (const e of node.elements) patternNames(e, out);
|
|
41
|
+
return;
|
|
42
|
+
case "AssignmentPattern":
|
|
43
|
+
patternNames(node.left, out);
|
|
44
|
+
return;
|
|
45
|
+
case "RestElement":
|
|
46
|
+
patternNames(node.argument, out);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function isSafeDefault(node) {
|
|
51
|
+
switch (node.type) {
|
|
52
|
+
case "StringLiteral":
|
|
53
|
+
case "NumericLiteral":
|
|
54
|
+
case "BooleanLiteral":
|
|
55
|
+
case "NullLiteral":
|
|
56
|
+
case "BigIntLiteral":
|
|
57
|
+
case "RegExpLiteral":
|
|
58
|
+
case "Identifier":
|
|
59
|
+
return true;
|
|
60
|
+
// ESTree spells every literal as `Literal`; both shapes reach this analysis.
|
|
61
|
+
case "Literal":
|
|
62
|
+
return true;
|
|
63
|
+
case "TemplateLiteral":
|
|
64
|
+
return node.expressions.every(isSafeDefault);
|
|
65
|
+
case "UnaryExpression":
|
|
66
|
+
return isSafeDefault(node.argument);
|
|
67
|
+
case "MemberExpression":
|
|
68
|
+
return false;
|
|
69
|
+
default:
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function walk(root, visit) {
|
|
74
|
+
if (!root || typeof root !== "object") return;
|
|
75
|
+
visit(root);
|
|
76
|
+
for (const key of Object.keys(root)) {
|
|
77
|
+
if (key === "loc" || key === "range" || key === "leadingComments" || key === "trailingComments") continue;
|
|
78
|
+
const value = root[key];
|
|
79
|
+
if (Array.isArray(value)) {
|
|
80
|
+
for (const item of value) if (item && typeof item === "object") walk(item, visit);
|
|
81
|
+
} else if (value && typeof value === "object" && typeof value.type === "string") {
|
|
82
|
+
walk(value, visit);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function reassignedNames(body) {
|
|
87
|
+
const written = /* @__PURE__ */ new Set();
|
|
88
|
+
walk(body, (node) => {
|
|
89
|
+
if (node.type === "AssignmentExpression") patternNames(node.left, written);
|
|
90
|
+
else if (node.type === "UpdateExpression") {
|
|
91
|
+
const arg = node.argument;
|
|
92
|
+
if (arg?.type === "Identifier") written.add(arg.name);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return written;
|
|
96
|
+
}
|
|
97
|
+
function shadowedNames(body, candidates) {
|
|
98
|
+
const shadowed = /* @__PURE__ */ new Set();
|
|
99
|
+
const note = (node) => {
|
|
100
|
+
const names = /* @__PURE__ */ new Set();
|
|
101
|
+
patternNames(node, names);
|
|
102
|
+
for (const n of names) if (candidates.has(n)) shadowed.add(n);
|
|
103
|
+
};
|
|
104
|
+
walk(body, (node) => {
|
|
105
|
+
switch (node.type) {
|
|
106
|
+
case "VariableDeclarator":
|
|
107
|
+
note(node.id);
|
|
108
|
+
return;
|
|
109
|
+
case "FunctionDeclaration":
|
|
110
|
+
case "FunctionExpression":
|
|
111
|
+
case "ArrowFunctionExpression":
|
|
112
|
+
note(node.id);
|
|
113
|
+
for (const p of node.params ?? []) note(p);
|
|
114
|
+
return;
|
|
115
|
+
case "CatchClause":
|
|
116
|
+
note(node.param);
|
|
117
|
+
return;
|
|
118
|
+
case "ClassDeclaration":
|
|
119
|
+
case "ClassExpression":
|
|
120
|
+
note(node.id);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return shadowed;
|
|
125
|
+
}
|
|
126
|
+
function collect(pattern, path, plan) {
|
|
127
|
+
for (const property of pattern.properties ?? []) {
|
|
128
|
+
if (property.type === "RestElement") {
|
|
129
|
+
const argument = property.argument;
|
|
130
|
+
if (argument?.type !== "Identifier" || path.length > 0) {
|
|
131
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
132
|
+
patternNames(argument, names2);
|
|
133
|
+
for (const name of names2) plan.bails.push({ name, reason: "rest" });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
plan.rest = { name: argument.name, keys: [] };
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (property.computed) {
|
|
140
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
141
|
+
patternNames(property.value, names2);
|
|
142
|
+
for (const name of names2) plan.bails.push({ name, reason: "computed" });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const key = property.key;
|
|
146
|
+
const propertyName = key.type === "Identifier" ? key.name : key.value;
|
|
147
|
+
let value = property.value;
|
|
148
|
+
let fallback;
|
|
149
|
+
if (value.type === "AssignmentPattern") {
|
|
150
|
+
fallback = value.right;
|
|
151
|
+
value = value.left;
|
|
152
|
+
}
|
|
153
|
+
const here = [...path, propertyName];
|
|
154
|
+
if (value.type === "Identifier") {
|
|
155
|
+
if (fallback && !isSafeDefault(fallback)) {
|
|
156
|
+
plan.bails.push({ name: value.name, reason: "unsafe-default" });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
plan.reads.push({ name: value.name, path: here, ...fallback ? { fallback } : {} });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (value.type === "ObjectPattern") {
|
|
163
|
+
if (fallback) {
|
|
164
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
165
|
+
patternNames(value, names2);
|
|
166
|
+
for (const name of names2) plan.bails.push({ name, reason: "unsafe-default" });
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
collect(value, here, plan);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const names = /* @__PURE__ */ new Set();
|
|
173
|
+
patternNames(value, names);
|
|
174
|
+
for (const name of names) plan.bails.push({ name, reason: "computed" });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function planPropsDestructure(pattern, body) {
|
|
178
|
+
const plan = { reads: [], bails: [] };
|
|
179
|
+
if (pattern?.type !== "ObjectPattern") return plan;
|
|
180
|
+
collect(pattern, [], plan);
|
|
181
|
+
if (plan.rest) {
|
|
182
|
+
if (body?.type !== "BlockStatement") {
|
|
183
|
+
plan.bails.push({ name: plan.rest.name, reason: "rest" });
|
|
184
|
+
delete plan.rest;
|
|
185
|
+
} else {
|
|
186
|
+
plan.rest.keys = (pattern.properties ?? []).filter((p) => p.type !== "RestElement" && !p.computed).map((p) => {
|
|
187
|
+
const key = p.key;
|
|
188
|
+
return key.type === "Identifier" ? key.name : key.value;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (plan.reads.length === 0 && !plan.rest) return plan;
|
|
193
|
+
const candidates = new Set(plan.reads.map((r) => r.name));
|
|
194
|
+
if (plan.rest) candidates.add(plan.rest.name);
|
|
195
|
+
const written = reassignedNames(body);
|
|
196
|
+
const shadowed = shadowedNames(body, candidates);
|
|
197
|
+
const kept = [];
|
|
198
|
+
for (const read of plan.reads) {
|
|
199
|
+
if (written.has(read.name)) plan.bails.push({ name: read.name, reason: "reassigned" });
|
|
200
|
+
else if (shadowed.has(read.name)) plan.bails.push({ name: read.name, reason: "shadowed" });
|
|
201
|
+
else kept.push(read);
|
|
202
|
+
}
|
|
203
|
+
plan.reads = kept;
|
|
204
|
+
if (plan.rest && written.has(plan.rest.name)) {
|
|
205
|
+
plan.bails.push({ name: plan.rest.name, reason: "reassigned" });
|
|
206
|
+
delete plan.rest;
|
|
207
|
+
} else if (plan.rest && shadowed.has(plan.rest.name)) {
|
|
208
|
+
plan.bails.push({ name: plan.rest.name, reason: "shadowed" });
|
|
209
|
+
delete plan.rest;
|
|
210
|
+
}
|
|
211
|
+
return plan;
|
|
212
|
+
}
|
|
213
|
+
function explainBail(reason) {
|
|
214
|
+
switch (reason) {
|
|
215
|
+
case "rest":
|
|
216
|
+
return "this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters";
|
|
217
|
+
case "computed":
|
|
218
|
+
return "the property is not known until it runs";
|
|
219
|
+
case "reassigned":
|
|
220
|
+
return "the binding is assigned to, and props are read-only";
|
|
221
|
+
case "shadowed":
|
|
222
|
+
return "an inner scope binds the same name";
|
|
223
|
+
case "unsafe-default":
|
|
224
|
+
return "the default would have to run again on every read";
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Props destructuring, without losing reactivity.
|
|
3
|
+
*
|
|
4
|
+
* Props come in as an object of getters, so `props.name` re-reads every time and that
|
|
5
|
+
* keeps a binding current. `const { name } = props` copies the value out once, which is
|
|
6
|
+
* why we call splitProps in about 84 components.
|
|
7
|
+
*
|
|
8
|
+
* The plan here rewrites `name` to `props.name` at each use rather than making it an
|
|
9
|
+
* accessor. `() => props.name` would change the binding's type, and then every use has
|
|
10
|
+
* to change with it: passed to a plain function, stored in an array, compared with
|
|
11
|
+
* `===`. That's a whole-program job. Substitution is one function body and a rename.
|
|
12
|
+
*
|
|
13
|
+
* It does change one thing. A read that happens later sees the current value instead of
|
|
14
|
+
* the value at destructure time, which is the reason to do this at all. Anything past
|
|
15
|
+
* that I leave as written and report, so splitProps stays correct where it's still the
|
|
16
|
+
* right answer.
|
|
17
|
+
*
|
|
18
|
+
* No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
|
|
19
|
+
* transform/bindings.ts does, so either front-end can drive it.
|
|
20
|
+
*/
|
|
21
|
+
interface Node {
|
|
22
|
+
type: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
/** Why a binding was left alone. All of these change more than when the read happens. */
|
|
26
|
+
export type DestructureBail =
|
|
27
|
+
/**
|
|
28
|
+
* A rest we can't serve: destructured further (`...{ a }`), or in a function with no
|
|
29
|
+
* block to put the splitProps call in (`({ a, ...rest }) => …`).
|
|
30
|
+
*/
|
|
31
|
+
'rest'
|
|
32
|
+
/** `const { [key]: a } = props`: we don't know the property until it runs. */
|
|
33
|
+
| 'computed'
|
|
34
|
+
/** The binding gets assigned to, and props are read-only, so it can't become a member. */
|
|
35
|
+
| 'reassigned'
|
|
36
|
+
/** An inner scope binds the same name, so a use site could mean either one. */
|
|
37
|
+
| 'shadowed'
|
|
38
|
+
/**
|
|
39
|
+
* A default we can't re-run on every read: a function hands out a new identity each
|
|
40
|
+
* time, a call runs its side effect each time.
|
|
41
|
+
*/
|
|
42
|
+
| 'unsafe-default';
|
|
43
|
+
export interface PropsRead {
|
|
44
|
+
/** The local name the pattern introduced. */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Property path to read through instead: `['user', 'name']` for `{ user: { name } }`. */
|
|
47
|
+
path: string[];
|
|
48
|
+
/**
|
|
49
|
+
* Default from the pattern. JS only applies one for `undefined`, not for null, so
|
|
50
|
+
* codegen has to test `=== undefined` rather than reach for `??`, and re-run it on
|
|
51
|
+
* every read.
|
|
52
|
+
*/
|
|
53
|
+
fallback?: Node;
|
|
54
|
+
}
|
|
55
|
+
export interface DestructurePlan {
|
|
56
|
+
/** Bindings we can rewrite to a property read. */
|
|
57
|
+
reads: PropsRead[];
|
|
58
|
+
/** Bindings we left alone, with the reason to report. */
|
|
59
|
+
bails: {
|
|
60
|
+
name: string;
|
|
61
|
+
reason: DestructureBail;
|
|
62
|
+
}[];
|
|
63
|
+
/**
|
|
64
|
+
* A `...rest`, and the keys it has to exclude.
|
|
65
|
+
*
|
|
66
|
+
* This is what splitProps is for: it copies the getters across rather than reading
|
|
67
|
+
* them, which is the reason a plain `...rest` can't be rewritten. So instead of
|
|
68
|
+
* refusing the pattern, we write the splitProps call the author would have written.
|
|
69
|
+
*/
|
|
70
|
+
rest?: {
|
|
71
|
+
name: string;
|
|
72
|
+
keys: string[];
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
|
|
77
|
+
* bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
|
|
78
|
+
* and say why).
|
|
79
|
+
*/
|
|
80
|
+
export declare function planPropsDestructure(pattern: Node, body: Node | null | undefined): DestructurePlan;
|
|
81
|
+
/** Reason text for the diagnostic. */
|
|
82
|
+
export declare function explainBail(reason: DestructureBail): string;
|
|
83
|
+
export {};
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* that I leave as written and report, so splitProps stays correct where it's still the
|
|
16
16
|
* right answer.
|
|
17
17
|
*
|
|
18
|
-
* No babel in here (see no-babel-in-core.spec.ts)
|
|
18
|
+
* No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
|
|
19
19
|
* transform/bindings.ts does, so either front-end can drive it.
|
|
20
20
|
*/
|
|
21
21
|
interface Node {
|
|
@@ -29,7 +29,7 @@ export type DestructureBail =
|
|
|
29
29
|
* block to put the splitProps call in (`({ a, ...rest }) => …`).
|
|
30
30
|
*/
|
|
31
31
|
'rest'
|
|
32
|
-
/** `const { [key]: a } = props
|
|
32
|
+
/** `const { [key]: a } = props`: we don't know the property until it runs. */
|
|
33
33
|
| 'computed'
|
|
34
34
|
/** The binding gets assigned to, and props are read-only, so it can't become a member. */
|
|
35
35
|
| 'reassigned'
|
|
@@ -43,7 +43,7 @@ export type DestructureBail =
|
|
|
43
43
|
export interface PropsRead {
|
|
44
44
|
/** The local name the pattern introduced. */
|
|
45
45
|
name: string;
|
|
46
|
-
/** Property path to read through instead
|
|
46
|
+
/** Property path to read through instead: `['user', 'name']` for `{ user: { name } }`. */
|
|
47
47
|
path: string[];
|
|
48
48
|
/**
|
|
49
49
|
* Default from the pattern. JS only applies one for `undefined`, not for null, so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props-destructure.d.ts","sourceRoot":"","sources":["../../src/analyze/props-destructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,yFAAyF;AACzF,MAAM,MAAM,eAAe;AACzB;;;GAGG;AACD,MAAM;AACR
|
|
1
|
+
{"version":3,"file":"props-destructure.d.ts","sourceRoot":"","sources":["../../src/analyze/props-destructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,yFAAyF;AACzF,MAAM,MAAM,eAAe;AACzB;;;GAGG;AACD,MAAM;AACR,8EAA8E;GAC5E,UAAU;AACZ,0FAA0F;GACxF,YAAY;AACd,+EAA+E;GAC7E,UAAU;AACZ;;;GAGG;GACD,gBAAgB,CAAC;AAErB,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,EAAE,CAAC;IACnD;;;;;;OAMG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACzC;AAoLD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,CAgDlG;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAa3D"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* that I leave as written and report, so splitProps stays correct where it's still the
|
|
16
16
|
* right answer.
|
|
17
17
|
*
|
|
18
|
-
* No babel in here (see no-babel-in-core.spec.ts)
|
|
18
|
+
* No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
|
|
19
19
|
* transform/bindings.ts does, so either front-end can drive it.
|
|
20
20
|
*/
|
|
21
21
|
/** Every name a pattern introduces, so we can check each one for shadowing and writes. */
|
|
@@ -48,8 +48,8 @@ function patternNames(node, out) {
|
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Defaults get re-run on every read now, so they have to be cheap and stable. Literals
|
|
51
|
-
* and identifiers are. A function isn't
|
|
52
|
-
* breaks anything comparing props
|
|
51
|
+
* and identifiers are. A function isn't: it hands out a new identity each read, which
|
|
52
|
+
* breaks anything comparing props: and neither is a call.
|
|
53
53
|
*/
|
|
54
54
|
function isSafeDefault(node) {
|
|
55
55
|
switch (node.type) {
|
|
@@ -94,7 +94,7 @@ function walk(root, visit) {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
/** Anything written to in the body
|
|
97
|
+
/** Anything written to in the body: `name = x`, `name++`, `[name] = …`. */
|
|
98
98
|
function reassignedNames(body) {
|
|
99
99
|
const written = new Set();
|
|
100
100
|
walk(body, (node) => {
|