ember-source 6.4.0-alpha.2 → 6.4.0-alpha.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/build-metadata.json +3 -3
- package/dist/ember-template-compiler.js +907 -1527
- package/dist/ember-testing.js +1 -1
- package/dist/ember.debug.js +3574 -4029
- package/dist/ember.prod.js +3408 -3984
- package/dist/packages/@ember/-internals/glimmer/index.js +2 -2
- package/dist/packages/@ember/-internals/owner/index.js +1 -0
- package/dist/packages/@ember/application/index.js +2 -2
- package/dist/packages/@ember/application/instance.js +1 -1
- package/dist/packages/@ember/component/helper.js +1 -1
- package/dist/packages/@ember/component/index.js +1 -1
- package/dist/packages/@ember/debug/lib/capture-render-tree.js +5 -3
- package/dist/packages/@ember/engine/index.js +2 -2
- package/dist/packages/@ember/helper/index.js +1 -1
- package/dist/packages/@ember/modifier/index.js +1 -1
- package/dist/packages/@ember/renderer/index.js +1 -1
- package/dist/packages/@ember/routing/index.js +1 -1
- package/dist/packages/@ember/template/index.js +1 -1
- package/dist/packages/@ember/template-compiler/lib/plugins/index.js +1 -1
- package/dist/packages/@ember/template-compiler/lib/plugins/transform-resolutions.js +1 -1
- package/dist/packages/@ember/template-compiler/lib/template.js +73 -89
- package/dist/packages/@glimmer/destroyable/index.js +45 -16
- package/dist/packages/@glimmer/encoder/index.js +1 -2
- package/dist/packages/@glimmer/global-context/index.js +15 -27
- package/dist/packages/@glimmer/manager/index.js +137 -84
- package/dist/packages/@glimmer/node/index.js +7 -4
- package/dist/packages/@glimmer/opcode-compiler/index.js +564 -534
- package/dist/packages/@glimmer/owner/index.js +1 -0
- package/dist/packages/@glimmer/program/index.js +42 -109
- package/dist/packages/@glimmer/reference/index.js +18 -29
- package/dist/packages/@glimmer/runtime/index.js +3435 -3263
- package/dist/packages/@glimmer/util/index.js +32 -273
- package/dist/packages/@glimmer/validator/index.js +36 -43
- package/dist/packages/@glimmer/vm/index.js +2 -140
- package/dist/packages/@glimmer/wire-format/index.js +1 -2
- package/dist/packages/ember/barrel.js +1 -1
- package/dist/packages/ember/version.js +1 -1
- package/dist/packages/ember-testing/lib/initializers.js +1 -1
- package/dist/packages/shared-chunks/{index-CQygUgr9.js → index-y5ClupI2.js} +50 -45
- package/dist/packages/shared-chunks/{setup-registry-DXuvS1Rj.js → setup-registry-8yPevDL_.js} +1 -1
- package/dist/packages/shared-chunks/{transform-resolutions-O6uYv8DS.js → transform-resolutions-Dpc2ClA0.js} +298 -441
- package/docs/data.json +40 -22
- package/package.json +21 -22
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/outlet.d.ts +1 -1
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/unwrap-template.d.ts +7 -0
- package/types/stable/@ember/-internals/glimmer/lib/renderer.d.ts +7 -9
- package/types/stable/@ember/-internals/glimmer/lib/resolver.d.ts +2 -5
- package/types/stable/index.d.ts +1 -0
- package/dist/packages/@glimmer/debug/index.js +0 -168
|
@@ -1,10 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Op, MachineOp, $v0, $fp, InternalComponentCapabilities, $s0, $sp, ContentType, $s1, TYPE_SIZE, isMachineOp, MACHINE_MASK, ARG_SHIFT } from '../vm/index.js';
|
|
1
|
+
import { EMPTY_STRING_ARRAY, reverse, Stack as StackImpl, EMPTY_ARRAY, assign, enumerate, dict } from '../util/index.js';
|
|
3
2
|
import { InstructionEncoderImpl } from '../encoder/index.js';
|
|
3
|
+
import { $v0, $fp, InternalComponentCapabilities, $s0, $sp, ContentType, $s1, TYPE_SIZE, MACHINE_MASK, ARG_SHIFT } from '../vm/index.js';
|
|
4
4
|
import { SexpOpcodes as opcodes } from '../wire-format/index.js';
|
|
5
5
|
import { hasCapability } from '../manager/index.js';
|
|
6
6
|
import { isDevelopingApp } from '@embroider/macros';
|
|
7
7
|
|
|
8
|
+
let debugToString;
|
|
9
|
+
if (isDevelopingApp()) {
|
|
10
|
+
let getFunctionName = fn => {
|
|
11
|
+
let functionName = fn.name;
|
|
12
|
+
if ("" === functionName) {
|
|
13
|
+
let match = /function (\w+)\s*\(/u.exec(String(fn));
|
|
14
|
+
functionName = match && match[1] || "";
|
|
15
|
+
}
|
|
16
|
+
return functionName.replace(/^bound /u, "");
|
|
17
|
+
},
|
|
18
|
+
getObjectName = obj => {
|
|
19
|
+
let name, className;
|
|
20
|
+
// If the class has a decent looking name, and the `toString` is one of the
|
|
21
|
+
// default Ember toStrings, replace the constructor portion of the toString
|
|
22
|
+
// with the class name. We check the length of the class name to prevent doing
|
|
23
|
+
// this when the value is minified.
|
|
24
|
+
return "function" == typeof obj.constructor && (className = getFunctionName(obj.constructor)), "toString" in obj && obj.toString !== Object.prototype.toString && obj.toString !== Function.prototype.toString && (
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
26
|
+
name = obj.toString()), name && /<.*:ember\d+>/u.test(name) && className && "_" !== className[0] && className.length > 2 && "Class" !== className ? name.replace(/<.*:/u, `<${className}:`) : name || className;
|
|
27
|
+
},
|
|
28
|
+
getPrimitiveName = value => String(value);
|
|
29
|
+
debugToString = value => "function" == typeof value ? getFunctionName(value) || "(unknown function)" : "object" == typeof value && null !== value ? getObjectName(value) || "(unknown object)" : getPrimitiveName(value);
|
|
30
|
+
}
|
|
31
|
+
var debugToString$1 = debugToString;
|
|
32
|
+
function encodeImmediate(num) {
|
|
33
|
+
return (num |= 0) < 0 ? function (num) {
|
|
34
|
+
return -536870913 & num;
|
|
35
|
+
}(num) : function (num) {
|
|
36
|
+
return ~num;
|
|
37
|
+
}(num);
|
|
38
|
+
}
|
|
8
39
|
let debugCompiler;
|
|
9
40
|
function makeResolutionTypeVerifier(typeToVerify) {
|
|
10
41
|
return opcode => {
|
|
@@ -15,14 +46,21 @@ function makeResolutionTypeVerifier(typeToVerify) {
|
|
|
15
46
|
return type === opcodes.GetStrictKeyword || type === opcodes.GetLexicalSymbol || type === typeToVerify;
|
|
16
47
|
};
|
|
17
48
|
}
|
|
18
|
-
|
|
49
|
+
[1, -1].forEach(x => {
|
|
50
|
+
return num = encodeImmediate(x), (num |= 0) > -536870913 ? function (num) {
|
|
51
|
+
return ~num;
|
|
52
|
+
}(num) : function (num) {
|
|
53
|
+
return 536870912 | num;
|
|
54
|
+
}(num);
|
|
55
|
+
var num;
|
|
56
|
+
});
|
|
19
57
|
const isGetFreeComponent = makeResolutionTypeVerifier(opcodes.GetFreeAsComponentHead),
|
|
20
58
|
isGetFreeModifier = makeResolutionTypeVerifier(opcodes.GetFreeAsModifierHead),
|
|
21
59
|
isGetFreeHelper = makeResolutionTypeVerifier(opcodes.GetFreeAsHelperHead),
|
|
22
60
|
isGetFreeComponentOrHelper = makeResolutionTypeVerifier(opcodes.GetFreeAsComponentOrHelperHead);
|
|
23
61
|
function assertResolverInvariants(meta) {
|
|
24
62
|
if (isDevelopingApp()) {
|
|
25
|
-
if (!meta.upvars) throw new Error("Attempted to resolve a component, helper, or modifier, but no free vars were found");
|
|
63
|
+
if (!meta.symbols.upvars) throw new Error("Attempted to resolve a component, helper, or modifier, but no free vars were found");
|
|
26
64
|
if (!meta.owner) throw new Error("Attempted to resolve a component, helper, or modifier, but no owner was associated with the template it was being resolved from");
|
|
27
65
|
}
|
|
28
66
|
return meta;
|
|
@@ -35,75 +73,45 @@ function assertResolverInvariants(meta) {
|
|
|
35
73
|
*/
|
|
36
74
|
function lookupBuiltInHelper(expr, resolver, meta, constants, type) {
|
|
37
75
|
let {
|
|
38
|
-
|
|
76
|
+
symbols: {
|
|
77
|
+
upvars: upvars
|
|
78
|
+
}
|
|
39
79
|
} = assertResolverInvariants(meta),
|
|
40
|
-
name =
|
|
41
|
-
helper = resolver
|
|
80
|
+
name = upvars[expr[1]],
|
|
81
|
+
helper = resolver?.lookupBuiltInHelper?.(name) ?? null;
|
|
42
82
|
if (isDevelopingApp() && null === helper)
|
|
43
83
|
// Keyword helper did not exist, which means that we're attempting to use a
|
|
44
84
|
// value of some kind that is not in scope
|
|
45
|
-
throw
|
|
85
|
+
throw meta.isStrictMode, new Error(`Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
86
|
+
meta.symbols.upvars[expr[1]] ?? "{unknown variable}"}`);
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
46
88
|
return constants.helper(helper, name);
|
|
47
89
|
}
|
|
48
|
-
const HighLevelResolutionOpcodes = {
|
|
49
|
-
Modifier: 1003,
|
|
50
|
-
Component: 1004,
|
|
51
|
-
Helper: 1005,
|
|
52
|
-
ComponentOrHelper: 1007,
|
|
53
|
-
OptionalComponentOrHelper: 1008,
|
|
54
|
-
Local: 1010,
|
|
55
|
-
TemplateLocal: 1011
|
|
56
|
-
},
|
|
57
|
-
HighLevelBuilderOpcodes = {
|
|
58
|
-
Label: 1e3,
|
|
59
|
-
StartLabels: 1001,
|
|
60
|
-
StopLabels: 1002,
|
|
61
|
-
Start: 1e3,
|
|
62
|
-
End: 1002
|
|
63
|
-
},
|
|
64
|
-
HighLevelOperands = {
|
|
65
|
-
Label: 1,
|
|
66
|
-
IsStrictMode: 2,
|
|
67
|
-
DebugSymbols: 3,
|
|
68
|
-
Block: 4,
|
|
69
|
-
StdLib: 5,
|
|
70
|
-
NonSmallInt: 6,
|
|
71
|
-
SymbolTable: 7,
|
|
72
|
-
Layout: 8
|
|
73
|
-
};
|
|
74
90
|
function labelOperand(value) {
|
|
75
91
|
return {
|
|
76
|
-
type:
|
|
92
|
+
type: 1,
|
|
77
93
|
value: value
|
|
78
94
|
};
|
|
79
95
|
}
|
|
80
|
-
function isStrictMode() {
|
|
81
|
-
return {
|
|
82
|
-
type: HighLevelOperands.IsStrictMode,
|
|
83
|
-
value: void 0
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
96
|
function stdlibOperand(value) {
|
|
87
97
|
return {
|
|
88
|
-
type:
|
|
98
|
+
type: 5,
|
|
89
99
|
value: value
|
|
90
100
|
};
|
|
91
101
|
}
|
|
92
102
|
function symbolTableOperand(value) {
|
|
93
103
|
return {
|
|
94
|
-
type:
|
|
104
|
+
type: 7,
|
|
95
105
|
value: value
|
|
96
106
|
};
|
|
97
107
|
}
|
|
98
108
|
function layoutOperand(value) {
|
|
99
109
|
return {
|
|
100
|
-
type:
|
|
110
|
+
type: 8,
|
|
101
111
|
value: value
|
|
102
112
|
};
|
|
103
113
|
}
|
|
104
114
|
class Labels {
|
|
105
|
-
labels = dict();
|
|
106
|
-
targets = [];
|
|
107
115
|
label(name, index) {
|
|
108
116
|
this.labels[name] = index;
|
|
109
117
|
}
|
|
@@ -122,44 +130,61 @@ class Labels {
|
|
|
122
130
|
at: at,
|
|
123
131
|
target: target
|
|
124
132
|
} of targets) {
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
125
134
|
let address = labels[target] - at;
|
|
126
|
-
|
|
135
|
+
heap.getbyaddr(at), heap.setbyaddr(at, address);
|
|
127
136
|
}
|
|
128
137
|
}
|
|
138
|
+
constructor() {
|
|
139
|
+
this.labels = dict(), this.targets = [];
|
|
140
|
+
}
|
|
129
141
|
}
|
|
130
|
-
function encodeOp(encoder,
|
|
142
|
+
function encodeOp(encoder, context, meta, op) {
|
|
143
|
+
let {
|
|
144
|
+
program: {
|
|
145
|
+
constants: constants
|
|
146
|
+
},
|
|
147
|
+
resolver: resolver
|
|
148
|
+
} = context;
|
|
131
149
|
if (function (op) {
|
|
132
|
-
return op <
|
|
150
|
+
return op < 1e3;
|
|
133
151
|
}(op[0])) {
|
|
134
152
|
let [type, ...operands] = op;
|
|
135
153
|
encoder.push(constants, type, ...operands);
|
|
136
154
|
} else switch (op[0]) {
|
|
137
|
-
case
|
|
155
|
+
case 1e3:
|
|
138
156
|
return encoder.label(op[1]);
|
|
139
|
-
case
|
|
157
|
+
case 1001:
|
|
140
158
|
return encoder.startLabels();
|
|
141
|
-
case
|
|
159
|
+
case 1002:
|
|
142
160
|
return encoder.stopLabels();
|
|
143
|
-
case
|
|
161
|
+
case 1004:
|
|
144
162
|
return function (resolver, constants, meta, [, expr, then]) {
|
|
145
|
-
|
|
163
|
+
isGetFreeComponent(expr);
|
|
146
164
|
let type = expr[0];
|
|
147
|
-
if (isDevelopingApp() && expr[0] === opcodes.GetStrictKeyword) throw
|
|
165
|
+
if (isDevelopingApp() && expr[0] === opcodes.GetStrictKeyword) throw meta.isStrictMode, new Error(`Attempted to resolve a component in a strict mode template, but that value was not in scope: ${// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
166
|
+
meta.symbols.upvars[expr[1]] ?? "{unknown variable}"}`);
|
|
148
167
|
if (type === opcodes.GetLexicalSymbol) {
|
|
149
168
|
let {
|
|
150
169
|
scopeValues: scopeValues,
|
|
151
|
-
owner: owner
|
|
170
|
+
owner: owner,
|
|
171
|
+
symbols: {
|
|
172
|
+
lexical: lexical
|
|
173
|
+
}
|
|
152
174
|
} = meta,
|
|
153
|
-
definition =
|
|
154
|
-
then(constants.component(definition,
|
|
175
|
+
definition = scopeValues[expr[1]];
|
|
176
|
+
then(constants.component(definition, owner, !1, lexical?.at(expr[1])));
|
|
155
177
|
} else {
|
|
156
178
|
let {
|
|
157
|
-
|
|
179
|
+
symbols: {
|
|
180
|
+
upvars: upvars
|
|
181
|
+
},
|
|
158
182
|
owner: owner
|
|
159
183
|
} = assertResolverInvariants(meta),
|
|
160
|
-
name =
|
|
161
|
-
definition = resolver
|
|
162
|
-
if (isDevelopingApp() && ("object" != typeof definition || null === definition)) throw
|
|
184
|
+
name = upvars[expr[1]],
|
|
185
|
+
definition = resolver?.lookupComponent?.(name, owner) ?? null;
|
|
186
|
+
if (isDevelopingApp() && ("object" != typeof definition || null === definition)) throw meta.isStrictMode, new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`);
|
|
187
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
163
188
|
then(constants.resolvedComponent(definition, name));
|
|
164
189
|
}
|
|
165
190
|
}
|
|
@@ -167,92 +192,112 @@ function encodeOp(encoder, constants, resolver, meta, op) {
|
|
|
167
192
|
* (helper)
|
|
168
193
|
* (helper arg)
|
|
169
194
|
*/(resolver, constants, meta, op);
|
|
170
|
-
case
|
|
195
|
+
case 1003:
|
|
171
196
|
/**
|
|
172
197
|
* <div {{modifier}}/>
|
|
173
198
|
* <div {{modifier arg}}/>
|
|
174
199
|
* <Foo {{modifier}}/>
|
|
175
200
|
*/
|
|
176
201
|
return function (resolver, constants, meta, [, expr, then]) {
|
|
177
|
-
|
|
202
|
+
isGetFreeModifier(expr);
|
|
178
203
|
let type = expr[0];
|
|
179
204
|
if (type === opcodes.GetLexicalSymbol) {
|
|
180
205
|
let {
|
|
181
|
-
scopeValues: scopeValues
|
|
206
|
+
scopeValues: scopeValues,
|
|
207
|
+
symbols: {
|
|
208
|
+
lexical: lexical
|
|
209
|
+
}
|
|
182
210
|
} = meta,
|
|
183
|
-
definition =
|
|
184
|
-
then(constants.modifier(definition));
|
|
211
|
+
definition = scopeValues[expr[1]];
|
|
212
|
+
then(constants.modifier(definition, lexical?.at(expr[1]) ?? void 0));
|
|
185
213
|
} else if (type === opcodes.GetStrictKeyword) {
|
|
186
214
|
let {
|
|
187
|
-
|
|
215
|
+
symbols: {
|
|
216
|
+
upvars: upvars
|
|
217
|
+
}
|
|
188
218
|
} = assertResolverInvariants(meta),
|
|
189
|
-
name =
|
|
190
|
-
modifier = resolver
|
|
191
|
-
if (isDevelopingApp() && null === modifier) throw
|
|
219
|
+
name = upvars[expr[1]],
|
|
220
|
+
modifier = resolver?.lookupBuiltInModifier?.(name) ?? null;
|
|
221
|
+
if (isDevelopingApp() && null === modifier) throw meta.isStrictMode, new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`);
|
|
222
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
192
223
|
then(constants.modifier(modifier, name));
|
|
193
224
|
} else {
|
|
194
225
|
let {
|
|
195
|
-
|
|
226
|
+
symbols: {
|
|
227
|
+
upvars: upvars
|
|
228
|
+
},
|
|
196
229
|
owner: owner
|
|
197
230
|
} = assertResolverInvariants(meta),
|
|
198
|
-
name =
|
|
199
|
-
modifier = resolver
|
|
200
|
-
if (isDevelopingApp() && null === modifier) throw
|
|
201
|
-
|
|
231
|
+
name = upvars[expr[1]],
|
|
232
|
+
modifier = resolver?.lookupModifier?.(name, owner) ?? null;
|
|
233
|
+
if (isDevelopingApp() && null === modifier) throw meta.isStrictMode, new Error(`Attempted to resolve \`${name}\`, which was expected to be a modifier, but nothing was found.`);
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
235
|
+
then(constants.modifier(modifier));
|
|
202
236
|
}
|
|
203
237
|
}
|
|
204
238
|
/**
|
|
205
239
|
* {{component-or-helper arg}}
|
|
206
240
|
*/(resolver, constants, meta, op);
|
|
207
|
-
case
|
|
241
|
+
case 1005:
|
|
208
242
|
return function (resolver, constants, meta, [, expr, then]) {
|
|
209
|
-
|
|
243
|
+
isGetFreeHelper(expr);
|
|
210
244
|
let type = expr[0];
|
|
211
245
|
if (type === opcodes.GetLexicalSymbol) {
|
|
212
246
|
let {
|
|
213
247
|
scopeValues: scopeValues
|
|
214
248
|
} = meta,
|
|
215
|
-
definition =
|
|
249
|
+
definition = scopeValues[expr[1]];
|
|
216
250
|
then(constants.helper(definition));
|
|
217
251
|
} else if (type === opcodes.GetStrictKeyword) then(lookupBuiltInHelper(expr, resolver, meta, constants, "helper"));else {
|
|
218
252
|
let {
|
|
219
|
-
|
|
253
|
+
symbols: {
|
|
254
|
+
upvars: upvars
|
|
255
|
+
},
|
|
220
256
|
owner: owner
|
|
221
257
|
} = assertResolverInvariants(meta),
|
|
222
|
-
name =
|
|
223
|
-
helper = resolver
|
|
224
|
-
if (isDevelopingApp() && null === helper) throw
|
|
258
|
+
name = upvars[expr[1]],
|
|
259
|
+
helper = resolver?.lookupHelper?.(name, owner) ?? null;
|
|
260
|
+
if (isDevelopingApp() && null === helper) throw meta.isStrictMode, new Error(`Attempted to resolve \`${name}\`, which was expected to be a helper, but nothing was found.`);
|
|
261
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
225
262
|
then(constants.helper(helper, name));
|
|
226
263
|
}
|
|
227
264
|
}(resolver, constants, meta, op);
|
|
228
|
-
case
|
|
265
|
+
case 1007:
|
|
229
266
|
return function (resolver, constants, meta, [, expr, {
|
|
230
267
|
ifComponent: ifComponent,
|
|
231
268
|
ifHelper: ifHelper
|
|
232
269
|
}]) {
|
|
233
|
-
|
|
270
|
+
isGetFreeComponentOrHelper(expr);
|
|
234
271
|
let type = expr[0];
|
|
235
272
|
if (type === opcodes.GetLexicalSymbol) {
|
|
236
273
|
let {
|
|
237
274
|
scopeValues: scopeValues,
|
|
238
|
-
owner: owner
|
|
275
|
+
owner: owner,
|
|
276
|
+
symbols: {
|
|
277
|
+
lexical: lexical
|
|
278
|
+
}
|
|
239
279
|
} = meta,
|
|
240
|
-
definition =
|
|
241
|
-
component = constants.component(definition,
|
|
280
|
+
definition = scopeValues[expr[1]],
|
|
281
|
+
component = constants.component(definition, owner, !0, lexical?.at(expr[1]));
|
|
242
282
|
if (null !== component) return void ifComponent(component);
|
|
243
283
|
let helper = constants.helper(definition, null, !0);
|
|
244
|
-
if (isDevelopingApp() && null === helper) throw
|
|
245
|
-
|
|
284
|
+
if (isDevelopingApp() && null === helper) throw meta.isStrictMode, new Error(
|
|
285
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
286
|
+
`Attempted to use a value as either a component or helper, but it did not have a component manager or helper manager associated with it. The value was: ${debugToString$1(definition)}`);
|
|
287
|
+
ifHelper(helper);
|
|
246
288
|
} else if (type === opcodes.GetStrictKeyword) ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, "component or helper"));else {
|
|
247
289
|
let {
|
|
248
|
-
|
|
290
|
+
symbols: {
|
|
291
|
+
upvars: upvars
|
|
292
|
+
},
|
|
249
293
|
owner: owner
|
|
250
294
|
} = assertResolverInvariants(meta),
|
|
251
|
-
name =
|
|
252
|
-
definition = resolver
|
|
295
|
+
name = upvars[expr[1]],
|
|
296
|
+
definition = resolver?.lookupComponent?.(name, owner) ?? null;
|
|
253
297
|
if (null !== definition) ifComponent(constants.resolvedComponent(definition, name));else {
|
|
254
|
-
let helper = resolver
|
|
255
|
-
if (isDevelopingApp() && null === helper) throw
|
|
298
|
+
let helper = resolver?.lookupHelper?.(name, owner) ?? null;
|
|
299
|
+
if (isDevelopingApp() && null === helper) throw meta.isStrictMode, new Error(`Attempted to resolve \`${name}\`, which was expected to be a component or helper, but nothing was found.`);
|
|
300
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
256
301
|
ifHelper(constants.helper(helper, name));
|
|
257
302
|
}
|
|
258
303
|
}
|
|
@@ -260,51 +305,56 @@ function encodeOp(encoder, constants, resolver, meta, op) {
|
|
|
260
305
|
/**
|
|
261
306
|
* {{maybeHelperOrComponent}}
|
|
262
307
|
*/(resolver, constants, meta, op);
|
|
263
|
-
case
|
|
308
|
+
case 1008:
|
|
264
309
|
return function (resolver, constants, meta, [, expr, {
|
|
265
310
|
ifComponent: ifComponent,
|
|
266
311
|
ifHelper: ifHelper,
|
|
267
312
|
ifValue: ifValue
|
|
268
313
|
}]) {
|
|
269
|
-
|
|
314
|
+
isGetFreeComponentOrHelper(expr);
|
|
270
315
|
let type = expr[0];
|
|
271
316
|
if (type === opcodes.GetLexicalSymbol) {
|
|
272
317
|
let {
|
|
273
318
|
scopeValues: scopeValues,
|
|
274
|
-
owner: owner
|
|
319
|
+
owner: owner,
|
|
320
|
+
symbols: {
|
|
321
|
+
lexical: lexical
|
|
322
|
+
}
|
|
275
323
|
} = meta,
|
|
276
|
-
definition =
|
|
324
|
+
definition = scopeValues[expr[1]];
|
|
277
325
|
if ("function" != typeof definition && ("object" != typeof definition || null === definition))
|
|
278
326
|
// The value is not an object, so it can't be a component or helper.
|
|
279
327
|
return void ifValue(constants.value(definition));
|
|
280
|
-
let component = constants.component(definition,
|
|
328
|
+
let component = constants.component(definition, owner, !0, lexical?.at(expr[1]));
|
|
281
329
|
if (null !== component) return void ifComponent(component);
|
|
282
330
|
let helper = constants.helper(definition, null, !0);
|
|
283
331
|
if (null !== helper) return void ifHelper(helper);
|
|
284
332
|
ifValue(constants.value(definition));
|
|
285
333
|
} else if (type === opcodes.GetStrictKeyword) ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, "value"));else {
|
|
286
334
|
let {
|
|
287
|
-
|
|
335
|
+
symbols: {
|
|
336
|
+
upvars: upvars
|
|
337
|
+
},
|
|
288
338
|
owner: owner
|
|
289
339
|
} = assertResolverInvariants(meta),
|
|
290
|
-
name =
|
|
291
|
-
definition = resolver
|
|
340
|
+
name = upvars[expr[1]],
|
|
341
|
+
definition = resolver?.lookupComponent?.(name, owner) ?? null;
|
|
292
342
|
if (null !== definition) return void ifComponent(constants.resolvedComponent(definition, name));
|
|
293
|
-
let helper = resolver
|
|
343
|
+
let helper = resolver?.lookupHelper?.(name, owner) ?? null;
|
|
294
344
|
null !== helper && ifHelper(constants.helper(helper, name));
|
|
295
345
|
}
|
|
296
346
|
}(resolver, constants, meta, op);
|
|
297
|
-
case
|
|
347
|
+
case 1010:
|
|
298
348
|
{
|
|
299
|
-
let freeVar = op
|
|
300
|
-
|
|
301
|
-
(
|
|
349
|
+
let [, freeVar, andThen] = op;
|
|
350
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
|
|
351
|
+
andThen(meta.symbols.upvars[freeVar], meta.moduleName);
|
|
302
352
|
break;
|
|
303
353
|
}
|
|
304
|
-
case
|
|
354
|
+
case 1011:
|
|
305
355
|
{
|
|
306
356
|
let [, valueIndex, then] = op,
|
|
307
|
-
value =
|
|
357
|
+
value = meta.scopeValues[valueIndex];
|
|
308
358
|
then(constants.value(value));
|
|
309
359
|
break;
|
|
310
360
|
}
|
|
@@ -313,29 +363,27 @@ function encodeOp(encoder, constants, resolver, meta, op) {
|
|
|
313
363
|
}
|
|
314
364
|
}
|
|
315
365
|
class EncoderImpl {
|
|
316
|
-
labelsStack = new StackImpl();
|
|
317
|
-
encoder = new InstructionEncoderImpl([]);
|
|
318
|
-
errors = [];
|
|
319
|
-
handle;
|
|
320
366
|
constructor(heap, meta, stdlib) {
|
|
321
|
-
this.heap = heap, this.meta = meta, this.stdlib = stdlib, this.handle = heap.malloc();
|
|
367
|
+
this.heap = heap, this.meta = meta, this.stdlib = stdlib, this.labelsStack = new StackImpl(), this.encoder = new InstructionEncoderImpl([]), this.errors = [], this.handle = heap.malloc();
|
|
322
368
|
}
|
|
323
369
|
error(error) {
|
|
324
|
-
this.encoder.encode(
|
|
370
|
+
this.encoder.encode(30, 0), this.errors.push(error);
|
|
325
371
|
}
|
|
326
372
|
commit(size) {
|
|
327
373
|
let handle = this.handle;
|
|
328
|
-
return this.heap.pushMachine(
|
|
374
|
+
return this.heap.pushMachine(5), this.heap.finishMalloc(handle, size), (list = this.errors) && list.length > 0 ? {
|
|
329
375
|
errors: this.errors,
|
|
330
376
|
handle: handle
|
|
331
377
|
} : handle;
|
|
378
|
+
var list;
|
|
332
379
|
}
|
|
333
380
|
push(constants, type, ...args) {
|
|
334
381
|
let {
|
|
335
382
|
heap: heap
|
|
336
383
|
} = this;
|
|
337
384
|
if (isDevelopingApp() && type > TYPE_SIZE) throw new Error(`Opcode type over 8-bits. Got ${type}.`);
|
|
338
|
-
|
|
385
|
+
var value;
|
|
386
|
+
let first = type | ((value = type) >= 0 && value <= 15 ? MACHINE_MASK : 0) | args.length << ARG_SHIFT;
|
|
339
387
|
heap.pushRaw(first);
|
|
340
388
|
for (let i = 0; i < args.length; i++) {
|
|
341
389
|
let op = args[i];
|
|
@@ -345,31 +393,30 @@ class EncoderImpl {
|
|
|
345
393
|
operand(constants, operand) {
|
|
346
394
|
if ("number" == typeof operand) return operand;
|
|
347
395
|
if ("object" == typeof operand && null !== operand) {
|
|
348
|
-
if (Array.isArray(operand)) return
|
|
396
|
+
if (Array.isArray(operand)) return constants.array(operand);
|
|
349
397
|
switch (operand.type) {
|
|
350
|
-
case
|
|
398
|
+
case 1:
|
|
351
399
|
return this.currentLabels.target(this.heap.offset, operand.value), -1;
|
|
352
|
-
case
|
|
353
|
-
return
|
|
354
|
-
case
|
|
355
|
-
|
|
356
|
-
case
|
|
357
|
-
|
|
358
|
-
parameters: block[1] || EMPTY_ARRAY
|
|
359
|
-
}))));
|
|
360
|
-
case HighLevelOperands.StdLib:
|
|
361
|
-
return expect(this.stdlib, "attempted to encode a stdlib operand, but the encoder did not have a stdlib. Are you currently building the stdlib?")[operand.value];
|
|
362
|
-
case HighLevelOperands.NonSmallInt:
|
|
363
|
-
case HighLevelOperands.SymbolTable:
|
|
364
|
-
case HighLevelOperands.Layout:
|
|
400
|
+
case 2:
|
|
401
|
+
return constants.value(this.meta.isStrictMode);
|
|
402
|
+
case 3:
|
|
403
|
+
case 6:
|
|
404
|
+
case 7:
|
|
405
|
+
case 8:
|
|
365
406
|
return constants.value(operand.value);
|
|
407
|
+
case 4:
|
|
408
|
+
return constants.value((block = operand.value, containing = this.meta, new CompilableTemplateImpl(block[0], containing, {
|
|
409
|
+
parameters: block[1] || EMPTY_ARRAY
|
|
410
|
+
})));
|
|
411
|
+
case 5:
|
|
412
|
+
return this.stdlib[operand.value];
|
|
366
413
|
}
|
|
367
414
|
}
|
|
368
415
|
var block, containing;
|
|
369
|
-
return
|
|
416
|
+
return constants.value(operand);
|
|
370
417
|
}
|
|
371
418
|
get currentLabels() {
|
|
372
|
-
return
|
|
419
|
+
return this.labelsStack.current;
|
|
373
420
|
}
|
|
374
421
|
label(name) {
|
|
375
422
|
this.currentLabels.label(name, this.heap.offset + 1);
|
|
@@ -378,64 +425,38 @@ class EncoderImpl {
|
|
|
378
425
|
this.labelsStack.push(new Labels());
|
|
379
426
|
}
|
|
380
427
|
stopLabels() {
|
|
381
|
-
|
|
428
|
+
this.labelsStack.pop().patch(this.heap);
|
|
382
429
|
}
|
|
383
430
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
get "cautious-append"() {
|
|
392
|
-
return this.cautiousGuardedAppend;
|
|
393
|
-
}
|
|
394
|
-
get "trusting-non-dynamic-append"() {
|
|
395
|
-
return this.trustingNonDynamicAppend;
|
|
396
|
-
}
|
|
397
|
-
get "cautious-non-dynamic-append"() {
|
|
398
|
-
return this.cautiousNonDynamicAppend;
|
|
399
|
-
}
|
|
400
|
-
getAppend(trusting) {
|
|
401
|
-
return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend;
|
|
402
|
-
}
|
|
431
|
+
function templateCompilationContext(evaluation, meta) {
|
|
432
|
+
return {
|
|
433
|
+
evaluation: evaluation,
|
|
434
|
+
encoder: new EncoderImpl(evaluation.program.heap, meta, evaluation.stdlib),
|
|
435
|
+
meta: meta
|
|
436
|
+
};
|
|
403
437
|
}
|
|
404
|
-
class
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
this.blocks = blocks, this.names = blocks ? Object.keys(blocks) : [];
|
|
408
|
-
}
|
|
409
|
-
get(name) {
|
|
410
|
-
return this.blocks && this.blocks[name] || null;
|
|
411
|
-
}
|
|
412
|
-
has(name) {
|
|
413
|
-
let {
|
|
414
|
-
blocks: blocks
|
|
415
|
-
} = this;
|
|
416
|
-
return null !== blocks && name in blocks;
|
|
438
|
+
class Compilers {
|
|
439
|
+
add(name, func) {
|
|
440
|
+
this.names[name] = this.funcs.push(func) - 1;
|
|
417
441
|
}
|
|
418
|
-
|
|
419
|
-
let
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
[name]: block
|
|
424
|
-
}) : {
|
|
425
|
-
[name]: block
|
|
426
|
-
});
|
|
442
|
+
compile(op, sexp) {
|
|
443
|
+
let name = sexp[0],
|
|
444
|
+
index = this.names[name],
|
|
445
|
+
func = this.funcs[index];
|
|
446
|
+
sexp[0], func(op, sexp);
|
|
427
447
|
}
|
|
428
|
-
|
|
429
|
-
|
|
448
|
+
constructor() {
|
|
449
|
+
this.names = {},
|
|
450
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
451
|
+
this.funcs = [];
|
|
430
452
|
}
|
|
431
453
|
}
|
|
432
|
-
const
|
|
433
|
-
function
|
|
434
|
-
if (
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return new NamedBlocksImpl(out);
|
|
454
|
+
const EXPRESSIONS = new Compilers();
|
|
455
|
+
function withPath(op, path) {
|
|
456
|
+
if (void 0 !== path && 0 !== path.length) for (let i = 0; i < path.length; i++) op(22, path[i]);
|
|
457
|
+
}
|
|
458
|
+
function expr(op, expression) {
|
|
459
|
+
Array.isArray(expression) ? EXPRESSIONS.compile(op, expression) : (PushPrimitive(op, expression), op(31));
|
|
439
460
|
}
|
|
440
461
|
|
|
441
462
|
/**
|
|
@@ -443,7 +464,7 @@ function namedBlocks(blocks) {
|
|
|
443
464
|
* @param value A JavaScript primitive (undefined, null, boolean, number or string)
|
|
444
465
|
*/
|
|
445
466
|
function PushPrimitiveReference(op, value) {
|
|
446
|
-
PushPrimitive(op, value), op(
|
|
467
|
+
PushPrimitive(op, value), op(31);
|
|
447
468
|
}
|
|
448
469
|
|
|
449
470
|
/**
|
|
@@ -454,10 +475,12 @@ function PushPrimitiveReference(op, value) {
|
|
|
454
475
|
function PushPrimitive(op, primitive) {
|
|
455
476
|
let p = primitive;
|
|
456
477
|
var value;
|
|
457
|
-
"number" == typeof p && (p =
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
478
|
+
"number" == typeof p && (p = (value = p) % 1 == 0 && value <= 536870911 && value >= -536870912 ? encodeImmediate(p) : function (value) {
|
|
479
|
+
return {
|
|
480
|
+
type: 6,
|
|
481
|
+
value: value
|
|
482
|
+
};
|
|
483
|
+
}(p)), op(30, p);
|
|
461
484
|
}
|
|
462
485
|
|
|
463
486
|
/**
|
|
@@ -469,7 +492,7 @@ function PushPrimitive(op, primitive) {
|
|
|
469
492
|
* @param named An optional list of named arguments (name + expression) to compile
|
|
470
493
|
*/
|
|
471
494
|
function Call(op, handle, positional, named) {
|
|
472
|
-
op(
|
|
495
|
+
op(0), SimpleArgs(op, positional, named, !1), op(16, handle), op(1), op(36, $v0);
|
|
473
496
|
}
|
|
474
497
|
|
|
475
498
|
/**
|
|
@@ -480,7 +503,7 @@ function Call(op, handle, positional, named) {
|
|
|
480
503
|
* @param named An optional list of named arguments (name + expression) to compile
|
|
481
504
|
*/
|
|
482
505
|
function CallDynamic(op, positional, named, append) {
|
|
483
|
-
op(
|
|
506
|
+
op(0), SimpleArgs(op, positional, named, !1), op(33, $fp, 1), op(107), append ? (op(36, $v0), append(), op(1), op(34, 1)) : (op(1), op(34, 1), op(36, $v0));
|
|
484
507
|
}
|
|
485
508
|
|
|
486
509
|
/**
|
|
@@ -492,79 +515,10 @@ function CallDynamic(op, positional, named, append) {
|
|
|
492
515
|
* @param block a function that returns a list of statements to evaluate
|
|
493
516
|
*/
|
|
494
517
|
function Curry(op, type, definition, positional, named) {
|
|
495
|
-
op(
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
funcs = [];
|
|
500
|
-
add(name, func) {
|
|
501
|
-
this.names[name] = this.funcs.push(func) - 1;
|
|
502
|
-
}
|
|
503
|
-
compile(op, sexp) {
|
|
504
|
-
let name = sexp[0],
|
|
505
|
-
index = unwrap(this.names[name]),
|
|
506
|
-
func = this.funcs[index];
|
|
507
|
-
debugAssert(!!func, `expected an implementation for ${sexp[0]}`), func(op, sexp);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
const EXPRESSIONS = new Compilers();
|
|
511
|
-
function withPath(op, path) {
|
|
512
|
-
if (void 0 !== path && 0 !== path.length) for (let i = 0; i < path.length; i++) op(Op.GetProperty, path[i]);
|
|
513
|
-
}
|
|
514
|
-
function expr(op, expression) {
|
|
515
|
-
Array.isArray(expression) ? EXPRESSIONS.compile(op, expression) : (PushPrimitive(op, expression), op(Op.PrimitiveReference));
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Compile arguments, pushing an Arguments object onto the stack.
|
|
520
|
-
*
|
|
521
|
-
* @param args.params
|
|
522
|
-
* @param args.hash
|
|
523
|
-
* @param args.blocks
|
|
524
|
-
* @param args.atNames
|
|
525
|
-
*/
|
|
526
|
-
function SimpleArgs(op, positional, named, atNames) {
|
|
527
|
-
if (null === positional && null === named) return void op(Op.PushEmptyArgs);
|
|
528
|
-
let flags = CompilePositional(op, positional) << 4;
|
|
529
|
-
atNames && (flags |= 8);
|
|
530
|
-
let names = EMPTY_STRING_ARRAY;
|
|
531
|
-
if (named) {
|
|
532
|
-
names = named[0];
|
|
533
|
-
let val = named[1];
|
|
534
|
-
for (let i = 0; i < val.length; i++) expr(op, val[i]);
|
|
535
|
-
}
|
|
536
|
-
op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* Compile an optional list of positional arguments, which pushes each argument
|
|
541
|
-
* onto the stack and returns the number of parameters compiled
|
|
542
|
-
*
|
|
543
|
-
* @param positional an optional list of positional arguments
|
|
544
|
-
*/
|
|
545
|
-
function CompilePositional(op, positional) {
|
|
546
|
-
if (null === positional) return 0;
|
|
547
|
-
for (let i = 0; i < positional.length; i++) expr(op, positional[i]);
|
|
548
|
-
return positional.length;
|
|
549
|
-
}
|
|
550
|
-
function meta(layout) {
|
|
551
|
-
let [, symbols,, upvars] = layout.block;
|
|
552
|
-
return {
|
|
553
|
-
evalSymbols: evalSymbols(layout),
|
|
554
|
-
upvars: upvars,
|
|
555
|
-
scopeValues: layout.scope?.() ?? null,
|
|
556
|
-
isStrictMode: layout.isStrictMode,
|
|
557
|
-
moduleName: layout.moduleName,
|
|
558
|
-
owner: layout.owner,
|
|
559
|
-
size: symbols.length
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
function evalSymbols(layout) {
|
|
563
|
-
let {
|
|
564
|
-
block: block
|
|
565
|
-
} = layout,
|
|
566
|
-
[, symbols, hasEval] = block;
|
|
567
|
-
return hasEval ? symbols : null;
|
|
518
|
+
op(0), SimpleArgs(op, positional, named, !1), op(86), expr(op, definition), op(77, type, {
|
|
519
|
+
type: 2,
|
|
520
|
+
value: void 0
|
|
521
|
+
}), op(1), op(36, $v0);
|
|
568
522
|
}
|
|
569
523
|
|
|
570
524
|
/**
|
|
@@ -574,7 +528,7 @@ function evalSymbols(layout) {
|
|
|
574
528
|
* @param params optional block parameters to yield to the block
|
|
575
529
|
*/
|
|
576
530
|
function YieldBlock(op, to, positional) {
|
|
577
|
-
SimpleArgs(op, positional, null, !0), op(
|
|
531
|
+
SimpleArgs(op, positional, null, !0), op(23, to), op(24), op(61), op(64), op(40), op(1);
|
|
578
532
|
}
|
|
579
533
|
|
|
580
534
|
/**
|
|
@@ -585,10 +539,10 @@ function YieldBlock(op, to, positional) {
|
|
|
585
539
|
*/
|
|
586
540
|
function PushYieldableBlock(op, block) {
|
|
587
541
|
!function (op, parameters) {
|
|
588
|
-
null !== parameters ? op(
|
|
542
|
+
null !== parameters ? op(63, symbolTableOperand({
|
|
589
543
|
parameters: parameters
|
|
590
544
|
})) : PushPrimitive(op, null);
|
|
591
|
-
}(op, block && block[1]), op(
|
|
545
|
+
}(op, block && block[1]), op(62), PushCompilable(op, block);
|
|
592
546
|
}
|
|
593
547
|
|
|
594
548
|
/**
|
|
@@ -597,7 +551,7 @@ function PushYieldableBlock(op, block) {
|
|
|
597
551
|
* @param block a Compilable block
|
|
598
552
|
*/
|
|
599
553
|
function InvokeStaticBlock(op, block) {
|
|
600
|
-
op(
|
|
554
|
+
op(0), PushCompilable(op, block), op(61), op(2), op(1);
|
|
601
555
|
}
|
|
602
556
|
|
|
603
557
|
/**
|
|
@@ -612,19 +566,142 @@ function InvokeStaticBlockWithStack(op, block, callerCount) {
|
|
|
612
566
|
calleeCount = parameters.length,
|
|
613
567
|
count = Math.min(callerCount, calleeCount);
|
|
614
568
|
if (0 !== count) {
|
|
615
|
-
if (op(
|
|
616
|
-
op(
|
|
617
|
-
for (let i = 0; i < count; i++) op(
|
|
569
|
+
if (op(0), count) {
|
|
570
|
+
op(39);
|
|
571
|
+
for (let i = 0; i < count; i++) op(33, $fp, callerCount - i), op(19, parameters[i]);
|
|
618
572
|
}
|
|
619
|
-
PushCompilable(op, block), op(
|
|
573
|
+
PushCompilable(op, block), op(61), op(2), count && op(40), op(1);
|
|
620
574
|
} else InvokeStaticBlock(op, block);
|
|
621
575
|
}
|
|
622
576
|
function PushCompilable(op, _block) {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
577
|
+
null === _block ? PushPrimitive(op, null) : op(28, {
|
|
578
|
+
type: 4,
|
|
579
|
+
value: _block
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Compile arguments, pushing an Arguments object onto the stack.
|
|
585
|
+
*
|
|
586
|
+
* @param args.params
|
|
587
|
+
* @param args.hash
|
|
588
|
+
* @param args.blocks
|
|
589
|
+
* @param args.atNames
|
|
590
|
+
*/
|
|
591
|
+
function SimpleArgs(op, positional, named, atNames) {
|
|
592
|
+
if (null === positional && null === named) return void op(83);
|
|
593
|
+
let flags = CompilePositional(op, positional) << 4;
|
|
594
|
+
atNames && (flags |= 8);
|
|
595
|
+
let names = EMPTY_STRING_ARRAY;
|
|
596
|
+
if (named) {
|
|
597
|
+
names = named[0];
|
|
598
|
+
let val = named[1];
|
|
599
|
+
for (let i = 0; i < val.length; i++) expr(op, val[i]);
|
|
600
|
+
}
|
|
601
|
+
op(82, names, EMPTY_STRING_ARRAY, flags);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Compile an optional list of positional arguments, which pushes each argument
|
|
606
|
+
* onto the stack and returns the number of parameters compiled
|
|
607
|
+
*
|
|
608
|
+
* @param positional an optional list of positional arguments
|
|
609
|
+
*/
|
|
610
|
+
function CompilePositional(op, positional) {
|
|
611
|
+
if (null === positional) return 0;
|
|
612
|
+
for (let i = 0; i < positional.length; i++) expr(op, positional[i]);
|
|
613
|
+
return positional.length;
|
|
614
|
+
}
|
|
615
|
+
function meta(layout) {
|
|
616
|
+
let [, locals, upvars, lexicalSymbols] = layout.block;
|
|
617
|
+
return {
|
|
618
|
+
symbols: {
|
|
619
|
+
locals: locals,
|
|
620
|
+
upvars: upvars,
|
|
621
|
+
lexical: lexicalSymbols
|
|
622
|
+
},
|
|
623
|
+
scopeValues: layout.scope?.() ?? null,
|
|
624
|
+
isStrictMode: layout.isStrictMode,
|
|
625
|
+
moduleName: layout.moduleName,
|
|
626
|
+
owner: layout.owner,
|
|
627
|
+
size: locals.length
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
EXPRESSIONS.add(opcodes.Concat, (op, [, parts]) => {
|
|
631
|
+
for (let part of parts) expr(op, part);
|
|
632
|
+
op(27, parts.length);
|
|
633
|
+
}), EXPRESSIONS.add(opcodes.Call, (op, [, expression, positional, named]) => {
|
|
634
|
+
isGetFreeHelper(expression) ? op(1005, expression, handle => {
|
|
635
|
+
Call(op, handle, positional, named);
|
|
636
|
+
}) : (expr(op, expression), CallDynamic(op, positional, named));
|
|
637
|
+
}), EXPRESSIONS.add(opcodes.Curry, (op, [, expr, type, positional, named]) => {
|
|
638
|
+
Curry(op, type, expr, positional, named);
|
|
639
|
+
}), EXPRESSIONS.add(opcodes.GetSymbol, (op, [, sym, path]) => {
|
|
640
|
+
op(21, sym), withPath(op, path);
|
|
641
|
+
}), EXPRESSIONS.add(opcodes.GetLexicalSymbol, (op, [, sym, path]) => {
|
|
642
|
+
op(1011, sym, handle => {
|
|
643
|
+
op(29, handle), withPath(op, path);
|
|
644
|
+
});
|
|
645
|
+
}), EXPRESSIONS.add(opcodes.GetStrictKeyword, (op, expr) => {
|
|
646
|
+
op(1010, expr[1], () => {
|
|
647
|
+
op(1005, expr, handle => {
|
|
648
|
+
Call(op, handle, null, null);
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
}), EXPRESSIONS.add(opcodes.GetFreeAsHelperHead, (op, expr) => {
|
|
652
|
+
op(1010, expr[1], () => {
|
|
653
|
+
op(1005, expr, handle => {
|
|
654
|
+
Call(op, handle, null, null);
|
|
655
|
+
});
|
|
656
|
+
});
|
|
657
|
+
}), EXPRESSIONS.add(opcodes.Undefined, op => PushPrimitiveReference(op, void 0)), EXPRESSIONS.add(opcodes.HasBlock, (op, [, block]) => {
|
|
658
|
+
expr(op, block), op(25);
|
|
659
|
+
}), EXPRESSIONS.add(opcodes.HasBlockParams, (op, [, block]) => {
|
|
660
|
+
expr(op, block), op(24), op(61), op(26);
|
|
661
|
+
}), EXPRESSIONS.add(opcodes.IfInline, (op, [, condition, truthy, falsy]) => {
|
|
662
|
+
// Push in reverse order
|
|
663
|
+
expr(op, falsy), expr(op, truthy), expr(op, condition), op(109);
|
|
664
|
+
}), EXPRESSIONS.add(opcodes.Not, (op, [, value]) => {
|
|
665
|
+
expr(op, value), op(110);
|
|
666
|
+
}), EXPRESSIONS.add(opcodes.GetDynamicVar, (op, [, expression]) => {
|
|
667
|
+
expr(op, expression), op(111);
|
|
668
|
+
}), EXPRESSIONS.add(opcodes.Log, (op, [, positional]) => {
|
|
669
|
+
op(0), SimpleArgs(op, positional, null, !1), op(112), op(1), op(36, $v0);
|
|
670
|
+
});
|
|
671
|
+
class NamedBlocksImpl {
|
|
672
|
+
constructor(blocks) {
|
|
673
|
+
this.blocks = blocks, this.names = blocks ? Object.keys(blocks) : [];
|
|
674
|
+
}
|
|
675
|
+
get(name) {
|
|
676
|
+
return this.blocks && this.blocks[name] || null;
|
|
677
|
+
}
|
|
678
|
+
has(name) {
|
|
679
|
+
let {
|
|
680
|
+
blocks: blocks
|
|
681
|
+
} = this;
|
|
682
|
+
return null !== blocks && name in blocks;
|
|
683
|
+
}
|
|
684
|
+
with(name, block) {
|
|
685
|
+
let {
|
|
686
|
+
blocks: blocks
|
|
687
|
+
} = this;
|
|
688
|
+
return new NamedBlocksImpl(blocks ? assign({}, blocks, {
|
|
689
|
+
[name]: block
|
|
690
|
+
}) : {
|
|
691
|
+
[name]: block
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
get hasAny() {
|
|
695
|
+
return null !== this.blocks;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const EMPTY_BLOCKS = new NamedBlocksImpl(null);
|
|
699
|
+
function namedBlocks(blocks) {
|
|
700
|
+
if (null === blocks) return EMPTY_BLOCKS;
|
|
701
|
+
let out = dict(),
|
|
702
|
+
[keys, values] = blocks;
|
|
703
|
+
for (const [i, key] of enumerate(keys)) out[key] = values[i];
|
|
704
|
+
return new NamedBlocksImpl(out);
|
|
628
705
|
}
|
|
629
706
|
function SwitchCases(op, bootstrap, matcher) {
|
|
630
707
|
// Setup the switch DSL
|
|
@@ -639,20 +716,20 @@ function SwitchCases(op, bootstrap, matcher) {
|
|
|
639
716
|
});
|
|
640
717
|
}),
|
|
641
718
|
// Emit the opcodes for the switch
|
|
642
|
-
op(
|
|
719
|
+
op(69, 1), bootstrap(), op(1001);
|
|
643
720
|
// First, emit the jump opcodes. We don't need a jump for the last
|
|
644
721
|
// opcode, since it bleeds directly into its clause.
|
|
645
|
-
for (let clause of clauses.slice(0, -1)) op(
|
|
722
|
+
for (let clause of clauses.slice(0, -1)) op(67, labelOperand(clause.label), clause.match);
|
|
646
723
|
// Enumerate the clauses in reverse order. Earlier matches will
|
|
647
724
|
// require fewer checks.
|
|
648
725
|
for (let i = clauses.length - 1; i >= 0; i--) {
|
|
649
|
-
let clause =
|
|
650
|
-
op(
|
|
726
|
+
let clause = clauses[i];
|
|
727
|
+
op(1e3, clause.label), op(34, 1), clause.callback(),
|
|
651
728
|
// The first match is special: it is placed directly before the END
|
|
652
729
|
// label, so no additional jump is needed at the end of it.
|
|
653
|
-
0 !== i && op(
|
|
730
|
+
0 !== i && op(4, labelOperand("END"));
|
|
654
731
|
}
|
|
655
|
-
op(
|
|
732
|
+
op(1e3, "END"), op(1002), op(70);
|
|
656
733
|
}
|
|
657
734
|
|
|
658
735
|
/**
|
|
@@ -719,25 +796,20 @@ function SwitchCases(op, bootstrap, matcher) {
|
|
|
719
796
|
function Replayable(op, args, body) {
|
|
720
797
|
// Start a new label frame, to give END and RETURN
|
|
721
798
|
// a unique meaning.
|
|
722
|
-
op(
|
|
799
|
+
op(1001), op(0),
|
|
723
800
|
// If the body invokes a block, its return will return to
|
|
724
801
|
// END. Otherwise, the return in RETURN will return to END.
|
|
725
|
-
op(
|
|
726
|
-
// Push the arguments onto the stack. The args() function
|
|
727
|
-
// tells us how many stack elements to retain for re-execution
|
|
728
|
-
// when updating.
|
|
729
|
-
let count = args();
|
|
802
|
+
op(6, labelOperand("ENDINITIAL")),
|
|
730
803
|
// Start a new updating closure, remembering `count` elements
|
|
731
804
|
// from the stack. Everything after this point, and before END,
|
|
732
805
|
// will execute both initially and to update the block.
|
|
733
|
-
|
|
734
806
|
// The enter and exit opcodes also track the area of the DOM
|
|
735
807
|
// associated with this block. If an assertion inside the block
|
|
736
808
|
// fails (for example, the test value changes from true to false
|
|
737
809
|
// in an #if), the DOM is cleared and the program is re-executed,
|
|
738
810
|
// restoring `count` elements to the stack and executing the
|
|
739
811
|
// instructions between the enter and exit.
|
|
740
|
-
op(
|
|
812
|
+
op(69, args()),
|
|
741
813
|
// Evaluate the body of the block. The body of the block may
|
|
742
814
|
// return, which will jump execution to END during initial
|
|
743
815
|
// execution, and exit the updating routine.
|
|
@@ -745,16 +817,16 @@ function Replayable(op, args, body) {
|
|
|
745
817
|
// All execution paths in the body should run the FINALLY once
|
|
746
818
|
// they are done. It is executed both during initial execution
|
|
747
819
|
// and during updating execution.
|
|
748
|
-
op(
|
|
820
|
+
op(1e3, "FINALLY"),
|
|
749
821
|
// Finalize the DOM.
|
|
750
|
-
op(
|
|
822
|
+
op(70),
|
|
751
823
|
// In initial execution, this is a noop: it returns to the
|
|
752
824
|
// immediately following opcode. In updating execution, this
|
|
753
825
|
// exits the updating routine.
|
|
754
|
-
op(
|
|
826
|
+
op(5),
|
|
755
827
|
// Cleanup code for the block. Runs on initial execution
|
|
756
828
|
// but not on updating.
|
|
757
|
-
op(
|
|
829
|
+
op(1e3, "ENDINITIAL"), op(1), op(1002);
|
|
758
830
|
}
|
|
759
831
|
|
|
760
832
|
/**
|
|
@@ -775,13 +847,13 @@ function Replayable(op, args, body) {
|
|
|
775
847
|
function ReplayableIf(op, args, ifTrue, ifFalse) {
|
|
776
848
|
return Replayable(op, args, () => {
|
|
777
849
|
// If the conditional is false, jump to the ELSE label.
|
|
778
|
-
op(
|
|
850
|
+
op(66, labelOperand("ELSE")),
|
|
779
851
|
// Otherwise, execute the code associated with the true branch.
|
|
780
852
|
ifTrue(),
|
|
781
853
|
// We're done, so return. In the initial execution, this runs
|
|
782
854
|
// the cleanup code. In the updating VM, it exits the updating
|
|
783
855
|
// routine.
|
|
784
|
-
op(
|
|
856
|
+
op(4, labelOperand("FINALLY")), op(1e3, "ELSE"),
|
|
785
857
|
// If the conditional is false, and code associatied ith the
|
|
786
858
|
// false branch was provided, execute it. If there was no code
|
|
787
859
|
// associated with the false branch, jumping to the else statement
|
|
@@ -789,10 +861,6 @@ function ReplayableIf(op, args, ifTrue, ifFalse) {
|
|
|
789
861
|
void 0 !== ifFalse && ifFalse();
|
|
790
862
|
});
|
|
791
863
|
}
|
|
792
|
-
|
|
793
|
-
// {{component}}
|
|
794
|
-
// <Component>
|
|
795
|
-
// chokepoint
|
|
796
864
|
function InvokeComponent(op, component, _elementBlock, positional, named, _blocks) {
|
|
797
865
|
let {
|
|
798
866
|
compilable: compilable,
|
|
@@ -800,8 +868,8 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
800
868
|
handle: handle
|
|
801
869
|
} = component,
|
|
802
870
|
elementBlock = _elementBlock ? [_elementBlock, []] : null,
|
|
803
|
-
blocks =
|
|
804
|
-
compilable ? (op(
|
|
871
|
+
blocks = namedBlocks(_blocks);
|
|
872
|
+
compilable ? (op(78, handle), function (op, {
|
|
805
873
|
capabilities: capabilities,
|
|
806
874
|
layout: layout,
|
|
807
875
|
elementBlock: elementBlock,
|
|
@@ -812,7 +880,7 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
812
880
|
let {
|
|
813
881
|
symbolTable: symbolTable
|
|
814
882
|
} = layout;
|
|
815
|
-
if (
|
|
883
|
+
if (hasCapability(capabilities, InternalComponentCapabilities.prepareArgs)) return void InvokeNonStaticComponent(op, {
|
|
816
884
|
capabilities: capabilities,
|
|
817
885
|
elementBlock: elementBlock,
|
|
818
886
|
positional: positional,
|
|
@@ -821,7 +889,7 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
821
889
|
blocks: blocks,
|
|
822
890
|
layout: layout
|
|
823
891
|
});
|
|
824
|
-
op(
|
|
892
|
+
op(36, $s0), op(33, $sp, 1), op(35, $s0), op(0);
|
|
825
893
|
// Setup arguments
|
|
826
894
|
let {
|
|
827
895
|
symbols: symbols
|
|
@@ -861,14 +929,14 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
861
929
|
names = named[0];
|
|
862
930
|
let val = named[1];
|
|
863
931
|
for (let i = 0; i < val.length; i++) {
|
|
864
|
-
let symbol = symbols.indexOf(
|
|
932
|
+
let symbol = symbols.indexOf(names[i]);
|
|
865
933
|
expr(op, val[i]), argSymbols.push(symbol);
|
|
866
934
|
}
|
|
867
935
|
}
|
|
868
936
|
// Finally, push the VM arguments themselves. These args won't need access
|
|
869
937
|
// to blocks (they aren't accessible from userland anyways), so we push an
|
|
870
938
|
// empty array instead of the actual block names.
|
|
871
|
-
op(
|
|
939
|
+
op(82, names, EMPTY_STRING_ARRAY, flags),
|
|
872
940
|
// And push an extra pop operation to remove the args before we begin setting
|
|
873
941
|
// variables on the local context
|
|
874
942
|
argSymbols.push(-1);
|
|
@@ -879,17 +947,19 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
879
947
|
let names = named[0],
|
|
880
948
|
val = named[1];
|
|
881
949
|
for (let i = 0; i < val.length; i++) {
|
|
882
|
-
let name =
|
|
950
|
+
let name = names[i],
|
|
883
951
|
symbol = symbols.indexOf(name);
|
|
884
952
|
-1 !== symbol && (expr(op, val[i]), argSymbols.push(symbol), argNames.push(name));
|
|
885
953
|
}
|
|
886
954
|
}
|
|
887
|
-
op(
|
|
955
|
+
op(97, $s0), hasCapability(capabilities, InternalComponentCapabilities.dynamicScope) && op(59), hasCapability(capabilities, InternalComponentCapabilities.createInstance) &&
|
|
956
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
957
|
+
op(87, 0 | blocks.has("default")), op(88, $s0), hasCapability(capabilities, InternalComponentCapabilities.createArgs) ? op(90, $s0) : op(90, $s0, argNames),
|
|
888
958
|
// Setup the new root scope for the component
|
|
889
|
-
op(
|
|
959
|
+
op(37, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0),
|
|
890
960
|
// Pop the self reference off the stack and set it to the symbol for `this`
|
|
891
961
|
// in the new scope. This is why all subsequent symbols are increased by one.
|
|
892
|
-
op(
|
|
962
|
+
op(19, 0);
|
|
893
963
|
// Going in reverse, now we pop the args/blocks off the stack, starting with
|
|
894
964
|
// arguments, and assign them to their symbols in the new scope.
|
|
895
965
|
for (const symbol of reverse(argSymbols))
|
|
@@ -898,12 +968,12 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
898
968
|
-1 === symbol ?
|
|
899
969
|
// The expression was not bound to a local symbol, it was only pushed to be
|
|
900
970
|
// used with VM args in the javascript side
|
|
901
|
-
op(
|
|
971
|
+
op(34, 1) : op(19, symbol + 1);
|
|
902
972
|
// if any positional params exist, pop them off the stack as well
|
|
903
|
-
null !== positional && op(
|
|
973
|
+
null !== positional && op(34, positional.length);
|
|
904
974
|
// Finish up by popping off and assigning blocks
|
|
905
|
-
for (const symbol of reverse(blockSymbols)) op(
|
|
906
|
-
op(
|
|
975
|
+
for (const symbol of reverse(blockSymbols)) op(20, symbol + 1);
|
|
976
|
+
op(28, layoutOperand(layout)), op(61), op(2), op(100, $s0), op(1), op(40), hasCapability(capabilities, InternalComponentCapabilities.dynamicScope) && op(60), op(98), op(35, $s0);
|
|
907
977
|
}(op, {
|
|
908
978
|
capabilities: capabilities,
|
|
909
979
|
layout: compilable,
|
|
@@ -911,7 +981,7 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
911
981
|
positional: positional,
|
|
912
982
|
named: named,
|
|
913
983
|
blocks: blocks
|
|
914
|
-
})) : (op(
|
|
984
|
+
})) : (op(78, handle), InvokeNonStaticComponent(op, {
|
|
915
985
|
capabilities: capabilities,
|
|
916
986
|
elementBlock: elementBlock,
|
|
917
987
|
positional: positional,
|
|
@@ -922,16 +992,19 @@ function InvokeComponent(op, component, _elementBlock, positional, named, _block
|
|
|
922
992
|
}
|
|
923
993
|
function InvokeDynamicComponent(op, definition, _elementBlock, positional, named, _blocks, atNames, curried) {
|
|
924
994
|
let elementBlock = _elementBlock ? [_elementBlock, []] : null,
|
|
925
|
-
blocks =
|
|
926
|
-
Replayable(op, () => (expr(op, definition), op(
|
|
927
|
-
op(
|
|
995
|
+
blocks = namedBlocks(_blocks);
|
|
996
|
+
Replayable(op, () => (expr(op, definition), op(33, $sp, 0), 2), () => {
|
|
997
|
+
op(66, labelOperand("ELSE")), curried ? op(81) : op(80, {
|
|
998
|
+
type: 2,
|
|
999
|
+
value: void 0
|
|
1000
|
+
}), op(79), InvokeNonStaticComponent(op, {
|
|
928
1001
|
capabilities: !0,
|
|
929
1002
|
elementBlock: elementBlock,
|
|
930
1003
|
positional: positional,
|
|
931
1004
|
named: named,
|
|
932
1005
|
atNames: atNames,
|
|
933
1006
|
blocks: blocks
|
|
934
|
-
}), op(
|
|
1007
|
+
}), op(1e3, "ELSE");
|
|
935
1008
|
});
|
|
936
1009
|
}
|
|
937
1010
|
function InvokeNonStaticComponent(op, {
|
|
@@ -946,166 +1019,31 @@ function InvokeNonStaticComponent(op, {
|
|
|
946
1019
|
let bindableBlocks = !!namedBlocks,
|
|
947
1020
|
bindableAtNames = !0 === capabilities || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs) || !(!named || 0 === named[0].length),
|
|
948
1021
|
blocks = namedBlocks.with("attrs", elementBlock);
|
|
949
|
-
op(
|
|
1022
|
+
op(36, $s0), op(33, $sp, 1), op(35, $s0), op(0), function (op, positional, named, blocks, atNames) {
|
|
950
1023
|
let blockNames = blocks.names;
|
|
951
1024
|
for (const name of blockNames) PushYieldableBlock(op, blocks.get(name));
|
|
952
1025
|
let flags = CompilePositional(op, positional) << 4;
|
|
953
|
-
atNames && (flags |= 8), blocks && (flags |= 7);
|
|
1026
|
+
atNames && (flags |= 8), blocks.hasAny && (flags |= 7);
|
|
954
1027
|
let names = EMPTY_ARRAY;
|
|
955
1028
|
if (named) {
|
|
956
1029
|
names = named[0];
|
|
957
1030
|
let val = named[1];
|
|
958
1031
|
for (let i = 0; i < val.length; i++) expr(op, val[i]);
|
|
959
1032
|
}
|
|
960
|
-
op(
|
|
961
|
-
}(op, positional, named, blocks, atNames), op(
|
|
962
|
-
layout ? (op(
|
|
963
|
-
}), op(
|
|
1033
|
+
op(82, names, blockNames, flags);
|
|
1034
|
+
}(op, positional, named, blocks, atNames), op(85, $s0), invokePreparedComponent(op, blocks.has("default"), bindableBlocks, bindableAtNames, () => {
|
|
1035
|
+
layout ? (op(63, symbolTableOperand(layout.symbolTable)), op(28, layoutOperand(layout)), op(61)) : op(92, $s0), op(95, $s0);
|
|
1036
|
+
}), op(35, $s0);
|
|
964
1037
|
}
|
|
965
1038
|
function invokePreparedComponent(op, hasBlock, bindableBlocks, bindableAtNames, populateLayout = null) {
|
|
966
|
-
op(
|
|
1039
|
+
op(97, $s0), op(59),
|
|
1040
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1041
|
+
op(87, 0 | hasBlock),
|
|
967
1042
|
// this has to run after createComponent to allow
|
|
968
1043
|
// for late-bound layouts, but a caller is free
|
|
969
1044
|
// to populate the layout earlier if it wants to
|
|
970
1045
|
// and do nothing here.
|
|
971
|
-
populateLayout && populateLayout(), op(
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
/**
|
|
975
|
-
* Append content to the DOM. This standard function triages content and does the
|
|
976
|
-
* right thing based upon whether it's a string, safe string, component, fragment
|
|
977
|
-
* or node.
|
|
978
|
-
*
|
|
979
|
-
* @param trusting whether to interpolate a string as raw HTML (corresponds to
|
|
980
|
-
* triple curlies)
|
|
981
|
-
*/
|
|
982
|
-
function StdAppend(op, trusting, nonDynamicAppend) {
|
|
983
|
-
SwitchCases(op, () => op(Op.ContentType), when => {
|
|
984
|
-
when(ContentType.String, () => {
|
|
985
|
-
trusting ? (op(Op.AssertSame), op(Op.AppendHTML)) : op(Op.AppendText);
|
|
986
|
-
}), "number" == typeof nonDynamicAppend ? (when(ContentType.Component, () => {
|
|
987
|
-
op(Op.ResolveCurriedComponent), op(Op.PushDynamicComponentInstance), function (op) {
|
|
988
|
-
op(Op.Fetch, $s0), op(Op.Dup, $sp, 1), op(Op.Load, $s0), op(MachineOp.PushFrame), op(Op.PushEmptyArgs), op(Op.PrepareArgs, $s0), invokePreparedComponent(op, !1, !1, !0, () => {
|
|
989
|
-
op(Op.GetComponentLayout, $s0), op(Op.PopulateLayout, $s0);
|
|
990
|
-
}), op(Op.Load, $s0);
|
|
991
|
-
}(op);
|
|
992
|
-
}), when(ContentType.Helper, () => {
|
|
993
|
-
CallDynamic(op, null, null, () => {
|
|
994
|
-
op(MachineOp.InvokeStatic, nonDynamicAppend);
|
|
995
|
-
});
|
|
996
|
-
})) : (
|
|
997
|
-
// when non-dynamic, we can no longer call the value (potentially because we've already called it)
|
|
998
|
-
// this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM.
|
|
999
|
-
when(ContentType.Component, () => {
|
|
1000
|
-
op(Op.AppendText);
|
|
1001
|
-
}), when(ContentType.Helper, () => {
|
|
1002
|
-
op(Op.AppendText);
|
|
1003
|
-
})), when(ContentType.SafeString, () => {
|
|
1004
|
-
op(Op.AssertSame), op(Op.AppendSafeHTML);
|
|
1005
|
-
}), when(ContentType.Fragment, () => {
|
|
1006
|
-
op(Op.AssertSame), op(Op.AppendDocumentFragment);
|
|
1007
|
-
}), when(ContentType.Node, () => {
|
|
1008
|
-
op(Op.AssertSame), op(Op.AppendNode);
|
|
1009
|
-
});
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
function compileStd(context) {
|
|
1013
|
-
let mainHandle = build(context, op => function (op) {
|
|
1014
|
-
op(Op.Main, $s0), invokePreparedComponent(op, !1, !1, !0);
|
|
1015
|
-
}(op)),
|
|
1016
|
-
trustingGuardedNonDynamicAppend = build(context, op => StdAppend(op, !0, null)),
|
|
1017
|
-
cautiousGuardedNonDynamicAppend = build(context, op => StdAppend(op, !1, null)),
|
|
1018
|
-
trustingGuardedDynamicAppend = build(context, op => StdAppend(op, !0, trustingGuardedNonDynamicAppend)),
|
|
1019
|
-
cautiousGuardedDynamicAppend = build(context, op => StdAppend(op, !1, cautiousGuardedNonDynamicAppend));
|
|
1020
|
-
return new StdLib(mainHandle, trustingGuardedDynamicAppend, cautiousGuardedDynamicAppend, trustingGuardedNonDynamicAppend, cautiousGuardedNonDynamicAppend);
|
|
1021
|
-
}
|
|
1022
|
-
EXPRESSIONS.add(opcodes.Concat, (op, [, parts]) => {
|
|
1023
|
-
for (let part of parts) expr(op, part);
|
|
1024
|
-
op(Op.Concat, parts.length);
|
|
1025
|
-
}), EXPRESSIONS.add(opcodes.Call, (op, [, expression, positional, named]) => {
|
|
1026
|
-
isGetFreeHelper(expression) ? op(HighLevelResolutionOpcodes.Helper, expression, handle => {
|
|
1027
|
-
Call(op, handle, positional, named);
|
|
1028
|
-
}) : (expr(op, expression), CallDynamic(op, positional, named));
|
|
1029
|
-
}), EXPRESSIONS.add(opcodes.Curry, (op, [, expr, type, positional, named]) => {
|
|
1030
|
-
Curry(op, type, expr, positional, named);
|
|
1031
|
-
}), EXPRESSIONS.add(opcodes.GetSymbol, (op, [, sym, path]) => {
|
|
1032
|
-
op(Op.GetVariable, sym), withPath(op, path);
|
|
1033
|
-
}), EXPRESSIONS.add(opcodes.GetLexicalSymbol, (op, [, sym, path]) => {
|
|
1034
|
-
op(HighLevelResolutionOpcodes.TemplateLocal, sym, handle => {
|
|
1035
|
-
op(Op.ConstantReference, handle), withPath(op, path);
|
|
1036
|
-
});
|
|
1037
|
-
}), EXPRESSIONS.add(opcodes.GetStrictKeyword, (op, expr) => {
|
|
1038
|
-
op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
|
|
1039
|
-
op(HighLevelResolutionOpcodes.Helper, expr, handle => {
|
|
1040
|
-
Call(op, handle, null, null);
|
|
1041
|
-
});
|
|
1042
|
-
});
|
|
1043
|
-
}), EXPRESSIONS.add(opcodes.GetFreeAsHelperHead, (op, expr) => {
|
|
1044
|
-
op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
|
|
1045
|
-
op(HighLevelResolutionOpcodes.Helper, expr, handle => {
|
|
1046
|
-
Call(op, handle, null, null);
|
|
1047
|
-
});
|
|
1048
|
-
});
|
|
1049
|
-
}), EXPRESSIONS.add(opcodes.Undefined, op => PushPrimitiveReference(op, void 0)), EXPRESSIONS.add(opcodes.HasBlock, (op, [, block]) => {
|
|
1050
|
-
expr(op, block), op(Op.HasBlock);
|
|
1051
|
-
}), EXPRESSIONS.add(opcodes.HasBlockParams, (op, [, block]) => {
|
|
1052
|
-
expr(op, block), op(Op.SpreadBlock), op(Op.CompileBlock), op(Op.HasBlockParams);
|
|
1053
|
-
}), EXPRESSIONS.add(opcodes.IfInline, (op, [, condition, truthy, falsy]) => {
|
|
1054
|
-
// Push in reverse order
|
|
1055
|
-
expr(op, falsy), expr(op, truthy), expr(op, condition), op(Op.IfInline);
|
|
1056
|
-
}), EXPRESSIONS.add(opcodes.Not, (op, [, value]) => {
|
|
1057
|
-
expr(op, value), op(Op.Not);
|
|
1058
|
-
}), EXPRESSIONS.add(opcodes.GetDynamicVar, (op, [, expression]) => {
|
|
1059
|
-
expr(op, expression), op(Op.GetDynamicVar);
|
|
1060
|
-
}), EXPRESSIONS.add(opcodes.Log, (op, [, positional]) => {
|
|
1061
|
-
op(MachineOp.PushFrame), SimpleArgs(op, positional, null, !1), op(Op.Log), op(MachineOp.PopFrame), op(Op.Fetch, $v0);
|
|
1062
|
-
});
|
|
1063
|
-
const STDLIB_META = {
|
|
1064
|
-
evalSymbols: null,
|
|
1065
|
-
upvars: null,
|
|
1066
|
-
moduleName: "stdlib",
|
|
1067
|
-
// TODO: ??
|
|
1068
|
-
scopeValues: null,
|
|
1069
|
-
isStrictMode: !0,
|
|
1070
|
-
owner: null,
|
|
1071
|
-
size: 0
|
|
1072
|
-
};
|
|
1073
|
-
function build(program, builder) {
|
|
1074
|
-
let {
|
|
1075
|
-
constants: constants,
|
|
1076
|
-
heap: heap,
|
|
1077
|
-
resolver: resolver
|
|
1078
|
-
} = program,
|
|
1079
|
-
encoder = new EncoderImpl(heap, STDLIB_META);
|
|
1080
|
-
builder(function (...op) {
|
|
1081
|
-
encodeOp(encoder, constants, resolver, STDLIB_META, op);
|
|
1082
|
-
});
|
|
1083
|
-
let result = encoder.commit(0);
|
|
1084
|
-
if ("number" != typeof result)
|
|
1085
|
-
// This shouldn't be possible
|
|
1086
|
-
throw new Error("Unexpected errors compiling std");
|
|
1087
|
-
return result;
|
|
1088
|
-
}
|
|
1089
|
-
class CompileTimeCompilationContextImpl {
|
|
1090
|
-
constants;
|
|
1091
|
-
heap;
|
|
1092
|
-
stdlib;
|
|
1093
|
-
constructor({
|
|
1094
|
-
constants: constants,
|
|
1095
|
-
heap: heap
|
|
1096
|
-
}, resolver, createOp) {
|
|
1097
|
-
this.resolver = resolver, this.createOp = createOp, this.constants = constants, this.heap = heap, this.stdlib = compileStd(this);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
function programCompilationContext(artifacts, resolver, createOp) {
|
|
1101
|
-
return new CompileTimeCompilationContextImpl(artifacts, resolver, createOp);
|
|
1102
|
-
}
|
|
1103
|
-
function templateCompilationContext(program, meta) {
|
|
1104
|
-
return {
|
|
1105
|
-
program: program,
|
|
1106
|
-
encoder: new EncoderImpl(program.heap, meta, program.stdlib),
|
|
1107
|
-
meta: meta
|
|
1108
|
-
};
|
|
1046
|
+
populateLayout && populateLayout(), op(88, $s0), op(90, $s0), op(38, $s0), op(19, 0), bindableAtNames && op(17, $s0), bindableBlocks && op(18, $s0), op(34, 1), op(96, $s0), op(100, $s0), op(1), op(40), op(60), op(98);
|
|
1109
1047
|
}
|
|
1110
1048
|
const STATEMENTS = new Compilers(),
|
|
1111
1049
|
INFLATE_ATTR_TABLE = ["class", "id", "value", "name", "type", "style", "href"],
|
|
@@ -1119,63 +1057,71 @@ function inflateAttrName(attrName) {
|
|
|
1119
1057
|
function hashToArgs(hash) {
|
|
1120
1058
|
return null === hash ? null : [hash[0].map(key => `@${key}`), hash[1]];
|
|
1121
1059
|
}
|
|
1122
|
-
STATEMENTS.add(opcodes.Comment, (op, sexp) => op(
|
|
1123
|
-
isGetFreeModifier(expression) ? op(
|
|
1124
|
-
op(
|
|
1125
|
-
}) : (expr(op, expression), op(
|
|
1060
|
+
STATEMENTS.add(opcodes.Comment, (op, sexp) => op(42, sexp[1])), STATEMENTS.add(opcodes.CloseElement, op => op(55)), STATEMENTS.add(opcodes.FlushElement, op => op(54)), STATEMENTS.add(opcodes.Modifier, (op, [, expression, positional, named]) => {
|
|
1061
|
+
isGetFreeModifier(expression) ? op(1003, expression, handle => {
|
|
1062
|
+
op(0), SimpleArgs(op, positional, named, !1), op(57, handle), op(1);
|
|
1063
|
+
}) : (expr(op, expression), op(0), SimpleArgs(op, positional, named, !1), op(33, $fp, 1), op(108), op(1));
|
|
1126
1064
|
}), STATEMENTS.add(opcodes.StaticAttr, (op, [, name, value, namespace]) => {
|
|
1127
|
-
op(
|
|
1065
|
+
op(51, inflateAttrName(name), value, namespace ?? null);
|
|
1128
1066
|
}), STATEMENTS.add(opcodes.StaticComponentAttr, (op, [, name, value, namespace]) => {
|
|
1129
|
-
op(
|
|
1067
|
+
op(105, inflateAttrName(name), value, namespace ?? null);
|
|
1130
1068
|
}), STATEMENTS.add(opcodes.DynamicAttr, (op, [, name, value, namespace]) => {
|
|
1131
|
-
expr(op, value), op(
|
|
1069
|
+
expr(op, value), op(52, inflateAttrName(name), !1, namespace ?? null);
|
|
1132
1070
|
}), STATEMENTS.add(opcodes.TrustingDynamicAttr, (op, [, name, value, namespace]) => {
|
|
1133
|
-
expr(op, value), op(
|
|
1071
|
+
expr(op, value), op(52, inflateAttrName(name), !0, namespace ?? null);
|
|
1134
1072
|
}), STATEMENTS.add(opcodes.ComponentAttr, (op, [, name, value, namespace]) => {
|
|
1135
|
-
expr(op, value), op(
|
|
1073
|
+
expr(op, value), op(53, inflateAttrName(name), !1, namespace ?? null);
|
|
1136
1074
|
}), STATEMENTS.add(opcodes.TrustingComponentAttr, (op, [, name, value, namespace]) => {
|
|
1137
|
-
expr(op, value), op(
|
|
1075
|
+
expr(op, value), op(53, inflateAttrName(name), !0, namespace ?? null);
|
|
1138
1076
|
}), STATEMENTS.add(opcodes.OpenElement, (op, [, tag]) => {
|
|
1139
|
-
op(
|
|
1077
|
+
op(48, inflateTagName(tag));
|
|
1140
1078
|
}), STATEMENTS.add(opcodes.OpenElementWithSplat, (op, [, tag]) => {
|
|
1141
|
-
op(
|
|
1079
|
+
op(89), op(48, inflateTagName(tag));
|
|
1142
1080
|
}), STATEMENTS.add(opcodes.Component, (op, [, expr, elementBlock, named, blocks]) => {
|
|
1143
|
-
isGetFreeComponent(expr) ? op(
|
|
1081
|
+
isGetFreeComponent(expr) ? op(1004, expr, component => {
|
|
1144
1082
|
InvokeComponent(op, component, elementBlock, null, named, blocks);
|
|
1145
1083
|
}) :
|
|
1146
1084
|
// otherwise, the component name was an expression, so resolve the expression
|
|
1147
1085
|
// and invoke it as a dynamic component
|
|
1148
1086
|
InvokeDynamicComponent(op, expr, elementBlock, null, named, blocks, !0, !0);
|
|
1149
|
-
}), STATEMENTS.add(opcodes.Yield, (op, [, to, params]) => YieldBlock(op, to, params)), STATEMENTS.add(opcodes.AttrSplat, (op, [, to]) => YieldBlock(op, to, null)), STATEMENTS.add(opcodes.Debugger, (op, [,
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1087
|
+
}), STATEMENTS.add(opcodes.Yield, (op, [, to, params]) => YieldBlock(op, to, params)), STATEMENTS.add(opcodes.AttrSplat, (op, [, to]) => YieldBlock(op, to, null)), STATEMENTS.add(opcodes.Debugger, (op, [, locals, upvars, lexical]) => {
|
|
1088
|
+
op(103, function (locals, upvars, lexical) {
|
|
1089
|
+
return {
|
|
1090
|
+
type: 3,
|
|
1091
|
+
value: {
|
|
1092
|
+
locals: locals,
|
|
1093
|
+
upvars: upvars,
|
|
1094
|
+
lexical: lexical
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
}(locals, upvars, lexical));
|
|
1098
|
+
}), STATEMENTS.add(opcodes.Append, (op, [, value]) => {
|
|
1153
1099
|
// Special case for static values
|
|
1154
1100
|
if (Array.isArray(value)) {
|
|
1155
|
-
if (isGetFreeComponentOrHelper(value)) op(
|
|
1101
|
+
if (isGetFreeComponentOrHelper(value)) op(1008, value, {
|
|
1156
1102
|
ifComponent(component) {
|
|
1157
1103
|
InvokeComponent(op, component, null, null, null, null);
|
|
1158
1104
|
},
|
|
1159
1105
|
ifHelper(handle) {
|
|
1160
|
-
op(
|
|
1106
|
+
op(0), Call(op, handle, null, null), op(3, stdlibOperand("cautious-non-dynamic-append")), op(1);
|
|
1161
1107
|
},
|
|
1162
1108
|
ifValue(handle) {
|
|
1163
|
-
op(
|
|
1109
|
+
op(0), op(29, handle), op(3, stdlibOperand("cautious-non-dynamic-append")), op(1);
|
|
1164
1110
|
}
|
|
1165
1111
|
});else if (value[0] === opcodes.Call) {
|
|
1166
1112
|
let [, expression, positional, named] = value;
|
|
1167
|
-
isGetFreeComponentOrHelper(expression) ? op(
|
|
1113
|
+
isGetFreeComponentOrHelper(expression) ? op(1007, expression, {
|
|
1168
1114
|
ifComponent(component) {
|
|
1169
1115
|
InvokeComponent(op, component, null, positional, hashToArgs(named), null);
|
|
1170
1116
|
},
|
|
1171
1117
|
ifHelper(handle) {
|
|
1172
|
-
op(
|
|
1118
|
+
op(0), Call(op, handle, positional, named), op(3, stdlibOperand("cautious-non-dynamic-append")), op(1);
|
|
1173
1119
|
}
|
|
1174
1120
|
}) : SwitchCases(op, () => {
|
|
1175
|
-
expr(op, expression), op(
|
|
1121
|
+
expr(op, expression), op(106);
|
|
1176
1122
|
}, when => {
|
|
1177
1123
|
when(ContentType.Component, () => {
|
|
1178
|
-
op(
|
|
1124
|
+
op(81), op(79), InvokeNonStaticComponent(op, {
|
|
1179
1125
|
capabilities: !0,
|
|
1180
1126
|
elementBlock: null,
|
|
1181
1127
|
positional: positional,
|
|
@@ -1185,52 +1131,51 @@ STATEMENTS.add(opcodes.Comment, (op, sexp) => op(Op.Comment, sexp[1])), STATEMEN
|
|
|
1185
1131
|
});
|
|
1186
1132
|
}), when(ContentType.Helper, () => {
|
|
1187
1133
|
CallDynamic(op, positional, named, () => {
|
|
1188
|
-
op(
|
|
1134
|
+
op(3, stdlibOperand("cautious-non-dynamic-append"));
|
|
1189
1135
|
});
|
|
1190
1136
|
});
|
|
1191
1137
|
});
|
|
1192
|
-
} else op(
|
|
1193
|
-
} else op(
|
|
1138
|
+
} else op(0), expr(op, value), op(3, stdlibOperand("cautious-append")), op(1);
|
|
1139
|
+
} else op(41, null == value ? "" : String(value));
|
|
1194
1140
|
}), STATEMENTS.add(opcodes.TrustingAppend, (op, [, value]) => {
|
|
1195
|
-
Array.isArray(value) ? (op(
|
|
1141
|
+
Array.isArray(value) ? (op(0), expr(op, value), op(3, stdlibOperand("trusting-append")), op(1)) : op(41, null == value ? "" : String(value));
|
|
1196
1142
|
}), STATEMENTS.add(opcodes.Block, (op, [, expr, positional, named, blocks]) => {
|
|
1197
|
-
isGetFreeComponent(expr) ? op(
|
|
1143
|
+
isGetFreeComponent(expr) ? op(1004, expr, component => {
|
|
1198
1144
|
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1199
1145
|
}) : InvokeDynamicComponent(op, expr, null, positional, named, blocks, !1, !1);
|
|
1200
1146
|
}), STATEMENTS.add(opcodes.InElement, (op, [, block, guid, destination, insertBefore]) => {
|
|
1201
|
-
ReplayableIf(op, () => (expr(op, guid), void 0 === insertBefore ? PushPrimitiveReference(op, void 0) : expr(op, insertBefore), expr(op, destination), op(
|
|
1202
|
-
op(
|
|
1147
|
+
ReplayableIf(op, () => (expr(op, guid), void 0 === insertBefore ? PushPrimitiveReference(op, void 0) : expr(op, insertBefore), expr(op, destination), op(33, $sp, 0), 4), () => {
|
|
1148
|
+
op(50), InvokeStaticBlock(op, block), op(56);
|
|
1203
1149
|
});
|
|
1204
|
-
}), STATEMENTS.add(opcodes.If, (op, [, condition, block, inverse]) => ReplayableIf(op, () => (expr(op, condition), op(
|
|
1150
|
+
}), STATEMENTS.add(opcodes.If, (op, [, condition, block, inverse]) => ReplayableIf(op, () => (expr(op, condition), op(71), 1), () => {
|
|
1205
1151
|
InvokeStaticBlock(op, block);
|
|
1206
1152
|
}, inverse ? () => {
|
|
1207
1153
|
InvokeStaticBlock(op, inverse);
|
|
1208
1154
|
} : void 0)), STATEMENTS.add(opcodes.Each, (op, [, value, key, block, inverse]) => Replayable(op, () => (key ? expr(op, key) : PushPrimitiveReference(op, null), expr(op, value), 2), () => {
|
|
1209
|
-
op(
|
|
1155
|
+
op(72, labelOperand("BODY"), labelOperand("ELSE")), op(0), op(33, $fp, 1), op(6, labelOperand("ITER")), op(1e3, "ITER"), op(74, labelOperand("BREAK")), op(1e3, "BODY"), InvokeStaticBlockWithStack(op, block, 2), op(34, 2), op(4, labelOperand("FINALLY")), op(1e3, "BREAK"), op(1), op(73), op(4, labelOperand("FINALLY")), op(1e3, "ELSE"), inverse && InvokeStaticBlock(op, inverse);
|
|
1210
1156
|
})), STATEMENTS.add(opcodes.Let, (op, [, positional, block]) => {
|
|
1211
1157
|
InvokeStaticBlockWithStack(op, block, CompilePositional(op, positional));
|
|
1212
1158
|
}), STATEMENTS.add(opcodes.WithDynamicVars, (op, [, named, block]) => {
|
|
1213
1159
|
if (named) {
|
|
1214
1160
|
let [names, expressions] = named;
|
|
1215
1161
|
CompilePositional(op, expressions), function (op, names, block) {
|
|
1216
|
-
op(
|
|
1162
|
+
op(59), op(58, names), block(), op(60);
|
|
1217
1163
|
}(op, names, () => {
|
|
1218
1164
|
InvokeStaticBlock(op, block);
|
|
1219
1165
|
});
|
|
1220
1166
|
} else InvokeStaticBlock(op, block);
|
|
1221
1167
|
}), STATEMENTS.add(opcodes.InvokeComponent, (op, [, expr, positional, named, blocks]) => {
|
|
1222
|
-
isGetFreeComponent(expr) ? op(
|
|
1168
|
+
isGetFreeComponent(expr) ? op(1004, expr, component => {
|
|
1223
1169
|
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1224
1170
|
}) : InvokeDynamicComponent(op, expr, null, positional, named, blocks, !1, !1);
|
|
1225
1171
|
});
|
|
1226
1172
|
class CompilableTemplateImpl {
|
|
1227
|
-
compiled = null;
|
|
1228
1173
|
constructor(statements, meta,
|
|
1229
1174
|
// Part of CompilableTemplate
|
|
1230
1175
|
symbolTable,
|
|
1231
1176
|
// Used for debugging
|
|
1232
1177
|
moduleName = "plain block") {
|
|
1233
|
-
this.statements = statements, this.meta = meta, this.symbolTable = symbolTable, this.moduleName = moduleName;
|
|
1178
|
+
this.statements = statements, this.meta = meta, this.symbolTable = symbolTable, this.moduleName = moduleName, this.compiled = null;
|
|
1234
1179
|
}
|
|
1235
1180
|
// Part of CompilableTemplate
|
|
1236
1181
|
compile(context) {
|
|
@@ -1247,10 +1192,9 @@ class CompilableTemplateImpl {
|
|
|
1247
1192
|
}
|
|
1248
1193
|
}
|
|
1249
1194
|
function compilable(layout, moduleName) {
|
|
1250
|
-
let [statements, symbols
|
|
1195
|
+
let [statements, symbols] = layout.block;
|
|
1251
1196
|
return new CompilableTemplateImpl(statements, meta(layout), {
|
|
1252
|
-
symbols: symbols
|
|
1253
|
-
hasEval: hasEval
|
|
1197
|
+
symbols: symbols
|
|
1254
1198
|
}, moduleName);
|
|
1255
1199
|
}
|
|
1256
1200
|
function compileStatements(statements, meta, syntaxContext) {
|
|
@@ -1258,13 +1202,10 @@ function compileStatements(statements, meta, syntaxContext) {
|
|
|
1258
1202
|
context = templateCompilationContext(syntaxContext, meta),
|
|
1259
1203
|
{
|
|
1260
1204
|
encoder: encoder,
|
|
1261
|
-
|
|
1262
|
-
constants: constants,
|
|
1263
|
-
resolver: resolver
|
|
1264
|
-
}
|
|
1205
|
+
evaluation: evaluation
|
|
1265
1206
|
} = context;
|
|
1266
1207
|
function pushOp(...op) {
|
|
1267
|
-
encodeOp(encoder,
|
|
1208
|
+
encodeOp(encoder, evaluation, meta, op);
|
|
1268
1209
|
}
|
|
1269
1210
|
for (const statement of statements) sCompiler.compile(pushOp, statement);
|
|
1270
1211
|
return context.encoder.commit(meta.size);
|
|
@@ -1299,23 +1240,119 @@ const DEFAULT_CAPABILITIES = {
|
|
|
1299
1240
|
willDestroy: !1,
|
|
1300
1241
|
hasSubOwner: !1
|
|
1301
1242
|
};
|
|
1243
|
+
class StdLib {
|
|
1244
|
+
constructor(main, trustingGuardedAppend, cautiousGuardedAppend, trustingNonDynamicAppend, cautiousNonDynamicAppend) {
|
|
1245
|
+
this.main = main, this.trustingGuardedAppend = trustingGuardedAppend, this.cautiousGuardedAppend = cautiousGuardedAppend, this.trustingNonDynamicAppend = trustingNonDynamicAppend, this.cautiousNonDynamicAppend = cautiousNonDynamicAppend;
|
|
1246
|
+
}
|
|
1247
|
+
get "trusting-append"() {
|
|
1248
|
+
return this.trustingGuardedAppend;
|
|
1249
|
+
}
|
|
1250
|
+
get "cautious-append"() {
|
|
1251
|
+
return this.cautiousGuardedAppend;
|
|
1252
|
+
}
|
|
1253
|
+
get "trusting-non-dynamic-append"() {
|
|
1254
|
+
return this.trustingNonDynamicAppend;
|
|
1255
|
+
}
|
|
1256
|
+
get "cautious-non-dynamic-append"() {
|
|
1257
|
+
return this.cautiousNonDynamicAppend;
|
|
1258
|
+
}
|
|
1259
|
+
getAppend(trusting) {
|
|
1260
|
+
return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* Append content to the DOM. This standard function triages content and does the
|
|
1266
|
+
* right thing based upon whether it's a string, safe string, component, fragment
|
|
1267
|
+
* or node.
|
|
1268
|
+
*
|
|
1269
|
+
* @param trusting whether to interpolate a string as raw HTML (corresponds to
|
|
1270
|
+
* triple curlies)
|
|
1271
|
+
*/
|
|
1272
|
+
function StdAppend(op, trusting, nonDynamicAppend) {
|
|
1273
|
+
SwitchCases(op, () => op(76), when => {
|
|
1274
|
+
when(ContentType.String, () => {
|
|
1275
|
+
trusting ? (op(68), op(43)) : op(47);
|
|
1276
|
+
}), "number" == typeof nonDynamicAppend ? (when(ContentType.Component, () => {
|
|
1277
|
+
op(81), op(79), function (op) {
|
|
1278
|
+
op(36, $s0), op(33, $sp, 1), op(35, $s0), op(0), op(83), op(85, $s0), invokePreparedComponent(op, !1, !1, !0, () => {
|
|
1279
|
+
op(92, $s0), op(95, $s0);
|
|
1280
|
+
}), op(35, $s0);
|
|
1281
|
+
}(op);
|
|
1282
|
+
}), when(ContentType.Helper, () => {
|
|
1283
|
+
CallDynamic(op, null, null, () => {
|
|
1284
|
+
op(3, nonDynamicAppend);
|
|
1285
|
+
});
|
|
1286
|
+
})) : (
|
|
1287
|
+
// when non-dynamic, we can no longer call the value (potentially because we've already called it)
|
|
1288
|
+
// this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM.
|
|
1289
|
+
when(ContentType.Component, () => {
|
|
1290
|
+
op(47);
|
|
1291
|
+
}), when(ContentType.Helper, () => {
|
|
1292
|
+
op(47);
|
|
1293
|
+
})), when(ContentType.SafeString, () => {
|
|
1294
|
+
op(68), op(44);
|
|
1295
|
+
}), when(ContentType.Fragment, () => {
|
|
1296
|
+
op(68), op(45);
|
|
1297
|
+
}), when(ContentType.Node, () => {
|
|
1298
|
+
op(68), op(46);
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
function compileStd(context) {
|
|
1303
|
+
let mainHandle = build(context, op => function (op) {
|
|
1304
|
+
op(75, $s0), invokePreparedComponent(op, !1, !1, !0);
|
|
1305
|
+
}(op)),
|
|
1306
|
+
trustingGuardedNonDynamicAppend = build(context, op => StdAppend(op, !0, null)),
|
|
1307
|
+
cautiousGuardedNonDynamicAppend = build(context, op => StdAppend(op, !1, null)),
|
|
1308
|
+
trustingGuardedDynamicAppend = build(context, op => StdAppend(op, !0, trustingGuardedNonDynamicAppend)),
|
|
1309
|
+
cautiousGuardedDynamicAppend = build(context, op => StdAppend(op, !1, cautiousGuardedNonDynamicAppend));
|
|
1310
|
+
return new StdLib(mainHandle, trustingGuardedDynamicAppend, cautiousGuardedDynamicAppend, trustingGuardedNonDynamicAppend, cautiousGuardedNonDynamicAppend);
|
|
1311
|
+
}
|
|
1312
|
+
const STDLIB_META = {
|
|
1313
|
+
symbols: {
|
|
1314
|
+
locals: null,
|
|
1315
|
+
upvars: null
|
|
1316
|
+
},
|
|
1317
|
+
moduleName: "stdlib",
|
|
1318
|
+
// TODO: ??
|
|
1319
|
+
scopeValues: null,
|
|
1320
|
+
isStrictMode: !0,
|
|
1321
|
+
owner: null,
|
|
1322
|
+
size: 0
|
|
1323
|
+
};
|
|
1324
|
+
function build(evaluation, builder) {
|
|
1325
|
+
let encoder = new EncoderImpl(evaluation.program.heap, STDLIB_META);
|
|
1326
|
+
builder(function (...op) {
|
|
1327
|
+
encodeOp(encoder, evaluation, STDLIB_META, op);
|
|
1328
|
+
});
|
|
1329
|
+
let result = encoder.commit(0);
|
|
1330
|
+
if ("number" != typeof result)
|
|
1331
|
+
// This shouldn't be possible
|
|
1332
|
+
throw new Error("Unexpected errors compiling std");
|
|
1333
|
+
return result;
|
|
1334
|
+
}
|
|
1335
|
+
class EvaluationContextImpl {
|
|
1336
|
+
constructor({
|
|
1337
|
+
constants: constants,
|
|
1338
|
+
heap: heap
|
|
1339
|
+
}, createOp, runtime) {
|
|
1340
|
+
this.constants = constants, this.heap = heap, this.resolver = runtime.resolver, this.createOp = createOp, this.env = runtime.env, this.program = runtime.program, this.stdlib = compileStd(this);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1302
1343
|
class WrappedBuilder {
|
|
1303
|
-
symbolTable;
|
|
1304
|
-
compiled = null;
|
|
1305
|
-
attrsBlockNumber;
|
|
1306
1344
|
constructor(layout, moduleName) {
|
|
1307
|
-
this.layout = layout, this.moduleName = moduleName;
|
|
1345
|
+
this.layout = layout, this.moduleName = moduleName, this.compiled = null;
|
|
1308
1346
|
let {
|
|
1309
1347
|
block: block
|
|
1310
1348
|
} = layout,
|
|
1311
|
-
[, symbols
|
|
1349
|
+
[, symbols] = block;
|
|
1312
1350
|
symbols = symbols.slice();
|
|
1313
1351
|
// ensure ATTRS_BLOCK is always included (only once) in the list of symbols
|
|
1314
1352
|
let attrsBlockIndex = symbols.indexOf("&attrs");
|
|
1315
1353
|
this.attrsBlockNumber = -1 === attrsBlockIndex ? symbols.push("&attrs") : attrsBlockIndex + 1, this.symbolTable = {
|
|
1316
|
-
hasEval: hasEval,
|
|
1317
1354
|
symbols: symbols
|
|
1318
|
-
};
|
|
1355
|
+
}, this.meta = meta(layout);
|
|
1319
1356
|
}
|
|
1320
1357
|
compile(syntax) {
|
|
1321
1358
|
if (null !== this.compiled) return this.compiled;
|
|
@@ -1323,19 +1360,16 @@ class WrappedBuilder {
|
|
|
1323
1360
|
context = templateCompilationContext(syntax, m),
|
|
1324
1361
|
{
|
|
1325
1362
|
encoder: encoder,
|
|
1326
|
-
|
|
1327
|
-
constants: constants,
|
|
1328
|
-
resolver: resolver
|
|
1329
|
-
}
|
|
1363
|
+
evaluation: evaluation
|
|
1330
1364
|
} = context;
|
|
1331
1365
|
var op, layout, attrsBlockNumber;
|
|
1332
1366
|
op = function (...op) {
|
|
1333
|
-
encodeOp(encoder,
|
|
1334
|
-
}, layout = this.layout, attrsBlockNumber = this.attrsBlockNumber, op(
|
|
1335
|
-
op(
|
|
1367
|
+
encodeOp(encoder, evaluation, m, op);
|
|
1368
|
+
}, layout = this.layout, attrsBlockNumber = this.attrsBlockNumber, op(1001), function (op, register, block) {
|
|
1369
|
+
op(36, register), block(), op(35, register);
|
|
1336
1370
|
}(op, $s1, () => {
|
|
1337
|
-
op(
|
|
1338
|
-
}), op(
|
|
1371
|
+
op(91, $s0), op(31), op(33, $sp, 0);
|
|
1372
|
+
}), op(66, labelOperand("BODY")), op(36, $s1), op(89), op(49), op(99, $s0), YieldBlock(op, attrsBlockNumber, null), op(54), op(1e3, "BODY"), InvokeStaticBlock(op, [layout.block[0], []]), op(36, $s1), op(66, labelOperand("END")), op(55), op(1e3, "END"), op(35, $s1), op(1002);
|
|
1339
1373
|
let handle = context.encoder.commit(m.size);
|
|
1340
1374
|
return "number" != typeof handle || (this.compiled = handle), handle;
|
|
1341
1375
|
}
|
|
@@ -1346,7 +1380,6 @@ let clientId = 0,
|
|
|
1346
1380
|
cacheMiss: 0
|
|
1347
1381
|
};
|
|
1348
1382
|
|
|
1349
|
-
// These interfaces are for backwards compatibility, some addons use these intimate APIs
|
|
1350
1383
|
/**
|
|
1351
1384
|
* Wraps a template js in a template module to change it into a factory
|
|
1352
1385
|
* that handles lazy parsing the template and to create per env singletons
|
|
@@ -1392,11 +1425,8 @@ function templateFactory({
|
|
|
1392
1425
|
}, factory;
|
|
1393
1426
|
}
|
|
1394
1427
|
class TemplateImpl {
|
|
1395
|
-
result = "ok";
|
|
1396
|
-
layout = null;
|
|
1397
|
-
wrappedLayout = null;
|
|
1398
1428
|
constructor(parsedLayout) {
|
|
1399
|
-
this.parsedLayout = parsedLayout;
|
|
1429
|
+
this.parsedLayout = parsedLayout, this.result = "ok", this.layout = null, this.wrappedLayout = null;
|
|
1400
1430
|
}
|
|
1401
1431
|
get moduleName() {
|
|
1402
1432
|
return this.parsedLayout.moduleName;
|
|
@@ -1420,4 +1450,4 @@ class TemplateImpl {
|
|
|
1420
1450
|
}
|
|
1421
1451
|
}
|
|
1422
1452
|
|
|
1423
|
-
export {
|
|
1453
|
+
export { DEFAULT_CAPABILITIES, EMPTY_BLOCKS, EvaluationContextImpl, MINIMAL_CAPABILITIES, StdLib, WrappedBuilder, compilable, compileStatements, compileStd, debugCompiler, InvokeStaticBlock as invokeStaticBlock, InvokeStaticBlockWithStack as invokeStaticBlockWithStack, meta, templateCacheCounters, templateCompilationContext, templateFactory };
|