ember-source 6.0.0-alpha.9 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blueprints/component/index.js +8 -71
- package/blueprints/component-class/index.js +8 -47
- package/build-metadata.json +3 -3
- package/dist/ember-template-compiler.js +4200 -6302
- package/dist/ember-testing.js +1 -1
- package/dist/ember.debug.js +4040 -8666
- package/dist/ember.prod.js +3734 -8082
- package/dist/packages/@glimmer/debug/index.js +87 -1440
- package/dist/packages/@glimmer/destroyable/index.js +59 -113
- package/dist/packages/@glimmer/encoder/index.js +4 -11
- package/dist/packages/@glimmer/global-context/index.js +40 -144
- package/dist/packages/@glimmer/manager/index.js +191 -312
- package/dist/packages/@glimmer/node/index.js +34 -76
- package/dist/packages/@glimmer/opcode-compiler/index.js +794 -1422
- package/dist/packages/@glimmer/owner/index.js +2 -1
- package/dist/packages/@glimmer/program/index.js +105 -192
- package/dist/packages/@glimmer/reference/index.js +109 -237
- package/dist/packages/@glimmer/runtime/index.js +1939 -3715
- package/dist/packages/@glimmer/util/index.js +114 -241
- package/dist/packages/@glimmer/validator/index.js +203 -409
- package/dist/packages/@glimmer/vm/index.js +163 -176
- package/dist/packages/@glimmer/wire-format/index.js +70 -71
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +1 -1
- package/lib/browsers.js +40 -68
- package/package.json +21 -24
|
@@ -1,34 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '../
|
|
3
|
-
import { Op, MachineOp, $v0, $fp, $sp, InternalComponentCapabilities, $s0, ContentType, TYPE_SIZE, ARG_SHIFT, $s1, isMachineOp, MACHINE_MASK } from '../vm/index.js';
|
|
1
|
+
import { isSmallInt, encodeImmediate, assert as debugAssert, EMPTY_STRING_ARRAY, unwrap, reverse, expect, debugToString as debugToString$1, Stack as StackImpl, isPresentArray, encodeHandle, EMPTY_ARRAY, assign, enumerate, dict } from '../util/index.js';
|
|
2
|
+
import { Op, MachineOp, $v0, $fp, InternalComponentCapabilities, $s0, $sp, ContentType, $s1, TYPE_SIZE, isMachineOp, MACHINE_MASK, ARG_SHIFT } from '../vm/index.js';
|
|
4
3
|
import { InstructionEncoderImpl } from '../encoder/index.js';
|
|
5
4
|
import { SexpOpcodes as opcodes } from '../wire-format/index.js';
|
|
6
5
|
import { hasCapability } from '../manager/index.js';
|
|
7
6
|
import { isDevelopingApp } from '@embroider/macros';
|
|
8
7
|
|
|
9
8
|
let debugCompiler;
|
|
10
|
-
function isGetLikeTuple(opcode) {
|
|
11
|
-
return Array.isArray(opcode) && opcode.length === 2;
|
|
12
|
-
}
|
|
13
9
|
function makeResolutionTypeVerifier(typeToVerify) {
|
|
14
10
|
return opcode => {
|
|
15
|
-
if (!
|
|
11
|
+
if (!function (opcode) {
|
|
12
|
+
return Array.isArray(opcode) && 2 === opcode.length;
|
|
13
|
+
}(opcode)) return !1;
|
|
16
14
|
let type = opcode[0];
|
|
17
15
|
return type === opcodes.GetStrictKeyword || type === opcodes.GetLexicalSymbol || type === typeToVerify;
|
|
18
16
|
};
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
new Array(Op.Size).fill(null), new Array(Op.Size).fill(null);
|
|
19
|
+
const isGetFreeComponent = makeResolutionTypeVerifier(opcodes.GetFreeAsComponentHead),
|
|
20
|
+
isGetFreeModifier = makeResolutionTypeVerifier(opcodes.GetFreeAsModifierHead),
|
|
21
|
+
isGetFreeHelper = makeResolutionTypeVerifier(opcodes.GetFreeAsHelperHead),
|
|
22
|
+
isGetFreeComponentOrHelper = makeResolutionTypeVerifier(opcodes.GetFreeAsComponentOrHelperHead);
|
|
24
23
|
function assertResolverInvariants(meta) {
|
|
25
24
|
if (isDevelopingApp()) {
|
|
26
|
-
if (!meta.upvars)
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
if (!meta.owner) {
|
|
30
|
-
throw new Error('Attempted to resolve a component, helper, or modifier, but no owner was associated with the template it was being resolved from');
|
|
31
|
-
}
|
|
25
|
+
if (!meta.upvars) throw new Error("Attempted to resolve a component, helper, or modifier, but no free vars were found");
|
|
26
|
+
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");
|
|
32
27
|
}
|
|
33
28
|
return meta;
|
|
34
29
|
}
|
|
@@ -38,292 +33,72 @@ function assertResolverInvariants(meta) {
|
|
|
38
33
|
* <Foo></Foo>
|
|
39
34
|
* <Foo @arg={{true}} />
|
|
40
35
|
*/
|
|
41
|
-
function resolveComponent(resolver, constants, meta, [, expr, then]) {
|
|
42
|
-
debugAssert(isGetFreeComponent(expr), 'Attempted to resolve a component with incorrect opcode');
|
|
43
|
-
let type = expr[0];
|
|
44
|
-
if (isDevelopingApp() && expr[0] === opcodes.GetStrictKeyword) {
|
|
45
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
46
|
-
throw new Error(`Attempted to resolve a component in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]] ?? '{unknown variable}'}`);
|
|
47
|
-
}
|
|
48
|
-
if (type === opcodes.GetLexicalSymbol) {
|
|
49
|
-
let {
|
|
50
|
-
scopeValues,
|
|
51
|
-
owner
|
|
52
|
-
} = meta;
|
|
53
|
-
let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
|
|
54
|
-
then(constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition')));
|
|
55
|
-
} else {
|
|
56
|
-
let {
|
|
57
|
-
upvars,
|
|
58
|
-
owner
|
|
59
|
-
} = assertResolverInvariants(meta);
|
|
60
|
-
let name = unwrap(upvars[expr[1]]);
|
|
61
|
-
let definition = resolver.lookupComponent(name, owner);
|
|
62
|
-
if (isDevelopingApp() && (typeof definition !== 'object' || definition === null)) {
|
|
63
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
64
|
-
throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`);
|
|
65
|
-
}
|
|
66
|
-
then(constants.resolvedComponent(definition, name));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* (helper)
|
|
72
|
-
* (helper arg)
|
|
73
|
-
*/
|
|
74
|
-
function resolveHelper(resolver, constants, meta, [, expr, then]) {
|
|
75
|
-
debugAssert(isGetFreeHelper(expr), 'Attempted to resolve a helper with incorrect opcode');
|
|
76
|
-
let type = expr[0];
|
|
77
|
-
if (type === opcodes.GetLexicalSymbol) {
|
|
78
|
-
let {
|
|
79
|
-
scopeValues
|
|
80
|
-
} = meta;
|
|
81
|
-
let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
|
|
82
|
-
then(constants.helper(definition));
|
|
83
|
-
} else if (type === opcodes.GetStrictKeyword) {
|
|
84
|
-
then(lookupBuiltInHelper(expr, resolver, meta, constants, 'helper'));
|
|
85
|
-
} else {
|
|
86
|
-
let {
|
|
87
|
-
upvars,
|
|
88
|
-
owner
|
|
89
|
-
} = assertResolverInvariants(meta);
|
|
90
|
-
let name = unwrap(upvars[expr[1]]);
|
|
91
|
-
let helper = resolver.lookupHelper(name, owner);
|
|
92
|
-
if (isDevelopingApp() && helper === null) {
|
|
93
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
94
|
-
throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a helper, but nothing was found.`);
|
|
95
|
-
}
|
|
96
|
-
then(constants.helper(helper, name));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* <div {{modifier}}/>
|
|
102
|
-
* <div {{modifier arg}}/>
|
|
103
|
-
* <Foo {{modifier}}/>
|
|
104
|
-
*/
|
|
105
|
-
function resolveModifier(resolver, constants, meta, [, expr, then]) {
|
|
106
|
-
debugAssert(isGetFreeModifier(expr), 'Attempted to resolve a modifier with incorrect opcode');
|
|
107
|
-
let type = expr[0];
|
|
108
|
-
if (type === opcodes.GetLexicalSymbol) {
|
|
109
|
-
let {
|
|
110
|
-
scopeValues
|
|
111
|
-
} = meta;
|
|
112
|
-
let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
|
|
113
|
-
then(constants.modifier(definition));
|
|
114
|
-
} else if (type === opcodes.GetStrictKeyword) {
|
|
115
|
-
let {
|
|
116
|
-
upvars
|
|
117
|
-
} = assertResolverInvariants(meta);
|
|
118
|
-
let name = unwrap(upvars[expr[1]]);
|
|
119
|
-
let modifier = resolver.lookupBuiltInModifier(name);
|
|
120
|
-
if (isDevelopingApp() && modifier === null) {
|
|
121
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
122
|
-
throw new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`);
|
|
123
|
-
}
|
|
124
|
-
then(constants.modifier(modifier, name));
|
|
125
|
-
} else {
|
|
126
|
-
let {
|
|
127
|
-
upvars,
|
|
128
|
-
owner
|
|
129
|
-
} = assertResolverInvariants(meta);
|
|
130
|
-
let name = unwrap(upvars[expr[1]]);
|
|
131
|
-
let modifier = resolver.lookupModifier(name, owner);
|
|
132
|
-
if (isDevelopingApp() && modifier === null) {
|
|
133
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
134
|
-
throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a modifier, but nothing was found.`);
|
|
135
|
-
}
|
|
136
|
-
then(constants.modifier(modifier, name));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* {{component-or-helper arg}}
|
|
142
|
-
*/
|
|
143
|
-
function resolveComponentOrHelper(resolver, constants, meta, [, expr, {
|
|
144
|
-
ifComponent,
|
|
145
|
-
ifHelper
|
|
146
|
-
}]) {
|
|
147
|
-
debugAssert(isGetFreeComponentOrHelper(expr), 'Attempted to resolve a component or helper with incorrect opcode');
|
|
148
|
-
let type = expr[0];
|
|
149
|
-
if (type === opcodes.GetLexicalSymbol) {
|
|
150
|
-
let {
|
|
151
|
-
scopeValues,
|
|
152
|
-
owner
|
|
153
|
-
} = meta;
|
|
154
|
-
let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
|
|
155
|
-
let component = constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition'), true);
|
|
156
|
-
if (component !== null) {
|
|
157
|
-
ifComponent(component);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
let helper = constants.helper(definition, null, true);
|
|
161
|
-
if (isDevelopingApp() && helper === null) {
|
|
162
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
163
|
-
throw new Error(`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)}`);
|
|
164
|
-
}
|
|
165
|
-
ifHelper(expect(helper, 'BUG: helper must exist'));
|
|
166
|
-
} else if (type === opcodes.GetStrictKeyword) {
|
|
167
|
-
ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'component or helper'));
|
|
168
|
-
} else {
|
|
169
|
-
let {
|
|
170
|
-
upvars,
|
|
171
|
-
owner
|
|
172
|
-
} = assertResolverInvariants(meta);
|
|
173
|
-
let name = unwrap(upvars[expr[1]]);
|
|
174
|
-
let definition = resolver.lookupComponent(name, owner);
|
|
175
|
-
if (definition !== null) {
|
|
176
|
-
ifComponent(constants.resolvedComponent(definition, name));
|
|
177
|
-
} else {
|
|
178
|
-
let helper = resolver.lookupHelper(name, owner);
|
|
179
|
-
if (isDevelopingApp() && helper === null) {
|
|
180
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
181
|
-
throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component or helper, but nothing was found.`);
|
|
182
|
-
}
|
|
183
|
-
ifHelper(constants.helper(helper, name));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* {{maybeHelperOrComponent}}
|
|
190
|
-
*/
|
|
191
|
-
function resolveOptionalComponentOrHelper(resolver, constants, meta, [, expr, {
|
|
192
|
-
ifComponent,
|
|
193
|
-
ifHelper,
|
|
194
|
-
ifValue
|
|
195
|
-
}]) {
|
|
196
|
-
debugAssert(isGetFreeComponentOrHelper(expr), 'Attempted to resolve an optional component or helper with incorrect opcode');
|
|
197
|
-
let type = expr[0];
|
|
198
|
-
if (type === opcodes.GetLexicalSymbol) {
|
|
199
|
-
let {
|
|
200
|
-
scopeValues,
|
|
201
|
-
owner
|
|
202
|
-
} = meta;
|
|
203
|
-
let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
|
|
204
|
-
if (typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) {
|
|
205
|
-
// The value is not an object, so it can't be a component or helper.
|
|
206
|
-
ifValue(constants.value(definition));
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
let component = constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition'), true);
|
|
210
|
-
if (component !== null) {
|
|
211
|
-
ifComponent(component);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
let helper = constants.helper(definition, null, true);
|
|
215
|
-
if (helper !== null) {
|
|
216
|
-
ifHelper(helper);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
ifValue(constants.value(definition));
|
|
220
|
-
} else if (type === opcodes.GetStrictKeyword) {
|
|
221
|
-
ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'value'));
|
|
222
|
-
} else {
|
|
223
|
-
let {
|
|
224
|
-
upvars,
|
|
225
|
-
owner
|
|
226
|
-
} = assertResolverInvariants(meta);
|
|
227
|
-
let name = unwrap(upvars[expr[1]]);
|
|
228
|
-
let definition = resolver.lookupComponent(name, owner);
|
|
229
|
-
if (definition !== null) {
|
|
230
|
-
ifComponent(constants.resolvedComponent(definition, name));
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
let helper = resolver.lookupHelper(name, owner);
|
|
234
|
-
if (helper !== null) {
|
|
235
|
-
ifHelper(constants.helper(helper, name));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
36
|
function lookupBuiltInHelper(expr, resolver, meta, constants, type) {
|
|
240
37
|
let {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (isDevelopingApp() &&
|
|
246
|
-
debugAssert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time');
|
|
247
|
-
|
|
38
|
+
upvars: upvars
|
|
39
|
+
} = assertResolverInvariants(meta),
|
|
40
|
+
name = unwrap(upvars[expr[1]]),
|
|
41
|
+
helper = resolver.lookupBuiltInHelper(name);
|
|
42
|
+
if (isDevelopingApp() && null === helper)
|
|
248
43
|
// Keyword helper did not exist, which means that we're attempting to use a
|
|
249
44
|
// value of some kind that is not in scope
|
|
250
|
-
throw new Error(`Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]] ??
|
|
251
|
-
}
|
|
45
|
+
throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]] ?? "{unknown variable}"}`);
|
|
252
46
|
return constants.helper(helper, name);
|
|
253
47
|
}
|
|
254
48
|
const HighLevelResolutionOpcodes = {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
};
|
|
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
|
+
};
|
|
280
74
|
function labelOperand(value) {
|
|
281
75
|
return {
|
|
282
76
|
type: HighLevelOperands.Label,
|
|
283
|
-
value
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
function debugSymbolsOperand() {
|
|
287
|
-
return {
|
|
288
|
-
type: HighLevelOperands.DebugSymbols,
|
|
289
|
-
value: undefined
|
|
77
|
+
value: value
|
|
290
78
|
};
|
|
291
79
|
}
|
|
292
80
|
function isStrictMode() {
|
|
293
81
|
return {
|
|
294
82
|
type: HighLevelOperands.IsStrictMode,
|
|
295
|
-
value:
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
function blockOperand(value) {
|
|
299
|
-
return {
|
|
300
|
-
type: HighLevelOperands.Block,
|
|
301
|
-
value
|
|
83
|
+
value: void 0
|
|
302
84
|
};
|
|
303
85
|
}
|
|
304
86
|
function stdlibOperand(value) {
|
|
305
87
|
return {
|
|
306
88
|
type: HighLevelOperands.StdLib,
|
|
307
|
-
value
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
function nonSmallIntOperand(value) {
|
|
311
|
-
debugAssert(!isSmallInt(value), 'Attempted to make a operand for an int that was not a small int, you should encode this as an immediate');
|
|
312
|
-
return {
|
|
313
|
-
type: HighLevelOperands.NonSmallInt,
|
|
314
|
-
value
|
|
89
|
+
value: value
|
|
315
90
|
};
|
|
316
91
|
}
|
|
317
92
|
function symbolTableOperand(value) {
|
|
318
93
|
return {
|
|
319
94
|
type: HighLevelOperands.SymbolTable,
|
|
320
|
-
value
|
|
95
|
+
value: value
|
|
321
96
|
};
|
|
322
97
|
}
|
|
323
98
|
function layoutOperand(value) {
|
|
324
99
|
return {
|
|
325
100
|
type: HighLevelOperands.Layout,
|
|
326
|
-
value
|
|
101
|
+
value: value
|
|
327
102
|
};
|
|
328
103
|
}
|
|
329
104
|
class Labels {
|
|
@@ -334,65 +109,207 @@ class Labels {
|
|
|
334
109
|
}
|
|
335
110
|
target(at, target) {
|
|
336
111
|
this.targets.push({
|
|
337
|
-
at,
|
|
338
|
-
target
|
|
112
|
+
at: at,
|
|
113
|
+
target: target
|
|
339
114
|
});
|
|
340
115
|
}
|
|
341
116
|
patch(heap) {
|
|
342
117
|
let {
|
|
343
|
-
targets,
|
|
344
|
-
labels
|
|
118
|
+
targets: targets,
|
|
119
|
+
labels: labels
|
|
345
120
|
} = this;
|
|
346
121
|
for (const {
|
|
347
|
-
at,
|
|
348
|
-
target
|
|
122
|
+
at: at,
|
|
123
|
+
target: target
|
|
349
124
|
} of targets) {
|
|
350
125
|
let address = labels[target] - at;
|
|
351
|
-
debugAssert(heap.getbyaddr(at)
|
|
352
|
-
heap.setbyaddr(at, address);
|
|
126
|
+
debugAssert(-1 === heap.getbyaddr(at), "Expected heap to contain a placeholder, but it did not"), heap.setbyaddr(at, address);
|
|
353
127
|
}
|
|
354
128
|
}
|
|
355
129
|
}
|
|
356
130
|
function encodeOp(encoder, constants, resolver, meta, op) {
|
|
357
|
-
if (
|
|
131
|
+
if (function (op) {
|
|
132
|
+
return op < HighLevelBuilderOpcodes.Start;
|
|
133
|
+
}(op[0])) {
|
|
358
134
|
let [type, ...operands] = op;
|
|
359
135
|
encoder.push(constants, type, ...operands);
|
|
360
|
-
} else {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
{
|
|
380
|
-
let
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
136
|
+
} else switch (op[0]) {
|
|
137
|
+
case HighLevelBuilderOpcodes.Label:
|
|
138
|
+
return encoder.label(op[1]);
|
|
139
|
+
case HighLevelBuilderOpcodes.StartLabels:
|
|
140
|
+
return encoder.startLabels();
|
|
141
|
+
case HighLevelBuilderOpcodes.StopLabels:
|
|
142
|
+
return encoder.stopLabels();
|
|
143
|
+
case HighLevelResolutionOpcodes.Component:
|
|
144
|
+
return function (resolver, constants, meta, [, expr, then]) {
|
|
145
|
+
debugAssert(isGetFreeComponent(expr), "Attempted to resolve a component with incorrect opcode");
|
|
146
|
+
let type = expr[0];
|
|
147
|
+
if (isDevelopingApp() && expr[0] === opcodes.GetStrictKeyword) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve a component in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]] ?? "{unknown variable}"}`);
|
|
148
|
+
if (type === opcodes.GetLexicalSymbol) {
|
|
149
|
+
let {
|
|
150
|
+
scopeValues: scopeValues,
|
|
151
|
+
owner: owner
|
|
152
|
+
} = meta,
|
|
153
|
+
definition = expect(scopeValues, "BUG: scopeValues must exist if template symbol is used")[expr[1]];
|
|
154
|
+
then(constants.component(definition, expect(owner, "BUG: expected owner when resolving component definition")));
|
|
155
|
+
} else {
|
|
156
|
+
let {
|
|
157
|
+
upvars: upvars,
|
|
158
|
+
owner: owner
|
|
159
|
+
} = assertResolverInvariants(meta),
|
|
160
|
+
name = unwrap(upvars[expr[1]]),
|
|
161
|
+
definition = resolver.lookupComponent(name, owner);
|
|
162
|
+
if (isDevelopingApp() && ("object" != typeof definition || null === definition)) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`);
|
|
163
|
+
then(constants.resolvedComponent(definition, name));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* (helper)
|
|
168
|
+
* (helper arg)
|
|
169
|
+
*/(resolver, constants, meta, op);
|
|
170
|
+
case HighLevelResolutionOpcodes.Modifier:
|
|
171
|
+
/**
|
|
172
|
+
* <div {{modifier}}/>
|
|
173
|
+
* <div {{modifier arg}}/>
|
|
174
|
+
* <Foo {{modifier}}/>
|
|
175
|
+
*/
|
|
176
|
+
return function (resolver, constants, meta, [, expr, then]) {
|
|
177
|
+
debugAssert(isGetFreeModifier(expr), "Attempted to resolve a modifier with incorrect opcode");
|
|
178
|
+
let type = expr[0];
|
|
179
|
+
if (type === opcodes.GetLexicalSymbol) {
|
|
180
|
+
let {
|
|
181
|
+
scopeValues: scopeValues
|
|
182
|
+
} = meta,
|
|
183
|
+
definition = expect(scopeValues, "BUG: scopeValues must exist if template symbol is used")[expr[1]];
|
|
184
|
+
then(constants.modifier(definition));
|
|
185
|
+
} else if (type === opcodes.GetStrictKeyword) {
|
|
186
|
+
let {
|
|
187
|
+
upvars: upvars
|
|
188
|
+
} = assertResolverInvariants(meta),
|
|
189
|
+
name = unwrap(upvars[expr[1]]),
|
|
190
|
+
modifier = resolver.lookupBuiltInModifier(name);
|
|
191
|
+
if (isDevelopingApp() && null === modifier) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`);
|
|
192
|
+
then(constants.modifier(modifier, name));
|
|
193
|
+
} else {
|
|
194
|
+
let {
|
|
195
|
+
upvars: upvars,
|
|
196
|
+
owner: owner
|
|
197
|
+
} = assertResolverInvariants(meta),
|
|
198
|
+
name = unwrap(upvars[expr[1]]),
|
|
199
|
+
modifier = resolver.lookupModifier(name, owner);
|
|
200
|
+
if (isDevelopingApp() && null === modifier) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve \`${name}\`, which was expected to be a modifier, but nothing was found.`);
|
|
201
|
+
then(constants.modifier(modifier, name));
|
|
385
202
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* {{component-or-helper arg}}
|
|
206
|
+
*/(resolver, constants, meta, op);
|
|
207
|
+
case HighLevelResolutionOpcodes.Helper:
|
|
208
|
+
return function (resolver, constants, meta, [, expr, then]) {
|
|
209
|
+
debugAssert(isGetFreeHelper(expr), "Attempted to resolve a helper with incorrect opcode");
|
|
210
|
+
let type = expr[0];
|
|
211
|
+
if (type === opcodes.GetLexicalSymbol) {
|
|
212
|
+
let {
|
|
213
|
+
scopeValues: scopeValues
|
|
214
|
+
} = meta,
|
|
215
|
+
definition = expect(scopeValues, "BUG: scopeValues must exist if template symbol is used")[expr[1]];
|
|
216
|
+
then(constants.helper(definition));
|
|
217
|
+
} else if (type === opcodes.GetStrictKeyword) then(lookupBuiltInHelper(expr, resolver, meta, constants, "helper"));else {
|
|
218
|
+
let {
|
|
219
|
+
upvars: upvars,
|
|
220
|
+
owner: owner
|
|
221
|
+
} = assertResolverInvariants(meta),
|
|
222
|
+
name = unwrap(upvars[expr[1]]),
|
|
223
|
+
helper = resolver.lookupHelper(name, owner);
|
|
224
|
+
if (isDevelopingApp() && null === helper) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve \`${name}\`, which was expected to be a helper, but nothing was found.`);
|
|
225
|
+
then(constants.helper(helper, name));
|
|
392
226
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
227
|
+
}(resolver, constants, meta, op);
|
|
228
|
+
case HighLevelResolutionOpcodes.ComponentOrHelper:
|
|
229
|
+
return function (resolver, constants, meta, [, expr, {
|
|
230
|
+
ifComponent: ifComponent,
|
|
231
|
+
ifHelper: ifHelper
|
|
232
|
+
}]) {
|
|
233
|
+
debugAssert(isGetFreeComponentOrHelper(expr), "Attempted to resolve a component or helper with incorrect opcode");
|
|
234
|
+
let type = expr[0];
|
|
235
|
+
if (type === opcodes.GetLexicalSymbol) {
|
|
236
|
+
let {
|
|
237
|
+
scopeValues: scopeValues,
|
|
238
|
+
owner: owner
|
|
239
|
+
} = meta,
|
|
240
|
+
definition = expect(scopeValues, "BUG: scopeValues must exist if template symbol is used")[expr[1]],
|
|
241
|
+
component = constants.component(definition, expect(owner, "BUG: expected owner when resolving component definition"), !0);
|
|
242
|
+
if (null !== component) return void ifComponent(component);
|
|
243
|
+
let helper = constants.helper(definition, null, !0);
|
|
244
|
+
if (isDevelopingApp() && null === helper) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`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)}`);
|
|
245
|
+
ifHelper(expect(helper, "BUG: helper must exist"));
|
|
246
|
+
} else if (type === opcodes.GetStrictKeyword) ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, "component or helper"));else {
|
|
247
|
+
let {
|
|
248
|
+
upvars: upvars,
|
|
249
|
+
owner: owner
|
|
250
|
+
} = assertResolverInvariants(meta),
|
|
251
|
+
name = unwrap(upvars[expr[1]]),
|
|
252
|
+
definition = resolver.lookupComponent(name, owner);
|
|
253
|
+
if (null !== definition) ifComponent(constants.resolvedComponent(definition, name));else {
|
|
254
|
+
let helper = resolver.lookupHelper(name, owner);
|
|
255
|
+
if (isDevelopingApp() && null === helper) throw debugAssert(!meta.isStrictMode, "Strict mode errors should already be handled at compile time"), new Error(`Attempted to resolve \`${name}\`, which was expected to be a component or helper, but nothing was found.`);
|
|
256
|
+
ifHelper(constants.helper(helper, name));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* {{maybeHelperOrComponent}}
|
|
262
|
+
*/(resolver, constants, meta, op);
|
|
263
|
+
case HighLevelResolutionOpcodes.OptionalComponentOrHelper:
|
|
264
|
+
return function (resolver, constants, meta, [, expr, {
|
|
265
|
+
ifComponent: ifComponent,
|
|
266
|
+
ifHelper: ifHelper,
|
|
267
|
+
ifValue: ifValue
|
|
268
|
+
}]) {
|
|
269
|
+
debugAssert(isGetFreeComponentOrHelper(expr), "Attempted to resolve an optional component or helper with incorrect opcode");
|
|
270
|
+
let type = expr[0];
|
|
271
|
+
if (type === opcodes.GetLexicalSymbol) {
|
|
272
|
+
let {
|
|
273
|
+
scopeValues: scopeValues,
|
|
274
|
+
owner: owner
|
|
275
|
+
} = meta,
|
|
276
|
+
definition = expect(scopeValues, "BUG: scopeValues must exist if template symbol is used")[expr[1]];
|
|
277
|
+
if ("function" != typeof definition && ("object" != typeof definition || null === definition))
|
|
278
|
+
// The value is not an object, so it can't be a component or helper.
|
|
279
|
+
return void ifValue(constants.value(definition));
|
|
280
|
+
let component = constants.component(definition, expect(owner, "BUG: expected owner when resolving component definition"), !0);
|
|
281
|
+
if (null !== component) return void ifComponent(component);
|
|
282
|
+
let helper = constants.helper(definition, null, !0);
|
|
283
|
+
if (null !== helper) return void ifHelper(helper);
|
|
284
|
+
ifValue(constants.value(definition));
|
|
285
|
+
} else if (type === opcodes.GetStrictKeyword) ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, "value"));else {
|
|
286
|
+
let {
|
|
287
|
+
upvars: upvars,
|
|
288
|
+
owner: owner
|
|
289
|
+
} = assertResolverInvariants(meta),
|
|
290
|
+
name = unwrap(upvars[expr[1]]),
|
|
291
|
+
definition = resolver.lookupComponent(name, owner);
|
|
292
|
+
if (null !== definition) return void ifComponent(constants.resolvedComponent(definition, name));
|
|
293
|
+
let helper = resolver.lookupHelper(name, owner);
|
|
294
|
+
null !== helper && ifHelper(constants.helper(helper, name));
|
|
295
|
+
}
|
|
296
|
+
}(resolver, constants, meta, op);
|
|
297
|
+
case HighLevelResolutionOpcodes.Local:
|
|
298
|
+
{
|
|
299
|
+
let freeVar = op[1],
|
|
300
|
+
name = expect(meta.upvars, "BUG: attempted to resolve value but no upvars found")[freeVar];
|
|
301
|
+
(0, op[2])(name, meta.moduleName);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case HighLevelResolutionOpcodes.TemplateLocal:
|
|
305
|
+
{
|
|
306
|
+
let [, valueIndex, then] = op,
|
|
307
|
+
value = expect(meta.scopeValues, "BUG: Attempted to get a template local, but template does not have any")[valueIndex];
|
|
308
|
+
then(constants.value(value));
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
default:
|
|
312
|
+
throw new Error(`Unexpected high level opcode ${op[0]}`);
|
|
396
313
|
}
|
|
397
314
|
}
|
|
398
315
|
class EncoderImpl {
|
|
@@ -401,37 +318,24 @@ class EncoderImpl {
|
|
|
401
318
|
errors = [];
|
|
402
319
|
handle;
|
|
403
320
|
constructor(heap, meta, stdlib) {
|
|
404
|
-
this.heap = heap;
|
|
405
|
-
this.meta = meta;
|
|
406
|
-
this.stdlib = stdlib;
|
|
407
|
-
this.handle = heap.malloc();
|
|
321
|
+
this.heap = heap, this.meta = meta, this.stdlib = stdlib, this.handle = heap.malloc();
|
|
408
322
|
}
|
|
409
323
|
error(error) {
|
|
410
|
-
this.encoder.encode(Op.Primitive, 0);
|
|
411
|
-
this.errors.push(error);
|
|
324
|
+
this.encoder.encode(Op.Primitive, 0), this.errors.push(error);
|
|
412
325
|
}
|
|
413
326
|
commit(size) {
|
|
414
327
|
let handle = this.handle;
|
|
415
|
-
this.heap.pushMachine(MachineOp.Return)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
errors: this.errors,
|
|
420
|
-
handle
|
|
421
|
-
};
|
|
422
|
-
} else {
|
|
423
|
-
return handle;
|
|
424
|
-
}
|
|
328
|
+
return this.heap.pushMachine(MachineOp.Return), this.heap.finishMalloc(handle, size), isPresentArray(this.errors) ? {
|
|
329
|
+
errors: this.errors,
|
|
330
|
+
handle: handle
|
|
331
|
+
} : handle;
|
|
425
332
|
}
|
|
426
333
|
push(constants, type, ...args) {
|
|
427
334
|
let {
|
|
428
|
-
heap
|
|
335
|
+
heap: heap
|
|
429
336
|
} = this;
|
|
430
|
-
if (isDevelopingApp() && type > TYPE_SIZE) {
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
let machine = isMachineOp(type) ? MACHINE_MASK : 0;
|
|
434
|
-
let first = type | machine | args.length << ARG_SHIFT;
|
|
337
|
+
if (isDevelopingApp() && type > TYPE_SIZE) throw new Error(`Opcode type over 8-bits. Got ${type}.`);
|
|
338
|
+
let first = type | (isMachineOp(type) ? MACHINE_MASK : 0) | args.length << ARG_SHIFT;
|
|
435
339
|
heap.pushRaw(first);
|
|
436
340
|
for (let i = 0; i < args.length; i++) {
|
|
437
341
|
let op = args[i];
|
|
@@ -439,36 +343,33 @@ class EncoderImpl {
|
|
|
439
343
|
}
|
|
440
344
|
}
|
|
441
345
|
operand(constants, operand) {
|
|
442
|
-
if (typeof operand
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
case HighLevelOperands.SymbolTable:
|
|
463
|
-
case HighLevelOperands.Layout:
|
|
464
|
-
return constants.value(operand.value);
|
|
465
|
-
}
|
|
346
|
+
if ("number" == typeof operand) return operand;
|
|
347
|
+
if ("object" == typeof operand && null !== operand) {
|
|
348
|
+
if (Array.isArray(operand)) return encodeHandle(constants.array(operand));
|
|
349
|
+
switch (operand.type) {
|
|
350
|
+
case HighLevelOperands.Label:
|
|
351
|
+
return this.currentLabels.target(this.heap.offset, operand.value), -1;
|
|
352
|
+
case HighLevelOperands.IsStrictMode:
|
|
353
|
+
return encodeHandle(constants.value(this.meta.isStrictMode));
|
|
354
|
+
case HighLevelOperands.DebugSymbols:
|
|
355
|
+
return encodeHandle(constants.array(this.meta.evalSymbols || EMPTY_STRING_ARRAY));
|
|
356
|
+
case HighLevelOperands.Block:
|
|
357
|
+
return encodeHandle(constants.value((block = operand.value, containing = this.meta, new CompilableTemplateImpl(block[0], containing, {
|
|
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:
|
|
365
|
+
return constants.value(operand.value);
|
|
466
366
|
}
|
|
467
367
|
}
|
|
368
|
+
var block, containing;
|
|
468
369
|
return encodeHandle(constants.value(operand));
|
|
469
370
|
}
|
|
470
371
|
get currentLabels() {
|
|
471
|
-
return expect(this.labelsStack.current,
|
|
372
|
+
return expect(this.labelsStack.current, "bug: not in a label stack");
|
|
472
373
|
}
|
|
473
374
|
label(name) {
|
|
474
375
|
this.currentLabels.label(name, this.heap.offset + 1);
|
|
@@ -477,31 +378,23 @@ class EncoderImpl {
|
|
|
477
378
|
this.labelsStack.push(new Labels());
|
|
478
379
|
}
|
|
479
380
|
stopLabels() {
|
|
480
|
-
|
|
481
|
-
label.patch(this.heap);
|
|
381
|
+
expect(this.labelsStack.pop(), "unbalanced push and pop labels").patch(this.heap);
|
|
482
382
|
}
|
|
483
383
|
}
|
|
484
|
-
function isBuilderOpcode(op) {
|
|
485
|
-
return op < HighLevelBuilderOpcodes.Start;
|
|
486
|
-
}
|
|
487
384
|
class StdLib {
|
|
488
385
|
constructor(main, trustingGuardedAppend, cautiousGuardedAppend, trustingNonDynamicAppend, cautiousNonDynamicAppend) {
|
|
489
|
-
this.main = main;
|
|
490
|
-
this.trustingGuardedAppend = trustingGuardedAppend;
|
|
491
|
-
this.cautiousGuardedAppend = cautiousGuardedAppend;
|
|
492
|
-
this.trustingNonDynamicAppend = trustingNonDynamicAppend;
|
|
493
|
-
this.cautiousNonDynamicAppend = cautiousNonDynamicAppend;
|
|
386
|
+
this.main = main, this.trustingGuardedAppend = trustingGuardedAppend, this.cautiousGuardedAppend = cautiousGuardedAppend, this.trustingNonDynamicAppend = trustingNonDynamicAppend, this.cautiousNonDynamicAppend = cautiousNonDynamicAppend;
|
|
494
387
|
}
|
|
495
|
-
get
|
|
388
|
+
get "trusting-append"() {
|
|
496
389
|
return this.trustingGuardedAppend;
|
|
497
390
|
}
|
|
498
|
-
get
|
|
391
|
+
get "cautious-append"() {
|
|
499
392
|
return this.cautiousGuardedAppend;
|
|
500
393
|
}
|
|
501
|
-
get
|
|
394
|
+
get "trusting-non-dynamic-append"() {
|
|
502
395
|
return this.trustingNonDynamicAppend;
|
|
503
396
|
}
|
|
504
|
-
get
|
|
397
|
+
get "cautious-non-dynamic-append"() {
|
|
505
398
|
return this.cautiousNonDynamicAppend;
|
|
506
399
|
}
|
|
507
400
|
getAppend(trusting) {
|
|
@@ -511,47 +404,37 @@ class StdLib {
|
|
|
511
404
|
class NamedBlocksImpl {
|
|
512
405
|
names;
|
|
513
406
|
constructor(blocks) {
|
|
514
|
-
this.blocks = blocks;
|
|
515
|
-
this.names = blocks ? Object.keys(blocks) : [];
|
|
407
|
+
this.blocks = blocks, this.names = blocks ? Object.keys(blocks) : [];
|
|
516
408
|
}
|
|
517
409
|
get(name) {
|
|
518
|
-
|
|
519
|
-
return this.blocks[name] || null;
|
|
410
|
+
return this.blocks && this.blocks[name] || null;
|
|
520
411
|
}
|
|
521
412
|
has(name) {
|
|
522
413
|
let {
|
|
523
|
-
blocks
|
|
414
|
+
blocks: blocks
|
|
524
415
|
} = this;
|
|
525
|
-
return
|
|
416
|
+
return null !== blocks && name in blocks;
|
|
526
417
|
}
|
|
527
418
|
with(name, block) {
|
|
528
419
|
let {
|
|
529
|
-
blocks
|
|
420
|
+
blocks: blocks
|
|
530
421
|
} = this;
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
return new NamedBlocksImpl({
|
|
537
|
-
[name]: block
|
|
538
|
-
});
|
|
539
|
-
}
|
|
422
|
+
return new NamedBlocksImpl(blocks ? assign({}, blocks, {
|
|
423
|
+
[name]: block
|
|
424
|
+
}) : {
|
|
425
|
+
[name]: block
|
|
426
|
+
});
|
|
540
427
|
}
|
|
541
428
|
get hasAny() {
|
|
542
|
-
return this.blocks
|
|
429
|
+
return null !== this.blocks;
|
|
543
430
|
}
|
|
544
431
|
}
|
|
545
432
|
const EMPTY_BLOCKS = new NamedBlocksImpl(null);
|
|
546
433
|
function namedBlocks(blocks) {
|
|
547
|
-
if (
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
let [keys, values] = blocks;
|
|
552
|
-
for (const [i, key] of enumerate(keys)) {
|
|
553
|
-
out[key] = unwrap(values[i]);
|
|
554
|
-
}
|
|
434
|
+
if (null === blocks) return EMPTY_BLOCKS;
|
|
435
|
+
let out = dict(),
|
|
436
|
+
[keys, values] = blocks;
|
|
437
|
+
for (const [i, key] of enumerate(keys)) out[key] = unwrap(values[i]);
|
|
555
438
|
return new NamedBlocksImpl(out);
|
|
556
439
|
}
|
|
557
440
|
|
|
@@ -560,8 +443,7 @@ function namedBlocks(blocks) {
|
|
|
560
443
|
* @param value A JavaScript primitive (undefined, null, boolean, number or string)
|
|
561
444
|
*/
|
|
562
445
|
function PushPrimitiveReference(op, value) {
|
|
563
|
-
PushPrimitive(op, value);
|
|
564
|
-
op(Op.PrimitiveReference);
|
|
446
|
+
PushPrimitive(op, value), op(Op.PrimitiveReference);
|
|
565
447
|
}
|
|
566
448
|
|
|
567
449
|
/**
|
|
@@ -571,10 +453,11 @@ function PushPrimitiveReference(op, value) {
|
|
|
571
453
|
*/
|
|
572
454
|
function PushPrimitive(op, primitive) {
|
|
573
455
|
let p = primitive;
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
456
|
+
var value;
|
|
457
|
+
"number" == typeof p && (p = isSmallInt(p) ? encodeImmediate(p) : (debugAssert(!isSmallInt(value = p), "Attempted to make a operand for an int that was not a small int, you should encode this as an immediate"), {
|
|
458
|
+
type: HighLevelOperands.NonSmallInt,
|
|
459
|
+
value: value
|
|
460
|
+
})), op(Op.Primitive, p);
|
|
578
461
|
}
|
|
579
462
|
|
|
580
463
|
/**
|
|
@@ -586,11 +469,7 @@ function PushPrimitive(op, primitive) {
|
|
|
586
469
|
* @param named An optional list of named arguments (name + expression) to compile
|
|
587
470
|
*/
|
|
588
471
|
function Call(op, handle, positional, named) {
|
|
589
|
-
op(MachineOp.PushFrame);
|
|
590
|
-
SimpleArgs(op, positional, named, false);
|
|
591
|
-
op(Op.Helper, handle);
|
|
592
|
-
op(MachineOp.PopFrame);
|
|
593
|
-
op(Op.Fetch, $v0);
|
|
472
|
+
op(MachineOp.PushFrame), SimpleArgs(op, positional, named, !1), op(Op.Helper, handle), op(MachineOp.PopFrame), op(Op.Fetch, $v0);
|
|
594
473
|
}
|
|
595
474
|
|
|
596
475
|
/**
|
|
@@ -601,20 +480,7 @@ function Call(op, handle, positional, named) {
|
|
|
601
480
|
* @param named An optional list of named arguments (name + expression) to compile
|
|
602
481
|
*/
|
|
603
482
|
function CallDynamic(op, positional, named, append) {
|
|
604
|
-
op(MachineOp.PushFrame);
|
|
605
|
-
SimpleArgs(op, positional, named, false);
|
|
606
|
-
op(Op.Dup, $fp, 1);
|
|
607
|
-
op(Op.DynamicHelper);
|
|
608
|
-
if (append) {
|
|
609
|
-
op(Op.Fetch, $v0);
|
|
610
|
-
append();
|
|
611
|
-
op(MachineOp.PopFrame);
|
|
612
|
-
op(Op.Pop, 1);
|
|
613
|
-
} else {
|
|
614
|
-
op(MachineOp.PopFrame);
|
|
615
|
-
op(Op.Pop, 1);
|
|
616
|
-
op(Op.Fetch, $v0);
|
|
617
|
-
}
|
|
483
|
+
op(MachineOp.PushFrame), SimpleArgs(op, positional, named, !1), op(Op.Dup, $fp, 1), op(Op.DynamicHelper), append ? (op(Op.Fetch, $v0), append(), op(MachineOp.PopFrame), op(Op.Pop, 1)) : (op(MachineOp.PopFrame), op(Op.Pop, 1), op(Op.Fetch, $v0));
|
|
618
484
|
}
|
|
619
485
|
|
|
620
486
|
/**
|
|
@@ -625,20 +491,8 @@ function CallDynamic(op, positional, named, append) {
|
|
|
625
491
|
* @param names a list of dynamic scope names
|
|
626
492
|
* @param block a function that returns a list of statements to evaluate
|
|
627
493
|
*/
|
|
628
|
-
function DynamicScope(op, names, block) {
|
|
629
|
-
op(Op.PushDynamicScope);
|
|
630
|
-
op(Op.BindDynamicScope, names);
|
|
631
|
-
block();
|
|
632
|
-
op(Op.PopDynamicScope);
|
|
633
|
-
}
|
|
634
494
|
function Curry(op, type, definition, positional, named) {
|
|
635
|
-
op(MachineOp.PushFrame);
|
|
636
|
-
SimpleArgs(op, positional, named, false);
|
|
637
|
-
op(Op.CaptureArgs);
|
|
638
|
-
expr(op, definition);
|
|
639
|
-
op(Op.Curry, type, isStrictMode());
|
|
640
|
-
op(MachineOp.PopFrame);
|
|
641
|
-
op(Op.Fetch, $v0);
|
|
495
|
+
op(MachineOp.PushFrame), SimpleArgs(op, positional, named, !1), op(Op.CaptureArgs), expr(op, definition), op(Op.Curry, type, isStrictMode()), op(MachineOp.PopFrame), op(Op.Fetch, $v0);
|
|
642
496
|
}
|
|
643
497
|
class Compilers {
|
|
644
498
|
names = {};
|
|
@@ -647,103 +501,18 @@ class Compilers {
|
|
|
647
501
|
this.names[name] = this.funcs.push(func) - 1;
|
|
648
502
|
}
|
|
649
503
|
compile(op, sexp) {
|
|
650
|
-
let name = sexp[0]
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
debugAssert(!!func, `expected an implementation for ${sexp[0]}`);
|
|
654
|
-
func(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);
|
|
655
508
|
}
|
|
656
509
|
}
|
|
657
510
|
const EXPRESSIONS = new Compilers();
|
|
658
|
-
EXPRESSIONS.add(opcodes.Concat, (op, [, parts]) => {
|
|
659
|
-
for (let part of parts) {
|
|
660
|
-
expr(op, part);
|
|
661
|
-
}
|
|
662
|
-
op(Op.Concat, parts.length);
|
|
663
|
-
});
|
|
664
|
-
EXPRESSIONS.add(opcodes.Call, (op, [, expression, positional, named]) => {
|
|
665
|
-
if (isGetFreeHelper(expression)) {
|
|
666
|
-
op(HighLevelResolutionOpcodes.Helper, expression, handle => {
|
|
667
|
-
Call(op, handle, positional, named);
|
|
668
|
-
});
|
|
669
|
-
} else {
|
|
670
|
-
expr(op, expression);
|
|
671
|
-
CallDynamic(op, positional, named);
|
|
672
|
-
}
|
|
673
|
-
});
|
|
674
|
-
EXPRESSIONS.add(opcodes.Curry, (op, [, expr, type, positional, named]) => {
|
|
675
|
-
Curry(op, type, expr, positional, named);
|
|
676
|
-
});
|
|
677
|
-
EXPRESSIONS.add(opcodes.GetSymbol, (op, [, sym, path]) => {
|
|
678
|
-
op(Op.GetVariable, sym);
|
|
679
|
-
withPath(op, path);
|
|
680
|
-
});
|
|
681
|
-
EXPRESSIONS.add(opcodes.GetLexicalSymbol, (op, [, sym, path]) => {
|
|
682
|
-
op(HighLevelResolutionOpcodes.TemplateLocal, sym, handle => {
|
|
683
|
-
op(Op.ConstantReference, handle);
|
|
684
|
-
withPath(op, path);
|
|
685
|
-
});
|
|
686
|
-
});
|
|
687
|
-
EXPRESSIONS.add(opcodes.GetStrictKeyword, (op, expr) => {
|
|
688
|
-
op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
|
|
689
|
-
op(HighLevelResolutionOpcodes.Helper, expr, handle => {
|
|
690
|
-
Call(op, handle, null, null);
|
|
691
|
-
});
|
|
692
|
-
});
|
|
693
|
-
});
|
|
694
|
-
EXPRESSIONS.add(opcodes.GetFreeAsHelperHead, (op, expr) => {
|
|
695
|
-
op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
|
|
696
|
-
op(HighLevelResolutionOpcodes.Helper, expr, handle => {
|
|
697
|
-
Call(op, handle, null, null);
|
|
698
|
-
});
|
|
699
|
-
});
|
|
700
|
-
});
|
|
701
511
|
function withPath(op, path) {
|
|
702
|
-
if (path
|
|
703
|
-
for (let i = 0; i < path.length; i++) {
|
|
704
|
-
op(Op.GetProperty, path[i]);
|
|
705
|
-
}
|
|
512
|
+
if (void 0 !== path && 0 !== path.length) for (let i = 0; i < path.length; i++) op(Op.GetProperty, path[i]);
|
|
706
513
|
}
|
|
707
|
-
EXPRESSIONS.add(opcodes.Undefined, op => PushPrimitiveReference(op, undefined));
|
|
708
|
-
EXPRESSIONS.add(opcodes.HasBlock, (op, [, block]) => {
|
|
709
|
-
expr(op, block);
|
|
710
|
-
op(Op.HasBlock);
|
|
711
|
-
});
|
|
712
|
-
EXPRESSIONS.add(opcodes.HasBlockParams, (op, [, block]) => {
|
|
713
|
-
expr(op, block);
|
|
714
|
-
op(Op.SpreadBlock);
|
|
715
|
-
op(Op.CompileBlock);
|
|
716
|
-
op(Op.HasBlockParams);
|
|
717
|
-
});
|
|
718
|
-
EXPRESSIONS.add(opcodes.IfInline, (op, [, condition, truthy, falsy]) => {
|
|
719
|
-
// Push in reverse order
|
|
720
|
-
expr(op, falsy);
|
|
721
|
-
expr(op, truthy);
|
|
722
|
-
expr(op, condition);
|
|
723
|
-
op(Op.IfInline);
|
|
724
|
-
});
|
|
725
|
-
EXPRESSIONS.add(opcodes.Not, (op, [, value]) => {
|
|
726
|
-
expr(op, value);
|
|
727
|
-
op(Op.Not);
|
|
728
|
-
});
|
|
729
|
-
EXPRESSIONS.add(opcodes.GetDynamicVar, (op, [, expression]) => {
|
|
730
|
-
expr(op, expression);
|
|
731
|
-
op(Op.GetDynamicVar);
|
|
732
|
-
});
|
|
733
|
-
EXPRESSIONS.add(opcodes.Log, (op, [, positional]) => {
|
|
734
|
-
op(MachineOp.PushFrame);
|
|
735
|
-
SimpleArgs(op, positional, null, false);
|
|
736
|
-
op(Op.Log);
|
|
737
|
-
op(MachineOp.PopFrame);
|
|
738
|
-
op(Op.Fetch, $v0);
|
|
739
|
-
});
|
|
740
514
|
function expr(op, expression) {
|
|
741
|
-
|
|
742
|
-
EXPRESSIONS.compile(op, expression);
|
|
743
|
-
} else {
|
|
744
|
-
PushPrimitive(op, expression);
|
|
745
|
-
op(Op.PrimitiveReference);
|
|
746
|
-
}
|
|
515
|
+
Array.isArray(expression) ? EXPRESSIONS.compile(op, expression) : (PushPrimitive(op, expression), op(Op.PrimitiveReference));
|
|
747
516
|
}
|
|
748
517
|
|
|
749
518
|
/**
|
|
@@ -754,42 +523,15 @@ function expr(op, expression) {
|
|
|
754
523
|
* @param args.blocks
|
|
755
524
|
* @param args.atNames
|
|
756
525
|
*/
|
|
757
|
-
function CompileArgs(op, positional, named, blocks, atNames) {
|
|
758
|
-
let blockNames = blocks.names;
|
|
759
|
-
for (const name of blockNames) {
|
|
760
|
-
PushYieldableBlock(op, blocks.get(name));
|
|
761
|
-
}
|
|
762
|
-
let count = CompilePositional(op, positional);
|
|
763
|
-
let flags = count << 4;
|
|
764
|
-
if (atNames) flags |= 0b1000;
|
|
765
|
-
if (blocks) {
|
|
766
|
-
flags |= 0b111;
|
|
767
|
-
}
|
|
768
|
-
let names = EMPTY_ARRAY;
|
|
769
|
-
if (named) {
|
|
770
|
-
names = named[0];
|
|
771
|
-
let val = named[1];
|
|
772
|
-
for (let i = 0; i < val.length; i++) {
|
|
773
|
-
expr(op, val[i]);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
op(Op.PushArgs, names, blockNames, flags);
|
|
777
|
-
}
|
|
778
526
|
function SimpleArgs(op, positional, named, atNames) {
|
|
779
|
-
if (
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
}
|
|
783
|
-
let count = CompilePositional(op, positional);
|
|
784
|
-
let flags = count << 4;
|
|
785
|
-
if (atNames) flags |= 0b1000;
|
|
527
|
+
if (null === positional && null === named) return void op(Op.PushEmptyArgs);
|
|
528
|
+
let flags = CompilePositional(op, positional) << 4;
|
|
529
|
+
atNames && (flags |= 8);
|
|
786
530
|
let names = EMPTY_STRING_ARRAY;
|
|
787
531
|
if (named) {
|
|
788
532
|
names = named[0];
|
|
789
533
|
let val = named[1];
|
|
790
|
-
for (let i = 0; i < val.length; i++)
|
|
791
|
-
expr(op, val[i]);
|
|
792
|
-
}
|
|
534
|
+
for (let i = 0; i < val.length; i++) expr(op, val[i]);
|
|
793
535
|
}
|
|
794
536
|
op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags);
|
|
795
537
|
}
|
|
@@ -801,10 +543,8 @@ function SimpleArgs(op, positional, named, atNames) {
|
|
|
801
543
|
* @param positional an optional list of positional arguments
|
|
802
544
|
*/
|
|
803
545
|
function CompilePositional(op, positional) {
|
|
804
|
-
if (
|
|
805
|
-
for (let i = 0; i < positional.length; i++)
|
|
806
|
-
expr(op, positional[i]);
|
|
807
|
-
}
|
|
546
|
+
if (null === positional) return 0;
|
|
547
|
+
for (let i = 0; i < positional.length; i++) expr(op, positional[i]);
|
|
808
548
|
return positional.length;
|
|
809
549
|
}
|
|
810
550
|
function meta(layout) {
|
|
@@ -821,9 +561,9 @@ function meta(layout) {
|
|
|
821
561
|
}
|
|
822
562
|
function evalSymbols(layout) {
|
|
823
563
|
let {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
564
|
+
block: block
|
|
565
|
+
} = layout,
|
|
566
|
+
[, symbols, hasEval] = block;
|
|
827
567
|
return hasEval ? symbols : null;
|
|
828
568
|
}
|
|
829
569
|
|
|
@@ -834,13 +574,7 @@ function evalSymbols(layout) {
|
|
|
834
574
|
* @param params optional block parameters to yield to the block
|
|
835
575
|
*/
|
|
836
576
|
function YieldBlock(op, to, positional) {
|
|
837
|
-
SimpleArgs(op, positional, null,
|
|
838
|
-
op(Op.GetBlock, to);
|
|
839
|
-
op(Op.SpreadBlock);
|
|
840
|
-
op(Op.CompileBlock);
|
|
841
|
-
op(Op.InvokeYield);
|
|
842
|
-
op(Op.PopScope);
|
|
843
|
-
op(MachineOp.PopFrame);
|
|
577
|
+
SimpleArgs(op, positional, null, !0), op(Op.GetBlock, to), op(Op.SpreadBlock), op(Op.CompileBlock), op(Op.InvokeYield), op(Op.PopScope), op(MachineOp.PopFrame);
|
|
844
578
|
}
|
|
845
579
|
|
|
846
580
|
/**
|
|
@@ -850,9 +584,11 @@ function YieldBlock(op, to, positional) {
|
|
|
850
584
|
* @param block An optional Compilable block
|
|
851
585
|
*/
|
|
852
586
|
function PushYieldableBlock(op, block) {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
587
|
+
!function (op, parameters) {
|
|
588
|
+
null !== parameters ? op(Op.PushSymbolTable, symbolTableOperand({
|
|
589
|
+
parameters: parameters
|
|
590
|
+
})) : PushPrimitive(op, null);
|
|
591
|
+
}(op, block && block[1]), op(Op.PushBlockScope), PushCompilable(op, block);
|
|
856
592
|
}
|
|
857
593
|
|
|
858
594
|
/**
|
|
@@ -861,11 +597,7 @@ function PushYieldableBlock(op, block) {
|
|
|
861
597
|
* @param block a Compilable block
|
|
862
598
|
*/
|
|
863
599
|
function InvokeStaticBlock(op, block) {
|
|
864
|
-
op(MachineOp.PushFrame);
|
|
865
|
-
PushCompilable(op, block);
|
|
866
|
-
op(Op.CompileBlock);
|
|
867
|
-
op(MachineOp.InvokeVirtual);
|
|
868
|
-
op(MachineOp.PopFrame);
|
|
600
|
+
op(MachineOp.PushFrame), PushCompilable(op, block), op(Op.CompileBlock), op(MachineOp.InvokeVirtual), op(MachineOp.PopFrame);
|
|
869
601
|
}
|
|
870
602
|
|
|
871
603
|
/**
|
|
@@ -876,88 +608,51 @@ function InvokeStaticBlock(op, block) {
|
|
|
876
608
|
* @param callerCount A number of stack entries to preserve
|
|
877
609
|
*/
|
|
878
610
|
function InvokeStaticBlockWithStack(op, block, callerCount) {
|
|
879
|
-
let parameters = block[1]
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
if (
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
op(MachineOp.PushFrame);
|
|
887
|
-
if (count) {
|
|
888
|
-
op(Op.ChildScope);
|
|
889
|
-
for (let i = 0; i < count; i++) {
|
|
890
|
-
op(Op.Dup, $fp, callerCount - i);
|
|
891
|
-
op(Op.SetVariable, parameters[i]);
|
|
611
|
+
let parameters = block[1],
|
|
612
|
+
calleeCount = parameters.length,
|
|
613
|
+
count = Math.min(callerCount, calleeCount);
|
|
614
|
+
if (0 !== count) {
|
|
615
|
+
if (op(MachineOp.PushFrame), count) {
|
|
616
|
+
op(Op.ChildScope);
|
|
617
|
+
for (let i = 0; i < count; i++) op(Op.Dup, $fp, callerCount - i), op(Op.SetVariable, parameters[i]);
|
|
892
618
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
op(Op.CompileBlock);
|
|
896
|
-
op(MachineOp.InvokeVirtual);
|
|
897
|
-
if (count) {
|
|
898
|
-
op(Op.PopScope);
|
|
899
|
-
}
|
|
900
|
-
op(MachineOp.PopFrame);
|
|
901
|
-
}
|
|
902
|
-
function PushSymbolTable(op, parameters) {
|
|
903
|
-
if (parameters !== null) {
|
|
904
|
-
op(Op.PushSymbolTable, symbolTableOperand({
|
|
905
|
-
parameters
|
|
906
|
-
}));
|
|
907
|
-
} else {
|
|
908
|
-
PushPrimitive(op, null);
|
|
909
|
-
}
|
|
619
|
+
PushCompilable(op, block), op(Op.CompileBlock), op(MachineOp.InvokeVirtual), count && op(Op.PopScope), op(MachineOp.PopFrame);
|
|
620
|
+
} else InvokeStaticBlock(op, block);
|
|
910
621
|
}
|
|
911
622
|
function PushCompilable(op, _block) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
}
|
|
623
|
+
var value;
|
|
624
|
+
null === _block ? PushPrimitive(op, null) : op(Op.Constant, (value = _block, {
|
|
625
|
+
type: HighLevelOperands.Block,
|
|
626
|
+
value: value
|
|
627
|
+
}));
|
|
917
628
|
}
|
|
918
629
|
function SwitchCases(op, bootstrap, matcher) {
|
|
919
630
|
// Setup the switch DSL
|
|
920
|
-
let clauses = []
|
|
921
|
-
|
|
922
|
-
|
|
631
|
+
let clauses = [],
|
|
632
|
+
count = 0;
|
|
633
|
+
// Call the callback
|
|
634
|
+
matcher(function (match, callback) {
|
|
923
635
|
clauses.push({
|
|
924
|
-
match,
|
|
925
|
-
callback,
|
|
926
|
-
label:
|
|
636
|
+
match: match,
|
|
637
|
+
callback: callback,
|
|
638
|
+
label: "CLAUSE" + count++
|
|
927
639
|
});
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
// Call the callback
|
|
931
|
-
matcher(when);
|
|
932
|
-
|
|
640
|
+
}),
|
|
933
641
|
// Emit the opcodes for the switch
|
|
934
|
-
op(Op.Enter, 1);
|
|
935
|
-
bootstrap();
|
|
936
|
-
op(HighLevelBuilderOpcodes.StartLabels);
|
|
937
|
-
|
|
642
|
+
op(Op.Enter, 1), bootstrap(), op(HighLevelBuilderOpcodes.StartLabels);
|
|
938
643
|
// First, emit the jump opcodes. We don't need a jump for the last
|
|
939
644
|
// opcode, since it bleeds directly into its clause.
|
|
940
|
-
for (let clause of clauses.slice(0, -1))
|
|
941
|
-
op(Op.JumpEq, labelOperand(clause.label), clause.match);
|
|
942
|
-
}
|
|
943
|
-
|
|
645
|
+
for (let clause of clauses.slice(0, -1)) op(Op.JumpEq, labelOperand(clause.label), clause.match);
|
|
944
646
|
// Enumerate the clauses in reverse order. Earlier matches will
|
|
945
647
|
// require fewer checks.
|
|
946
648
|
for (let i = clauses.length - 1; i >= 0; i--) {
|
|
947
649
|
let clause = unwrap(clauses[i]);
|
|
948
|
-
op(HighLevelBuilderOpcodes.Label, clause.label)
|
|
949
|
-
op(Op.Pop, 1);
|
|
950
|
-
clause.callback();
|
|
951
|
-
|
|
650
|
+
op(HighLevelBuilderOpcodes.Label, clause.label), op(Op.Pop, 1), clause.callback(),
|
|
952
651
|
// The first match is special: it is placed directly before the END
|
|
953
652
|
// label, so no additional jump is needed at the end of it.
|
|
954
|
-
|
|
955
|
-
op(MachineOp.Jump, labelOperand('END'));
|
|
956
|
-
}
|
|
653
|
+
0 !== i && op(MachineOp.Jump, labelOperand("END"));
|
|
957
654
|
}
|
|
958
|
-
op(HighLevelBuilderOpcodes.Label,
|
|
959
|
-
op(HighLevelBuilderOpcodes.StopLabels);
|
|
960
|
-
op(Op.Exit);
|
|
655
|
+
op(HighLevelBuilderOpcodes.Label, "END"), op(HighLevelBuilderOpcodes.StopLabels), op(Op.Exit);
|
|
961
656
|
}
|
|
962
657
|
|
|
963
658
|
/**
|
|
@@ -1024,54 +719,42 @@ function SwitchCases(op, bootstrap, matcher) {
|
|
|
1024
719
|
function Replayable(op, args, body) {
|
|
1025
720
|
// Start a new label frame, to give END and RETURN
|
|
1026
721
|
// a unique meaning.
|
|
1027
|
-
|
|
1028
|
-
op(HighLevelBuilderOpcodes.StartLabels);
|
|
1029
|
-
op(MachineOp.PushFrame);
|
|
1030
|
-
|
|
722
|
+
op(HighLevelBuilderOpcodes.StartLabels), op(MachineOp.PushFrame),
|
|
1031
723
|
// If the body invokes a block, its return will return to
|
|
1032
724
|
// END. Otherwise, the return in RETURN will return to END.
|
|
1033
|
-
op(MachineOp.ReturnTo, labelOperand(
|
|
1034
|
-
|
|
725
|
+
op(MachineOp.ReturnTo, labelOperand("ENDINITIAL"));
|
|
1035
726
|
// Push the arguments onto the stack. The args() function
|
|
1036
727
|
// tells us how many stack elements to retain for re-execution
|
|
1037
728
|
// when updating.
|
|
1038
729
|
let count = args();
|
|
1039
|
-
|
|
1040
730
|
// Start a new updating closure, remembering `count` elements
|
|
1041
731
|
// from the stack. Everything after this point, and before END,
|
|
1042
732
|
// will execute both initially and to update the block.
|
|
1043
|
-
|
|
733
|
+
|
|
1044
734
|
// The enter and exit opcodes also track the area of the DOM
|
|
1045
735
|
// associated with this block. If an assertion inside the block
|
|
1046
736
|
// fails (for example, the test value changes from true to false
|
|
1047
737
|
// in an #if), the DOM is cleared and the program is re-executed,
|
|
1048
738
|
// restoring `count` elements to the stack and executing the
|
|
1049
739
|
// instructions between the enter and exit.
|
|
1050
|
-
op(Op.Enter, count)
|
|
1051
|
-
|
|
740
|
+
op(Op.Enter, count),
|
|
1052
741
|
// Evaluate the body of the block. The body of the block may
|
|
1053
742
|
// return, which will jump execution to END during initial
|
|
1054
743
|
// execution, and exit the updating routine.
|
|
1055
|
-
body()
|
|
1056
|
-
|
|
744
|
+
body(),
|
|
1057
745
|
// All execution paths in the body should run the FINALLY once
|
|
1058
746
|
// they are done. It is executed both during initial execution
|
|
1059
747
|
// and during updating execution.
|
|
1060
|
-
op(HighLevelBuilderOpcodes.Label,
|
|
1061
|
-
|
|
748
|
+
op(HighLevelBuilderOpcodes.Label, "FINALLY"),
|
|
1062
749
|
// Finalize the DOM.
|
|
1063
|
-
op(Op.Exit)
|
|
1064
|
-
|
|
750
|
+
op(Op.Exit),
|
|
1065
751
|
// In initial execution, this is a noop: it returns to the
|
|
1066
752
|
// immediately following opcode. In updating execution, this
|
|
1067
753
|
// exits the updating routine.
|
|
1068
|
-
op(MachineOp.Return)
|
|
1069
|
-
|
|
754
|
+
op(MachineOp.Return),
|
|
1070
755
|
// Cleanup code for the block. Runs on initial execution
|
|
1071
756
|
// but not on updating.
|
|
1072
|
-
op(HighLevelBuilderOpcodes.Label,
|
|
1073
|
-
op(MachineOp.PopFrame);
|
|
1074
|
-
op(HighLevelBuilderOpcodes.StopLabels);
|
|
757
|
+
op(HighLevelBuilderOpcodes.Label, "ENDINITIAL"), op(MachineOp.PopFrame), op(HighLevelBuilderOpcodes.StopLabels);
|
|
1075
758
|
}
|
|
1076
759
|
|
|
1077
760
|
/**
|
|
@@ -1092,359 +775,200 @@ function Replayable(op, args, body) {
|
|
|
1092
775
|
function ReplayableIf(op, args, ifTrue, ifFalse) {
|
|
1093
776
|
return Replayable(op, args, () => {
|
|
1094
777
|
// If the conditional is false, jump to the ELSE label.
|
|
1095
|
-
op(Op.JumpUnless, labelOperand(
|
|
778
|
+
op(Op.JumpUnless, labelOperand("ELSE")),
|
|
1096
779
|
// Otherwise, execute the code associated with the true branch.
|
|
1097
|
-
ifTrue()
|
|
780
|
+
ifTrue(),
|
|
1098
781
|
// We're done, so return. In the initial execution, this runs
|
|
1099
782
|
// the cleanup code. In the updating VM, it exits the updating
|
|
1100
783
|
// routine.
|
|
1101
|
-
op(MachineOp.Jump, labelOperand(
|
|
1102
|
-
op(HighLevelBuilderOpcodes.Label, 'ELSE');
|
|
1103
|
-
|
|
784
|
+
op(MachineOp.Jump, labelOperand("FINALLY")), op(HighLevelBuilderOpcodes.Label, "ELSE"),
|
|
1104
785
|
// If the conditional is false, and code associatied ith the
|
|
1105
786
|
// false branch was provided, execute it. If there was no code
|
|
1106
787
|
// associated with the false branch, jumping to the else statement
|
|
1107
788
|
// has no other behavior.
|
|
1108
|
-
|
|
1109
|
-
ifFalse();
|
|
1110
|
-
}
|
|
789
|
+
void 0 !== ifFalse && ifFalse();
|
|
1111
790
|
});
|
|
1112
791
|
}
|
|
1113
|
-
const ATTRS_BLOCK = '&attrs';
|
|
1114
792
|
|
|
1115
793
|
// {{component}}
|
|
1116
|
-
|
|
1117
794
|
// <Component>
|
|
1118
|
-
|
|
1119
795
|
// chokepoint
|
|
1120
|
-
|
|
1121
796
|
function InvokeComponent(op, component, _elementBlock, positional, named, _blocks) {
|
|
1122
797
|
let {
|
|
1123
|
-
|
|
1124
|
-
capabilities,
|
|
1125
|
-
handle
|
|
1126
|
-
} = component;
|
|
1127
|
-
let elementBlock = _elementBlock ? [_elementBlock, []] : null;
|
|
1128
|
-
let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks;
|
|
1129
|
-
if (compilable) {
|
|
1130
|
-
op(Op.PushComponentDefinition, handle);
|
|
1131
|
-
InvokeStaticComponent(op, {
|
|
798
|
+
compilable: compilable,
|
|
1132
799
|
capabilities: capabilities,
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
800
|
+
handle: handle
|
|
801
|
+
} = component,
|
|
802
|
+
elementBlock = _elementBlock ? [_elementBlock, []] : null,
|
|
803
|
+
blocks = Array.isArray(_blocks) || null === _blocks ? namedBlocks(_blocks) : _blocks;
|
|
804
|
+
compilable ? (op(Op.PushComponentDefinition, handle), function (op, {
|
|
805
|
+
capabilities: capabilities,
|
|
806
|
+
layout: layout,
|
|
807
|
+
elementBlock: elementBlock,
|
|
808
|
+
positional: positional,
|
|
809
|
+
named: named,
|
|
810
|
+
blocks: blocks
|
|
811
|
+
}) {
|
|
812
|
+
let {
|
|
813
|
+
symbolTable: symbolTable
|
|
814
|
+
} = layout;
|
|
815
|
+
if (symbolTable.hasEval || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs)) return void InvokeNonStaticComponent(op, {
|
|
1142
816
|
capabilities: capabilities,
|
|
1143
|
-
elementBlock,
|
|
1144
|
-
positional,
|
|
1145
|
-
named,
|
|
1146
|
-
atNames:
|
|
1147
|
-
blocks
|
|
817
|
+
elementBlock: elementBlock,
|
|
818
|
+
positional: positional,
|
|
819
|
+
named: named,
|
|
820
|
+
atNames: !0,
|
|
821
|
+
blocks: blocks,
|
|
822
|
+
layout: layout
|
|
1148
823
|
});
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
if
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
op
|
|
1164
|
-
}
|
|
1165
|
-
op(Op.PushDynamicComponentInstance);
|
|
1166
|
-
InvokeNonStaticComponent(op, {
|
|
1167
|
-
capabilities: true,
|
|
1168
|
-
elementBlock,
|
|
1169
|
-
positional,
|
|
1170
|
-
named,
|
|
1171
|
-
atNames,
|
|
1172
|
-
blocks
|
|
1173
|
-
});
|
|
1174
|
-
op(HighLevelBuilderOpcodes.Label, 'ELSE');
|
|
1175
|
-
});
|
|
1176
|
-
}
|
|
1177
|
-
function InvokeStaticComponent(op, {
|
|
1178
|
-
capabilities,
|
|
1179
|
-
layout,
|
|
1180
|
-
elementBlock,
|
|
1181
|
-
positional,
|
|
1182
|
-
named,
|
|
1183
|
-
blocks
|
|
1184
|
-
}) {
|
|
1185
|
-
let {
|
|
1186
|
-
symbolTable
|
|
1187
|
-
} = layout;
|
|
1188
|
-
let bailOut = symbolTable.hasEval || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs);
|
|
1189
|
-
if (bailOut) {
|
|
1190
|
-
InvokeNonStaticComponent(op, {
|
|
1191
|
-
capabilities,
|
|
1192
|
-
elementBlock,
|
|
1193
|
-
positional,
|
|
1194
|
-
named,
|
|
1195
|
-
atNames: true,
|
|
1196
|
-
blocks,
|
|
1197
|
-
layout
|
|
1198
|
-
});
|
|
1199
|
-
return;
|
|
1200
|
-
}
|
|
1201
|
-
op(Op.Fetch, $s0);
|
|
1202
|
-
op(Op.Dup, $sp, 1);
|
|
1203
|
-
op(Op.Load, $s0);
|
|
1204
|
-
op(MachineOp.PushFrame);
|
|
1205
|
-
|
|
1206
|
-
// Setup arguments
|
|
1207
|
-
let {
|
|
1208
|
-
symbols
|
|
1209
|
-
} = symbolTable;
|
|
1210
|
-
|
|
1211
|
-
// As we push values onto the stack, we store the symbols associated with them
|
|
1212
|
-
// so that we can set them on the scope later on with SetVariable and SetBlock
|
|
1213
|
-
let blockSymbols = [];
|
|
1214
|
-
let argSymbols = [];
|
|
1215
|
-
let argNames = [];
|
|
1216
|
-
|
|
1217
|
-
// First we push the blocks onto the stack
|
|
1218
|
-
let blockNames = blocks.names;
|
|
1219
|
-
|
|
1220
|
-
// Starting with the attrs block, if it exists and is referenced in the component
|
|
1221
|
-
if (elementBlock !== null) {
|
|
1222
|
-
let symbol = symbols.indexOf(ATTRS_BLOCK);
|
|
1223
|
-
if (symbol !== -1) {
|
|
1224
|
-
PushYieldableBlock(op, elementBlock);
|
|
1225
|
-
blockSymbols.push(symbol);
|
|
824
|
+
op(Op.Fetch, $s0), op(Op.Dup, $sp, 1), op(Op.Load, $s0), op(MachineOp.PushFrame);
|
|
825
|
+
// Setup arguments
|
|
826
|
+
let {
|
|
827
|
+
symbols: symbols
|
|
828
|
+
} = symbolTable,
|
|
829
|
+
blockSymbols = [],
|
|
830
|
+
argSymbols = [],
|
|
831
|
+
argNames = [],
|
|
832
|
+
blockNames = blocks.names;
|
|
833
|
+
// As we push values onto the stack, we store the symbols associated with them
|
|
834
|
+
// so that we can set them on the scope later on with SetVariable and SetBlock
|
|
835
|
+
// Starting with the attrs block, if it exists and is referenced in the component
|
|
836
|
+
if (null !== elementBlock) {
|
|
837
|
+
let symbol = symbols.indexOf("&attrs");
|
|
838
|
+
-1 !== symbol && (PushYieldableBlock(op, elementBlock), blockSymbols.push(symbol));
|
|
1226
839
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
let symbol = symbols.indexOf(`&${name}`);
|
|
1233
|
-
if (symbol !== -1) {
|
|
1234
|
-
PushYieldableBlock(op, blocks.get(name));
|
|
1235
|
-
blockSymbols.push(symbol);
|
|
840
|
+
// Followed by the other blocks, if they exist and are referenced in the component.
|
|
841
|
+
// Also store the index of the associated symbol.
|
|
842
|
+
for (const name of blockNames) {
|
|
843
|
+
let symbol = symbols.indexOf(`&${name}`);
|
|
844
|
+
-1 !== symbol && (PushYieldableBlock(op, blocks.get(name)), blockSymbols.push(symbol));
|
|
1236
845
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
let val = named[1];
|
|
1259
|
-
for (let i = 0; i < val.length; i++) {
|
|
1260
|
-
let symbol = symbols.indexOf(unwrap(names[i]));
|
|
1261
|
-
expr(op, val[i]);
|
|
1262
|
-
argSymbols.push(symbol);
|
|
846
|
+
// Next up we have arguments. If the component has the `createArgs` capability,
|
|
847
|
+
// then it wants access to the arguments in JavaScript. We can't know whether
|
|
848
|
+
// or not an argument is used, so we have to give access to all of them.
|
|
849
|
+
if (hasCapability(capabilities, InternalComponentCapabilities.createArgs)) {
|
|
850
|
+
// First we push positional arguments
|
|
851
|
+
let flags = CompilePositional(op, positional) << 4;
|
|
852
|
+
// setup the flags with the count of positionals, and to indicate that atNames
|
|
853
|
+
// are used
|
|
854
|
+
flags |= 8;
|
|
855
|
+
let names = EMPTY_STRING_ARRAY;
|
|
856
|
+
// Next, if named args exist, push them all. If they have an associated symbol
|
|
857
|
+
// in the invoked component (e.g. they are used within its template), we push
|
|
858
|
+
// that symbol. If not, we still push the expression as it may be used, and
|
|
859
|
+
// we store the symbol as -1 (this is used later).
|
|
860
|
+
if (null !== named) {
|
|
861
|
+
names = named[0];
|
|
862
|
+
let val = named[1];
|
|
863
|
+
for (let i = 0; i < val.length; i++) {
|
|
864
|
+
let symbol = symbols.indexOf(unwrap(names[i]));
|
|
865
|
+
expr(op, val[i]), argSymbols.push(symbol);
|
|
866
|
+
}
|
|
1263
867
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
let name = unwrap(names[i]);
|
|
1282
|
-
let symbol = symbols.indexOf(name);
|
|
1283
|
-
if (symbol !== -1) {
|
|
1284
|
-
expr(op, val[i]);
|
|
1285
|
-
argSymbols.push(symbol);
|
|
1286
|
-
argNames.push(name);
|
|
868
|
+
// Finally, push the VM arguments themselves. These args won't need access
|
|
869
|
+
// to blocks (they aren't accessible from userland anyways), so we push an
|
|
870
|
+
// empty array instead of the actual block names.
|
|
871
|
+
op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags),
|
|
872
|
+
// And push an extra pop operation to remove the args before we begin setting
|
|
873
|
+
// variables on the local context
|
|
874
|
+
argSymbols.push(-1);
|
|
875
|
+
} else if (null !== named) {
|
|
876
|
+
// If the component does not have the `createArgs` capability, then the only
|
|
877
|
+
// expressions we need to push onto the stack are those that are actually
|
|
878
|
+
// referenced in the template of the invoked component (e.g. have symbols).
|
|
879
|
+
let names = named[0],
|
|
880
|
+
val = named[1];
|
|
881
|
+
for (let i = 0; i < val.length; i++) {
|
|
882
|
+
let name = unwrap(names[i]),
|
|
883
|
+
symbol = symbols.indexOf(name);
|
|
884
|
+
-1 !== symbol && (expr(op, val[i]), argSymbols.push(symbol), argNames.push(name));
|
|
1287
885
|
}
|
|
1288
886
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
if (hasCapability(capabilities, InternalComponentCapabilities.createArgs)) {
|
|
1299
|
-
op(Op.GetComponentSelf, $s0);
|
|
1300
|
-
} else {
|
|
1301
|
-
op(Op.GetComponentSelf, $s0, argNames);
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
// Setup the new root scope for the component
|
|
1305
|
-
op(Op.RootScope, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0);
|
|
1306
|
-
|
|
1307
|
-
// Pop the self reference off the stack and set it to the symbol for `this`
|
|
1308
|
-
// in the new scope. This is why all subsequent symbols are increased by one.
|
|
1309
|
-
op(Op.SetVariable, 0);
|
|
1310
|
-
|
|
1311
|
-
// Going in reverse, now we pop the args/blocks off the stack, starting with
|
|
1312
|
-
// arguments, and assign them to their symbols in the new scope.
|
|
1313
|
-
for (const symbol of reverse(argSymbols)) {
|
|
887
|
+
op(Op.BeginComponentTransaction, $s0), hasCapability(capabilities, InternalComponentCapabilities.dynamicScope) && op(Op.PushDynamicScope), hasCapability(capabilities, InternalComponentCapabilities.createInstance) && op(Op.CreateComponent, 0 | blocks.has("default"), $s0), op(Op.RegisterComponentDestructor, $s0), hasCapability(capabilities, InternalComponentCapabilities.createArgs) ? op(Op.GetComponentSelf, $s0) : op(Op.GetComponentSelf, $s0, argNames),
|
|
888
|
+
// Setup the new root scope for the component
|
|
889
|
+
op(Op.RootScope, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0),
|
|
890
|
+
// Pop the self reference off the stack and set it to the symbol for `this`
|
|
891
|
+
// in the new scope. This is why all subsequent symbols are increased by one.
|
|
892
|
+
op(Op.SetVariable, 0);
|
|
893
|
+
// Going in reverse, now we pop the args/blocks off the stack, starting with
|
|
894
|
+
// arguments, and assign them to their symbols in the new scope.
|
|
895
|
+
for (const symbol of reverse(argSymbols))
|
|
1314
896
|
// for (let i = argSymbols.length - 1; i >= 0; i--) {
|
|
1315
897
|
// let symbol = argSymbols[i];
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
op(Op.
|
|
1345
|
-
|
|
898
|
+
-1 === symbol ?
|
|
899
|
+
// The expression was not bound to a local symbol, it was only pushed to be
|
|
900
|
+
// used with VM args in the javascript side
|
|
901
|
+
op(Op.Pop, 1) : op(Op.SetVariable, symbol + 1);
|
|
902
|
+
// if any positional params exist, pop them off the stack as well
|
|
903
|
+
null !== positional && op(Op.Pop, positional.length);
|
|
904
|
+
// Finish up by popping off and assigning blocks
|
|
905
|
+
for (const symbol of reverse(blockSymbols)) op(Op.SetBlock, symbol + 1);
|
|
906
|
+
op(Op.Constant, layoutOperand(layout)), op(Op.CompileBlock), op(MachineOp.InvokeVirtual), op(Op.DidRenderLayout, $s0), op(MachineOp.PopFrame), op(Op.PopScope), hasCapability(capabilities, InternalComponentCapabilities.dynamicScope) && op(Op.PopDynamicScope), op(Op.CommitComponentTransaction), op(Op.Load, $s0);
|
|
907
|
+
}(op, {
|
|
908
|
+
capabilities: capabilities,
|
|
909
|
+
layout: compilable,
|
|
910
|
+
elementBlock: elementBlock,
|
|
911
|
+
positional: positional,
|
|
912
|
+
named: named,
|
|
913
|
+
blocks: blocks
|
|
914
|
+
})) : (op(Op.PushComponentDefinition, handle), InvokeNonStaticComponent(op, {
|
|
915
|
+
capabilities: capabilities,
|
|
916
|
+
elementBlock: elementBlock,
|
|
917
|
+
positional: positional,
|
|
918
|
+
named: named,
|
|
919
|
+
atNames: !0,
|
|
920
|
+
blocks: blocks
|
|
921
|
+
}));
|
|
922
|
+
}
|
|
923
|
+
function InvokeDynamicComponent(op, definition, _elementBlock, positional, named, _blocks, atNames, curried) {
|
|
924
|
+
let elementBlock = _elementBlock ? [_elementBlock, []] : null,
|
|
925
|
+
blocks = Array.isArray(_blocks) || null === _blocks ? namedBlocks(_blocks) : _blocks;
|
|
926
|
+
Replayable(op, () => (expr(op, definition), op(Op.Dup, $sp, 0), 2), () => {
|
|
927
|
+
op(Op.JumpUnless, labelOperand("ELSE")), curried ? op(Op.ResolveCurriedComponent) : op(Op.ResolveDynamicComponent, isStrictMode()), op(Op.PushDynamicComponentInstance), InvokeNonStaticComponent(op, {
|
|
928
|
+
capabilities: !0,
|
|
929
|
+
elementBlock: elementBlock,
|
|
930
|
+
positional: positional,
|
|
931
|
+
named: named,
|
|
932
|
+
atNames: atNames,
|
|
933
|
+
blocks: blocks
|
|
934
|
+
}), op(HighLevelBuilderOpcodes.Label, "ELSE");
|
|
935
|
+
});
|
|
1346
936
|
}
|
|
1347
937
|
function InvokeNonStaticComponent(op, {
|
|
1348
|
-
capabilities,
|
|
1349
|
-
elementBlock,
|
|
1350
|
-
positional,
|
|
1351
|
-
named,
|
|
1352
|
-
atNames,
|
|
938
|
+
capabilities: capabilities,
|
|
939
|
+
elementBlock: elementBlock,
|
|
940
|
+
positional: positional,
|
|
941
|
+
named: named,
|
|
942
|
+
atNames: atNames,
|
|
1353
943
|
blocks: namedBlocks,
|
|
1354
|
-
layout
|
|
944
|
+
layout: layout
|
|
1355
945
|
}) {
|
|
1356
|
-
let bindableBlocks = !!namedBlocks
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
op(Op.Fetch, $s0)
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
op(Op.CompileBlock);
|
|
1370
|
-
} else {
|
|
1371
|
-
op(Op.GetComponentLayout, $s0);
|
|
946
|
+
let bindableBlocks = !!namedBlocks,
|
|
947
|
+
bindableAtNames = !0 === capabilities || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs) || !(!named || 0 === named[0].length),
|
|
948
|
+
blocks = namedBlocks.with("attrs", elementBlock);
|
|
949
|
+
op(Op.Fetch, $s0), op(Op.Dup, $sp, 1), op(Op.Load, $s0), op(MachineOp.PushFrame), function (op, positional, named, blocks, atNames) {
|
|
950
|
+
let blockNames = blocks.names;
|
|
951
|
+
for (const name of blockNames) PushYieldableBlock(op, blocks.get(name));
|
|
952
|
+
let flags = CompilePositional(op, positional) << 4;
|
|
953
|
+
atNames && (flags |= 8), blocks && (flags |= 7);
|
|
954
|
+
let names = EMPTY_ARRAY;
|
|
955
|
+
if (named) {
|
|
956
|
+
names = named[0];
|
|
957
|
+
let val = named[1];
|
|
958
|
+
for (let i = 0; i < val.length; i++) expr(op, val[i]);
|
|
1372
959
|
}
|
|
1373
|
-
op(Op.
|
|
1374
|
-
})
|
|
1375
|
-
|
|
1376
|
-
}
|
|
1377
|
-
function WrappedComponent(op, layout, attrsBlockNumber) {
|
|
1378
|
-
op(HighLevelBuilderOpcodes.StartLabels);
|
|
1379
|
-
WithSavedRegister(op, $s1, () => {
|
|
1380
|
-
op(Op.GetComponentTagName, $s0);
|
|
1381
|
-
op(Op.PrimitiveReference);
|
|
1382
|
-
op(Op.Dup, $sp, 0);
|
|
1383
|
-
});
|
|
1384
|
-
op(Op.JumpUnless, labelOperand('BODY'));
|
|
1385
|
-
op(Op.Fetch, $s1);
|
|
1386
|
-
op(Op.PutComponentOperations);
|
|
1387
|
-
op(Op.OpenDynamicElement);
|
|
1388
|
-
op(Op.DidCreateElement, $s0);
|
|
1389
|
-
YieldBlock(op, attrsBlockNumber, null);
|
|
1390
|
-
op(Op.FlushElement);
|
|
1391
|
-
op(HighLevelBuilderOpcodes.Label, 'BODY');
|
|
1392
|
-
InvokeStaticBlock(op, [layout.block[0], []]);
|
|
1393
|
-
op(Op.Fetch, $s1);
|
|
1394
|
-
op(Op.JumpUnless, labelOperand('END'));
|
|
1395
|
-
op(Op.CloseElement);
|
|
1396
|
-
op(HighLevelBuilderOpcodes.Label, 'END');
|
|
1397
|
-
op(Op.Load, $s1);
|
|
1398
|
-
op(HighLevelBuilderOpcodes.StopLabels);
|
|
960
|
+
op(Op.PushArgs, names, blockNames, flags);
|
|
961
|
+
}(op, positional, named, blocks, atNames), op(Op.PrepareArgs, $s0), invokePreparedComponent(op, blocks.has("default"), bindableBlocks, bindableAtNames, () => {
|
|
962
|
+
layout ? (op(Op.PushSymbolTable, symbolTableOperand(layout.symbolTable)), op(Op.Constant, layoutOperand(layout)), op(Op.CompileBlock)) : op(Op.GetComponentLayout, $s0), op(Op.PopulateLayout, $s0);
|
|
963
|
+
}), op(Op.Load, $s0);
|
|
1399
964
|
}
|
|
1400
965
|
function invokePreparedComponent(op, hasBlock, bindableBlocks, bindableAtNames, populateLayout = null) {
|
|
1401
|
-
op(Op.BeginComponentTransaction, $s0)
|
|
1402
|
-
op(Op.PushDynamicScope);
|
|
1403
|
-
op(Op.CreateComponent, hasBlock | 0, $s0);
|
|
1404
|
-
|
|
966
|
+
op(Op.BeginComponentTransaction, $s0), op(Op.PushDynamicScope), op(Op.CreateComponent, 0 | hasBlock, $s0),
|
|
1405
967
|
// this has to run after createComponent to allow
|
|
1406
968
|
// for late-bound layouts, but a caller is free
|
|
1407
969
|
// to populate the layout earlier if it wants to
|
|
1408
970
|
// and do nothing here.
|
|
1409
|
-
|
|
1410
|
-
populateLayout();
|
|
1411
|
-
}
|
|
1412
|
-
op(Op.RegisterComponentDestructor, $s0);
|
|
1413
|
-
op(Op.GetComponentSelf, $s0);
|
|
1414
|
-
op(Op.VirtualRootScope, $s0);
|
|
1415
|
-
op(Op.SetVariable, 0);
|
|
1416
|
-
op(Op.SetupForEval, $s0);
|
|
1417
|
-
if (bindableAtNames) op(Op.SetNamedVariables, $s0);
|
|
1418
|
-
if (bindableBlocks) op(Op.SetBlocks, $s0);
|
|
1419
|
-
op(Op.Pop, 1);
|
|
1420
|
-
op(Op.InvokeComponentLayout, $s0);
|
|
1421
|
-
op(Op.DidRenderLayout, $s0);
|
|
1422
|
-
op(MachineOp.PopFrame);
|
|
1423
|
-
op(Op.PopScope);
|
|
1424
|
-
op(Op.PopDynamicScope);
|
|
1425
|
-
op(Op.CommitComponentTransaction);
|
|
1426
|
-
}
|
|
1427
|
-
function InvokeBareComponent(op) {
|
|
1428
|
-
op(Op.Fetch, $s0);
|
|
1429
|
-
op(Op.Dup, $sp, 1);
|
|
1430
|
-
op(Op.Load, $s0);
|
|
1431
|
-
op(MachineOp.PushFrame);
|
|
1432
|
-
op(Op.PushEmptyArgs);
|
|
1433
|
-
op(Op.PrepareArgs, $s0);
|
|
1434
|
-
invokePreparedComponent(op, false, false, true, () => {
|
|
1435
|
-
op(Op.GetComponentLayout, $s0);
|
|
1436
|
-
op(Op.PopulateLayout, $s0);
|
|
1437
|
-
});
|
|
1438
|
-
op(Op.Load, $s0);
|
|
1439
|
-
}
|
|
1440
|
-
function WithSavedRegister(op, register, block) {
|
|
1441
|
-
op(Op.Fetch, register);
|
|
1442
|
-
block();
|
|
1443
|
-
op(Op.Load, register);
|
|
1444
|
-
}
|
|
1445
|
-
function main(op) {
|
|
1446
|
-
op(Op.Main, $s0);
|
|
1447
|
-
invokePreparedComponent(op, false, false, true);
|
|
971
|
+
populateLayout && populateLayout(), op(Op.RegisterComponentDestructor, $s0), op(Op.GetComponentSelf, $s0), op(Op.VirtualRootScope, $s0), op(Op.SetVariable, 0), op(Op.SetupForEval, $s0), bindableAtNames && op(Op.SetNamedVariables, $s0), bindableBlocks && op(Op.SetBlocks, $s0), op(Op.Pop, 1), op(Op.InvokeComponentLayout, $s0), op(Op.DidRenderLayout, $s0), op(MachineOp.PopFrame), op(Op.PopScope), op(Op.PopDynamicScope), op(Op.CommitComponentTransaction);
|
|
1448
972
|
}
|
|
1449
973
|
|
|
1450
974
|
/**
|
|
@@ -1458,499 +982,371 @@ function main(op) {
|
|
|
1458
982
|
function StdAppend(op, trusting, nonDynamicAppend) {
|
|
1459
983
|
SwitchCases(op, () => op(Op.ContentType), when => {
|
|
1460
984
|
when(ContentType.String, () => {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
op(
|
|
1471
|
-
op(Op.PushDynamicComponentInstance);
|
|
1472
|
-
InvokeBareComponent(op);
|
|
1473
|
-
});
|
|
1474
|
-
when(ContentType.Helper, () => {
|
|
1475
|
-
CallDynamic(op, null, null, () => {
|
|
1476
|
-
op(MachineOp.InvokeStatic, nonDynamicAppend);
|
|
1477
|
-
});
|
|
1478
|
-
});
|
|
1479
|
-
} else {
|
|
1480
|
-
// when non-dynamic, we can no longer call the value (potentially because we've already called it)
|
|
1481
|
-
// this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM.
|
|
1482
|
-
when(ContentType.Component, () => {
|
|
1483
|
-
op(Op.AppendText);
|
|
1484
|
-
});
|
|
1485
|
-
when(ContentType.Helper, () => {
|
|
1486
|
-
op(Op.AppendText);
|
|
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);
|
|
1487
995
|
});
|
|
1488
|
-
}
|
|
1489
|
-
when
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
when(ContentType.
|
|
1494
|
-
op(Op.
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
when(ContentType.
|
|
1498
|
-
op(Op.AssertSame);
|
|
1499
|
-
|
|
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);
|
|
1500
1009
|
});
|
|
1501
1010
|
});
|
|
1502
1011
|
}
|
|
1503
1012
|
function compileStd(context) {
|
|
1504
|
-
let mainHandle = build(context, op =>
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
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));
|
|
1509
1020
|
return new StdLib(mainHandle, trustingGuardedDynamicAppend, cautiousGuardedDynamicAppend, trustingGuardedNonDynamicAppend, cautiousGuardedNonDynamicAppend);
|
|
1510
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
|
+
});
|
|
1511
1063
|
const STDLIB_META = {
|
|
1512
1064
|
evalSymbols: null,
|
|
1513
1065
|
upvars: null,
|
|
1514
|
-
moduleName:
|
|
1066
|
+
moduleName: "stdlib",
|
|
1515
1067
|
// TODO: ??
|
|
1516
1068
|
scopeValues: null,
|
|
1517
|
-
isStrictMode:
|
|
1069
|
+
isStrictMode: !0,
|
|
1518
1070
|
owner: null,
|
|
1519
1071
|
size: 0
|
|
1520
1072
|
};
|
|
1521
1073
|
function build(program, builder) {
|
|
1522
1074
|
let {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
function
|
|
1075
|
+
constants: constants,
|
|
1076
|
+
heap: heap,
|
|
1077
|
+
resolver: resolver
|
|
1078
|
+
} = program,
|
|
1079
|
+
encoder = new EncoderImpl(heap, STDLIB_META);
|
|
1080
|
+
builder(function (...op) {
|
|
1529
1081
|
encodeOp(encoder, constants, resolver, STDLIB_META, op);
|
|
1530
|
-
}
|
|
1531
|
-
builder(pushOp);
|
|
1082
|
+
});
|
|
1532
1083
|
let result = encoder.commit(0);
|
|
1533
|
-
if (typeof result
|
|
1084
|
+
if ("number" != typeof result)
|
|
1534
1085
|
// This shouldn't be possible
|
|
1535
|
-
throw new Error(
|
|
1536
|
-
|
|
1537
|
-
return result;
|
|
1538
|
-
}
|
|
1086
|
+
throw new Error("Unexpected errors compiling std");
|
|
1087
|
+
return result;
|
|
1539
1088
|
}
|
|
1540
1089
|
class CompileTimeCompilationContextImpl {
|
|
1541
1090
|
constants;
|
|
1542
1091
|
heap;
|
|
1543
1092
|
stdlib;
|
|
1544
1093
|
constructor({
|
|
1545
|
-
constants,
|
|
1546
|
-
heap
|
|
1094
|
+
constants: constants,
|
|
1095
|
+
heap: heap
|
|
1547
1096
|
}, resolver, createOp) {
|
|
1548
|
-
this.resolver = resolver;
|
|
1549
|
-
this.createOp = createOp;
|
|
1550
|
-
this.constants = constants;
|
|
1551
|
-
this.heap = heap;
|
|
1552
|
-
this.stdlib = compileStd(this);
|
|
1097
|
+
this.resolver = resolver, this.createOp = createOp, this.constants = constants, this.heap = heap, this.stdlib = compileStd(this);
|
|
1553
1098
|
}
|
|
1554
1099
|
}
|
|
1555
1100
|
function programCompilationContext(artifacts, resolver, createOp) {
|
|
1556
1101
|
return new CompileTimeCompilationContextImpl(artifacts, resolver, createOp);
|
|
1557
1102
|
}
|
|
1558
1103
|
function templateCompilationContext(program, meta) {
|
|
1559
|
-
let encoder = new EncoderImpl(program.heap, meta, program.stdlib);
|
|
1560
1104
|
return {
|
|
1561
|
-
program,
|
|
1562
|
-
encoder,
|
|
1563
|
-
meta
|
|
1105
|
+
program: program,
|
|
1106
|
+
encoder: new EncoderImpl(program.heap, meta, program.stdlib),
|
|
1107
|
+
meta: meta
|
|
1564
1108
|
};
|
|
1565
1109
|
}
|
|
1566
|
-
const STATEMENTS = new Compilers()
|
|
1567
|
-
|
|
1568
|
-
|
|
1110
|
+
const STATEMENTS = new Compilers(),
|
|
1111
|
+
INFLATE_ATTR_TABLE = ["class", "id", "value", "name", "type", "style", "href"],
|
|
1112
|
+
INFLATE_TAG_TABLE = ["div", "span", "p", "a"];
|
|
1569
1113
|
function inflateTagName(tagName) {
|
|
1570
|
-
return typeof tagName
|
|
1114
|
+
return "string" == typeof tagName ? tagName : INFLATE_TAG_TABLE[tagName];
|
|
1571
1115
|
}
|
|
1572
1116
|
function inflateAttrName(attrName) {
|
|
1573
|
-
return typeof attrName
|
|
1117
|
+
return "string" == typeof attrName ? attrName : INFLATE_ATTR_TABLE[attrName];
|
|
1574
1118
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
STATEMENTS.add(opcodes.Modifier, (op, [, expression, positional, named]) => {
|
|
1579
|
-
|
|
1580
|
-
op(
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
op(Op.Modifier, handle);
|
|
1584
|
-
op(MachineOp.PopFrame);
|
|
1585
|
-
});
|
|
1586
|
-
} else {
|
|
1587
|
-
expr(op, expression);
|
|
1588
|
-
op(MachineOp.PushFrame);
|
|
1589
|
-
SimpleArgs(op, positional, named, false);
|
|
1590
|
-
op(Op.Dup, $fp, 1);
|
|
1591
|
-
op(Op.DynamicModifier);
|
|
1592
|
-
op(MachineOp.PopFrame);
|
|
1593
|
-
}
|
|
1594
|
-
});
|
|
1595
|
-
STATEMENTS.add(opcodes.StaticAttr, (op, [, name, value, namespace]) => {
|
|
1119
|
+
function hashToArgs(hash) {
|
|
1120
|
+
return null === hash ? null : [hash[0].map(key => `@${key}`), hash[1]];
|
|
1121
|
+
}
|
|
1122
|
+
STATEMENTS.add(opcodes.Comment, (op, sexp) => op(Op.Comment, sexp[1])), STATEMENTS.add(opcodes.CloseElement, op => op(Op.CloseElement)), STATEMENTS.add(opcodes.FlushElement, op => op(Op.FlushElement)), STATEMENTS.add(opcodes.Modifier, (op, [, expression, positional, named]) => {
|
|
1123
|
+
isGetFreeModifier(expression) ? op(HighLevelResolutionOpcodes.Modifier, expression, handle => {
|
|
1124
|
+
op(MachineOp.PushFrame), SimpleArgs(op, positional, named, !1), op(Op.Modifier, handle), op(MachineOp.PopFrame);
|
|
1125
|
+
}) : (expr(op, expression), op(MachineOp.PushFrame), SimpleArgs(op, positional, named, !1), op(Op.Dup, $fp, 1), op(Op.DynamicModifier), op(MachineOp.PopFrame));
|
|
1126
|
+
}), STATEMENTS.add(opcodes.StaticAttr, (op, [, name, value, namespace]) => {
|
|
1596
1127
|
op(Op.StaticAttr, inflateAttrName(name), value, namespace ?? null);
|
|
1597
|
-
})
|
|
1598
|
-
STATEMENTS.add(opcodes.StaticComponentAttr, (op, [, name, value, namespace]) => {
|
|
1128
|
+
}), STATEMENTS.add(opcodes.StaticComponentAttr, (op, [, name, value, namespace]) => {
|
|
1599
1129
|
op(Op.StaticComponentAttr, inflateAttrName(name), value, namespace ?? null);
|
|
1600
|
-
})
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
op(Op.DynamicAttr, inflateAttrName(name),
|
|
1604
|
-
})
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
op(Op.
|
|
1608
|
-
})
|
|
1609
|
-
STATEMENTS.add(opcodes.ComponentAttr, (op, [, name, value, namespace]) => {
|
|
1610
|
-
expr(op, value);
|
|
1611
|
-
op(Op.ComponentAttr, inflateAttrName(name), false, namespace ?? null);
|
|
1612
|
-
});
|
|
1613
|
-
STATEMENTS.add(opcodes.TrustingComponentAttr, (op, [, name, value, namespace]) => {
|
|
1614
|
-
expr(op, value);
|
|
1615
|
-
op(Op.ComponentAttr, inflateAttrName(name), true, namespace ?? null);
|
|
1616
|
-
});
|
|
1617
|
-
STATEMENTS.add(opcodes.OpenElement, (op, [, tag]) => {
|
|
1618
|
-
op(Op.OpenElement, inflateTagName(tag));
|
|
1619
|
-
});
|
|
1620
|
-
STATEMENTS.add(opcodes.OpenElementWithSplat, (op, [, tag]) => {
|
|
1621
|
-
op(Op.PutComponentOperations);
|
|
1130
|
+
}), STATEMENTS.add(opcodes.DynamicAttr, (op, [, name, value, namespace]) => {
|
|
1131
|
+
expr(op, value), op(Op.DynamicAttr, inflateAttrName(name), !1, namespace ?? null);
|
|
1132
|
+
}), STATEMENTS.add(opcodes.TrustingDynamicAttr, (op, [, name, value, namespace]) => {
|
|
1133
|
+
expr(op, value), op(Op.DynamicAttr, inflateAttrName(name), !0, namespace ?? null);
|
|
1134
|
+
}), STATEMENTS.add(opcodes.ComponentAttr, (op, [, name, value, namespace]) => {
|
|
1135
|
+
expr(op, value), op(Op.ComponentAttr, inflateAttrName(name), !1, namespace ?? null);
|
|
1136
|
+
}), STATEMENTS.add(opcodes.TrustingComponentAttr, (op, [, name, value, namespace]) => {
|
|
1137
|
+
expr(op, value), op(Op.ComponentAttr, inflateAttrName(name), !0, namespace ?? null);
|
|
1138
|
+
}), STATEMENTS.add(opcodes.OpenElement, (op, [, tag]) => {
|
|
1622
1139
|
op(Op.OpenElement, inflateTagName(tag));
|
|
1623
|
-
})
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
STATEMENTS.add(opcodes.
|
|
1636
|
-
STATEMENTS.add(opcodes.AttrSplat, (op, [, to]) => YieldBlock(op, to, null));
|
|
1637
|
-
STATEMENTS.add(opcodes.Debugger, (op, [, debugInfo]) => op(Op.Debugger, debugSymbolsOperand(), debugInfo));
|
|
1638
|
-
STATEMENTS.add(opcodes.Append, (op, [, value]) => {
|
|
1140
|
+
}), STATEMENTS.add(opcodes.OpenElementWithSplat, (op, [, tag]) => {
|
|
1141
|
+
op(Op.PutComponentOperations), op(Op.OpenElement, inflateTagName(tag));
|
|
1142
|
+
}), STATEMENTS.add(opcodes.Component, (op, [, expr, elementBlock, named, blocks]) => {
|
|
1143
|
+
isGetFreeComponent(expr) ? op(HighLevelResolutionOpcodes.Component, expr, component => {
|
|
1144
|
+
InvokeComponent(op, component, elementBlock, null, named, blocks);
|
|
1145
|
+
}) :
|
|
1146
|
+
// otherwise, the component name was an expression, so resolve the expression
|
|
1147
|
+
// and invoke it as a dynamic component
|
|
1148
|
+
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, [, debugInfo]) => op(Op.Debugger, {
|
|
1150
|
+
type: HighLevelOperands.DebugSymbols,
|
|
1151
|
+
value: void 0
|
|
1152
|
+
}, debugInfo)), STATEMENTS.add(opcodes.Append, (op, [, value]) => {
|
|
1639
1153
|
// Special case for static values
|
|
1640
|
-
if (
|
|
1641
|
-
op(
|
|
1642
|
-
} else if (isGetFreeComponentOrHelper(value)) {
|
|
1643
|
-
op(HighLevelResolutionOpcodes.OptionalComponentOrHelper, value, {
|
|
1154
|
+
if (Array.isArray(value)) {
|
|
1155
|
+
if (isGetFreeComponentOrHelper(value)) op(HighLevelResolutionOpcodes.OptionalComponentOrHelper, value, {
|
|
1644
1156
|
ifComponent(component) {
|
|
1645
1157
|
InvokeComponent(op, component, null, null, null, null);
|
|
1646
1158
|
},
|
|
1647
1159
|
ifHelper(handle) {
|
|
1648
|
-
op(MachineOp.PushFrame);
|
|
1649
|
-
Call(op, handle, null, null);
|
|
1650
|
-
op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
|
|
1651
|
-
op(MachineOp.PopFrame);
|
|
1160
|
+
op(MachineOp.PushFrame), Call(op, handle, null, null), op(MachineOp.InvokeStatic, stdlibOperand("cautious-non-dynamic-append")), op(MachineOp.PopFrame);
|
|
1652
1161
|
},
|
|
1653
1162
|
ifValue(handle) {
|
|
1654
|
-
op(MachineOp.PushFrame);
|
|
1655
|
-
op(Op.ConstantReference, handle);
|
|
1656
|
-
op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
|
|
1657
|
-
op(MachineOp.PopFrame);
|
|
1163
|
+
op(MachineOp.PushFrame), op(Op.ConstantReference, handle), op(MachineOp.InvokeStatic, stdlibOperand("cautious-non-dynamic-append")), op(MachineOp.PopFrame);
|
|
1658
1164
|
}
|
|
1659
|
-
});
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
if (isGetFreeComponentOrHelper(expression)) {
|
|
1663
|
-
op(HighLevelResolutionOpcodes.ComponentOrHelper, expression, {
|
|
1165
|
+
});else if (value[0] === opcodes.Call) {
|
|
1166
|
+
let [, expression, positional, named] = value;
|
|
1167
|
+
isGetFreeComponentOrHelper(expression) ? op(HighLevelResolutionOpcodes.ComponentOrHelper, expression, {
|
|
1664
1168
|
ifComponent(component) {
|
|
1665
1169
|
InvokeComponent(op, component, null, positional, hashToArgs(named), null);
|
|
1666
1170
|
},
|
|
1667
1171
|
ifHelper(handle) {
|
|
1668
|
-
op(MachineOp.PushFrame);
|
|
1669
|
-
Call(op, handle, positional, named);
|
|
1670
|
-
op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
|
|
1671
|
-
op(MachineOp.PopFrame);
|
|
1172
|
+
op(MachineOp.PushFrame), Call(op, handle, positional, named), op(MachineOp.InvokeStatic, stdlibOperand("cautious-non-dynamic-append")), op(MachineOp.PopFrame);
|
|
1672
1173
|
}
|
|
1673
|
-
})
|
|
1674
|
-
|
|
1675
|
-
SwitchCases(op, () => {
|
|
1676
|
-
expr(op, expression);
|
|
1677
|
-
op(Op.DynamicContentType);
|
|
1174
|
+
}) : SwitchCases(op, () => {
|
|
1175
|
+
expr(op, expression), op(Op.DynamicContentType);
|
|
1678
1176
|
}, when => {
|
|
1679
1177
|
when(ContentType.Component, () => {
|
|
1680
|
-
op(Op.ResolveCurriedComponent)
|
|
1681
|
-
|
|
1682
|
-
InvokeNonStaticComponent(op, {
|
|
1683
|
-
capabilities: true,
|
|
1178
|
+
op(Op.ResolveCurriedComponent), op(Op.PushDynamicComponentInstance), InvokeNonStaticComponent(op, {
|
|
1179
|
+
capabilities: !0,
|
|
1684
1180
|
elementBlock: null,
|
|
1685
|
-
positional,
|
|
1686
|
-
named,
|
|
1687
|
-
atNames:
|
|
1181
|
+
positional: positional,
|
|
1182
|
+
named: named,
|
|
1183
|
+
atNames: !1,
|
|
1688
1184
|
blocks: namedBlocks(null)
|
|
1689
1185
|
});
|
|
1690
|
-
})
|
|
1691
|
-
when(ContentType.Helper, () => {
|
|
1186
|
+
}), when(ContentType.Helper, () => {
|
|
1692
1187
|
CallDynamic(op, positional, named, () => {
|
|
1693
|
-
op(MachineOp.InvokeStatic, stdlibOperand(
|
|
1188
|
+
op(MachineOp.InvokeStatic, stdlibOperand("cautious-non-dynamic-append"));
|
|
1694
1189
|
});
|
|
1695
1190
|
});
|
|
1696
1191
|
});
|
|
1697
|
-
}
|
|
1698
|
-
} else
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
});
|
|
1705
|
-
STATEMENTS.add(opcodes.
|
|
1706
|
-
|
|
1707
|
-
op(Op.
|
|
1708
|
-
} else {
|
|
1709
|
-
op(MachineOp.PushFrame);
|
|
1710
|
-
expr(op, value);
|
|
1711
|
-
op(MachineOp.InvokeStatic, stdlibOperand('trusting-append'));
|
|
1712
|
-
op(MachineOp.PopFrame);
|
|
1713
|
-
}
|
|
1714
|
-
});
|
|
1715
|
-
STATEMENTS.add(opcodes.Block, (op, [, expr, positional, named, blocks]) => {
|
|
1716
|
-
if (isGetFreeComponent(expr)) {
|
|
1717
|
-
op(HighLevelResolutionOpcodes.Component, expr, component => {
|
|
1718
|
-
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1719
|
-
});
|
|
1720
|
-
} else {
|
|
1721
|
-
InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
|
|
1722
|
-
}
|
|
1723
|
-
});
|
|
1724
|
-
STATEMENTS.add(opcodes.InElement, (op, [, block, guid, destination, insertBefore]) => {
|
|
1725
|
-
ReplayableIf(op, () => {
|
|
1726
|
-
expr(op, guid);
|
|
1727
|
-
if (insertBefore === undefined) {
|
|
1728
|
-
PushPrimitiveReference(op, undefined);
|
|
1729
|
-
} else {
|
|
1730
|
-
expr(op, insertBefore);
|
|
1731
|
-
}
|
|
1732
|
-
expr(op, destination);
|
|
1733
|
-
op(Op.Dup, $sp, 0);
|
|
1734
|
-
return 4;
|
|
1735
|
-
}, () => {
|
|
1736
|
-
op(Op.PushRemoteElement);
|
|
1737
|
-
InvokeStaticBlock(op, block);
|
|
1738
|
-
op(Op.PopRemoteElement);
|
|
1192
|
+
} else op(MachineOp.PushFrame), expr(op, value), op(MachineOp.InvokeStatic, stdlibOperand("cautious-append")), op(MachineOp.PopFrame);
|
|
1193
|
+
} else op(Op.Text, null == value ? "" : String(value));
|
|
1194
|
+
}), STATEMENTS.add(opcodes.TrustingAppend, (op, [, value]) => {
|
|
1195
|
+
Array.isArray(value) ? (op(MachineOp.PushFrame), expr(op, value), op(MachineOp.InvokeStatic, stdlibOperand("trusting-append")), op(MachineOp.PopFrame)) : op(Op.Text, null == value ? "" : String(value));
|
|
1196
|
+
}), STATEMENTS.add(opcodes.Block, (op, [, expr, positional, named, blocks]) => {
|
|
1197
|
+
isGetFreeComponent(expr) ? op(HighLevelResolutionOpcodes.Component, expr, component => {
|
|
1198
|
+
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1199
|
+
}) : InvokeDynamicComponent(op, expr, null, positional, named, blocks, !1, !1);
|
|
1200
|
+
}), 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(Op.Dup, $sp, 0), 4), () => {
|
|
1202
|
+
op(Op.PushRemoteElement), InvokeStaticBlock(op, block), op(Op.PopRemoteElement);
|
|
1739
1203
|
});
|
|
1740
|
-
})
|
|
1741
|
-
STATEMENTS.add(opcodes.If, (op, [, condition, block, inverse]) => ReplayableIf(op, () => {
|
|
1742
|
-
expr(op, condition);
|
|
1743
|
-
op(Op.ToBoolean);
|
|
1744
|
-
return 1;
|
|
1745
|
-
}, () => {
|
|
1204
|
+
}), STATEMENTS.add(opcodes.If, (op, [, condition, block, inverse]) => ReplayableIf(op, () => (expr(op, condition), op(Op.ToBoolean), 1), () => {
|
|
1746
1205
|
InvokeStaticBlock(op, block);
|
|
1747
1206
|
}, inverse ? () => {
|
|
1748
1207
|
InvokeStaticBlock(op, inverse);
|
|
1749
|
-
} :
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
PushPrimitiveReference(op, null);
|
|
1755
|
-
}
|
|
1756
|
-
expr(op, value);
|
|
1757
|
-
return 2;
|
|
1758
|
-
}, () => {
|
|
1759
|
-
op(Op.EnterList, labelOperand('BODY'), labelOperand('ELSE'));
|
|
1760
|
-
op(MachineOp.PushFrame);
|
|
1761
|
-
op(Op.Dup, $fp, 1);
|
|
1762
|
-
op(MachineOp.ReturnTo, labelOperand('ITER'));
|
|
1763
|
-
op(HighLevelBuilderOpcodes.Label, 'ITER');
|
|
1764
|
-
op(Op.Iterate, labelOperand('BREAK'));
|
|
1765
|
-
op(HighLevelBuilderOpcodes.Label, 'BODY');
|
|
1766
|
-
InvokeStaticBlockWithStack(op, block, 2);
|
|
1767
|
-
op(Op.Pop, 2);
|
|
1768
|
-
op(MachineOp.Jump, labelOperand('FINALLY'));
|
|
1769
|
-
op(HighLevelBuilderOpcodes.Label, 'BREAK');
|
|
1770
|
-
op(MachineOp.PopFrame);
|
|
1771
|
-
op(Op.ExitList);
|
|
1772
|
-
op(MachineOp.Jump, labelOperand('FINALLY'));
|
|
1773
|
-
op(HighLevelBuilderOpcodes.Label, 'ELSE');
|
|
1774
|
-
if (inverse) {
|
|
1775
|
-
InvokeStaticBlock(op, inverse);
|
|
1776
|
-
}
|
|
1777
|
-
}));
|
|
1778
|
-
STATEMENTS.add(opcodes.Let, (op, [, positional, block]) => {
|
|
1779
|
-
let count = CompilePositional(op, positional);
|
|
1780
|
-
InvokeStaticBlockWithStack(op, block, count);
|
|
1781
|
-
});
|
|
1782
|
-
STATEMENTS.add(opcodes.WithDynamicVars, (op, [, named, block]) => {
|
|
1208
|
+
} : 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(Op.EnterList, labelOperand("BODY"), labelOperand("ELSE")), op(MachineOp.PushFrame), op(Op.Dup, $fp, 1), op(MachineOp.ReturnTo, labelOperand("ITER")), op(HighLevelBuilderOpcodes.Label, "ITER"), op(Op.Iterate, labelOperand("BREAK")), op(HighLevelBuilderOpcodes.Label, "BODY"), InvokeStaticBlockWithStack(op, block, 2), op(Op.Pop, 2), op(MachineOp.Jump, labelOperand("FINALLY")), op(HighLevelBuilderOpcodes.Label, "BREAK"), op(MachineOp.PopFrame), op(Op.ExitList), op(MachineOp.Jump, labelOperand("FINALLY")), op(HighLevelBuilderOpcodes.Label, "ELSE"), inverse && InvokeStaticBlock(op, inverse);
|
|
1210
|
+
})), STATEMENTS.add(opcodes.Let, (op, [, positional, block]) => {
|
|
1211
|
+
InvokeStaticBlockWithStack(op, block, CompilePositional(op, positional));
|
|
1212
|
+
}), STATEMENTS.add(opcodes.WithDynamicVars, (op, [, named, block]) => {
|
|
1783
1213
|
if (named) {
|
|
1784
1214
|
let [names, expressions] = named;
|
|
1785
|
-
CompilePositional(op, expressions)
|
|
1786
|
-
|
|
1215
|
+
CompilePositional(op, expressions), function (op, names, block) {
|
|
1216
|
+
op(Op.PushDynamicScope), op(Op.BindDynamicScope, names), block(), op(Op.PopDynamicScope);
|
|
1217
|
+
}(op, names, () => {
|
|
1787
1218
|
InvokeStaticBlock(op, block);
|
|
1788
1219
|
});
|
|
1789
|
-
} else
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
if (isGetFreeComponent(expr)) {
|
|
1795
|
-
op(HighLevelResolutionOpcodes.Component, expr, component => {
|
|
1796
|
-
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1797
|
-
});
|
|
1798
|
-
} else {
|
|
1799
|
-
InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
|
|
1800
|
-
}
|
|
1220
|
+
} else InvokeStaticBlock(op, block);
|
|
1221
|
+
}), STATEMENTS.add(opcodes.InvokeComponent, (op, [, expr, positional, named, blocks]) => {
|
|
1222
|
+
isGetFreeComponent(expr) ? op(HighLevelResolutionOpcodes.Component, expr, component => {
|
|
1223
|
+
InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
|
|
1224
|
+
}) : InvokeDynamicComponent(op, expr, null, positional, named, blocks, !1, !1);
|
|
1801
1225
|
});
|
|
1802
|
-
function hashToArgs(hash) {
|
|
1803
|
-
if (hash === null) return null;
|
|
1804
|
-
let names = hash[0].map(key => `@${key}`);
|
|
1805
|
-
return [names, hash[1]];
|
|
1806
|
-
}
|
|
1807
|
-
const PLACEHOLDER_HANDLE = -1;
|
|
1808
1226
|
class CompilableTemplateImpl {
|
|
1809
1227
|
compiled = null;
|
|
1810
1228
|
constructor(statements, meta,
|
|
1811
1229
|
// Part of CompilableTemplate
|
|
1812
1230
|
symbolTable,
|
|
1813
1231
|
// Used for debugging
|
|
1814
|
-
moduleName =
|
|
1815
|
-
this.statements = statements;
|
|
1816
|
-
this.meta = meta;
|
|
1817
|
-
this.symbolTable = symbolTable;
|
|
1818
|
-
this.moduleName = moduleName;
|
|
1232
|
+
moduleName = "plain block") {
|
|
1233
|
+
this.statements = statements, this.meta = meta, this.symbolTable = symbolTable, this.moduleName = moduleName;
|
|
1819
1234
|
}
|
|
1820
|
-
|
|
1821
1235
|
// Part of CompilableTemplate
|
|
1822
1236
|
compile(context) {
|
|
1823
|
-
return
|
|
1237
|
+
return function (compilable, context) {
|
|
1238
|
+
if (null !== compilable.compiled) return compilable.compiled;
|
|
1239
|
+
compilable.compiled = -1;
|
|
1240
|
+
let {
|
|
1241
|
+
statements: statements,
|
|
1242
|
+
meta: meta
|
|
1243
|
+
} = compilable,
|
|
1244
|
+
result = compileStatements(statements, meta, context);
|
|
1245
|
+
return compilable.compiled = result, result;
|
|
1246
|
+
}(this, context);
|
|
1824
1247
|
}
|
|
1825
1248
|
}
|
|
1826
1249
|
function compilable(layout, moduleName) {
|
|
1827
1250
|
let [statements, symbols, hasEval] = layout.block;
|
|
1828
1251
|
return new CompilableTemplateImpl(statements, meta(layout), {
|
|
1829
|
-
symbols,
|
|
1830
|
-
hasEval
|
|
1252
|
+
symbols: symbols,
|
|
1253
|
+
hasEval: hasEval
|
|
1831
1254
|
}, moduleName);
|
|
1832
1255
|
}
|
|
1833
|
-
function maybeCompile(compilable, context) {
|
|
1834
|
-
if (compilable.compiled !== null) return compilable.compiled;
|
|
1835
|
-
compilable.compiled = PLACEHOLDER_HANDLE;
|
|
1836
|
-
let {
|
|
1837
|
-
statements,
|
|
1838
|
-
meta
|
|
1839
|
-
} = compilable;
|
|
1840
|
-
let result = compileStatements(statements, meta, context);
|
|
1841
|
-
compilable.compiled = result;
|
|
1842
|
-
return result;
|
|
1843
|
-
}
|
|
1844
1256
|
function compileStatements(statements, meta, syntaxContext) {
|
|
1845
|
-
let sCompiler = STATEMENTS
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1257
|
+
let sCompiler = STATEMENTS,
|
|
1258
|
+
context = templateCompilationContext(syntaxContext, meta),
|
|
1259
|
+
{
|
|
1260
|
+
encoder: encoder,
|
|
1261
|
+
program: {
|
|
1262
|
+
constants: constants,
|
|
1263
|
+
resolver: resolver
|
|
1264
|
+
}
|
|
1265
|
+
} = context;
|
|
1854
1266
|
function pushOp(...op) {
|
|
1855
1267
|
encodeOp(encoder, constants, resolver, meta, op);
|
|
1856
1268
|
}
|
|
1857
|
-
for (const statement of statements)
|
|
1858
|
-
|
|
1859
|
-
}
|
|
1860
|
-
let handle = context.encoder.commit(meta.size);
|
|
1861
|
-
return handle;
|
|
1862
|
-
}
|
|
1863
|
-
function compilableBlock(block, containing) {
|
|
1864
|
-
return new CompilableTemplateImpl(block[0], containing, {
|
|
1865
|
-
parameters: block[1] || EMPTY_ARRAY
|
|
1866
|
-
});
|
|
1269
|
+
for (const statement of statements) sCompiler.compile(pushOp, statement);
|
|
1270
|
+
return context.encoder.commit(meta.size);
|
|
1867
1271
|
}
|
|
1868
1272
|
const DEFAULT_CAPABILITIES = {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
};
|
|
1273
|
+
dynamicLayout: !0,
|
|
1274
|
+
dynamicTag: !0,
|
|
1275
|
+
prepareArgs: !0,
|
|
1276
|
+
createArgs: !0,
|
|
1277
|
+
attributeHook: !1,
|
|
1278
|
+
elementHook: !1,
|
|
1279
|
+
dynamicScope: !0,
|
|
1280
|
+
createCaller: !1,
|
|
1281
|
+
updateHook: !0,
|
|
1282
|
+
createInstance: !0,
|
|
1283
|
+
wrapped: !1,
|
|
1284
|
+
willDestroy: !1,
|
|
1285
|
+
hasSubOwner: !1
|
|
1286
|
+
},
|
|
1287
|
+
MINIMAL_CAPABILITIES = {
|
|
1288
|
+
dynamicLayout: !1,
|
|
1289
|
+
dynamicTag: !1,
|
|
1290
|
+
prepareArgs: !1,
|
|
1291
|
+
createArgs: !1,
|
|
1292
|
+
attributeHook: !1,
|
|
1293
|
+
elementHook: !1,
|
|
1294
|
+
dynamicScope: !1,
|
|
1295
|
+
createCaller: !1,
|
|
1296
|
+
updateHook: !1,
|
|
1297
|
+
createInstance: !1,
|
|
1298
|
+
wrapped: !1,
|
|
1299
|
+
willDestroy: !1,
|
|
1300
|
+
hasSubOwner: !1
|
|
1301
|
+
};
|
|
1898
1302
|
class WrappedBuilder {
|
|
1899
1303
|
symbolTable;
|
|
1900
1304
|
compiled = null;
|
|
1901
1305
|
attrsBlockNumber;
|
|
1902
1306
|
constructor(layout, moduleName) {
|
|
1903
|
-
this.layout = layout;
|
|
1904
|
-
this.moduleName = moduleName;
|
|
1307
|
+
this.layout = layout, this.moduleName = moduleName;
|
|
1905
1308
|
let {
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1309
|
+
block: block
|
|
1310
|
+
} = layout,
|
|
1311
|
+
[, symbols, hasEval] = block;
|
|
1909
1312
|
symbols = symbols.slice();
|
|
1910
|
-
|
|
1911
1313
|
// ensure ATTRS_BLOCK is always included (only once) in the list of symbols
|
|
1912
|
-
let attrsBlockIndex = symbols.indexOf(
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
this.attrsBlockNumber = attrsBlockIndex + 1;
|
|
1917
|
-
}
|
|
1918
|
-
this.symbolTable = {
|
|
1919
|
-
hasEval,
|
|
1920
|
-
symbols
|
|
1314
|
+
let attrsBlockIndex = symbols.indexOf("&attrs");
|
|
1315
|
+
this.attrsBlockNumber = -1 === attrsBlockIndex ? symbols.push("&attrs") : attrsBlockIndex + 1, this.symbolTable = {
|
|
1316
|
+
hasEval: hasEval,
|
|
1317
|
+
symbols: symbols
|
|
1921
1318
|
};
|
|
1922
1319
|
}
|
|
1923
1320
|
compile(syntax) {
|
|
1924
|
-
if (this.compiled
|
|
1925
|
-
let m = meta(this.layout)
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1321
|
+
if (null !== this.compiled) return this.compiled;
|
|
1322
|
+
let m = meta(this.layout),
|
|
1323
|
+
context = templateCompilationContext(syntax, m),
|
|
1324
|
+
{
|
|
1325
|
+
encoder: encoder,
|
|
1326
|
+
program: {
|
|
1327
|
+
constants: constants,
|
|
1328
|
+
resolver: resolver
|
|
1329
|
+
}
|
|
1330
|
+
} = context;
|
|
1331
|
+
var op, layout, attrsBlockNumber;
|
|
1332
|
+
op = function (...op) {
|
|
1935
1333
|
encodeOp(encoder, constants, resolver, m, op);
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1334
|
+
}, layout = this.layout, attrsBlockNumber = this.attrsBlockNumber, op(HighLevelBuilderOpcodes.StartLabels), function (op, register, block) {
|
|
1335
|
+
op(Op.Fetch, register), block(), op(Op.Load, register);
|
|
1336
|
+
}(op, $s1, () => {
|
|
1337
|
+
op(Op.GetComponentTagName, $s0), op(Op.PrimitiveReference), op(Op.Dup, $sp, 0);
|
|
1338
|
+
}), op(Op.JumpUnless, labelOperand("BODY")), op(Op.Fetch, $s1), op(Op.PutComponentOperations), op(Op.OpenDynamicElement), op(Op.DidCreateElement, $s0), YieldBlock(op, attrsBlockNumber, null), op(Op.FlushElement), op(HighLevelBuilderOpcodes.Label, "BODY"), InvokeStaticBlock(op, [layout.block[0], []]), op(Op.Fetch, $s1), op(Op.JumpUnless, labelOperand("END")), op(Op.CloseElement), op(HighLevelBuilderOpcodes.Label, "END"), op(Op.Load, $s1), op(HighLevelBuilderOpcodes.StopLabels);
|
|
1938
1339
|
let handle = context.encoder.commit(m.size);
|
|
1939
|
-
|
|
1940
|
-
return handle;
|
|
1941
|
-
}
|
|
1942
|
-
this.compiled = handle;
|
|
1943
|
-
return handle;
|
|
1340
|
+
return "number" != typeof handle || (this.compiled = handle), handle;
|
|
1944
1341
|
}
|
|
1945
1342
|
}
|
|
1946
|
-
let clientId = 0
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
};
|
|
1343
|
+
let clientId = 0,
|
|
1344
|
+
templateCacheCounters = {
|
|
1345
|
+
cacheHit: 0,
|
|
1346
|
+
cacheMiss: 0
|
|
1347
|
+
};
|
|
1951
1348
|
|
|
1952
1349
|
// These interfaces are for backwards compatibility, some addons use these intimate APIs
|
|
1953
|
-
|
|
1954
1350
|
/**
|
|
1955
1351
|
* Wraps a template js in a template module to change it into a factory
|
|
1956
1352
|
* that handles lazy parsing the template and to create per env singletons
|
|
@@ -1958,66 +1354,45 @@ let templateCacheCounters = {
|
|
|
1958
1354
|
*/
|
|
1959
1355
|
function templateFactory({
|
|
1960
1356
|
id: templateId,
|
|
1961
|
-
moduleName,
|
|
1962
|
-
block,
|
|
1963
|
-
scope,
|
|
1964
|
-
isStrictMode
|
|
1357
|
+
moduleName: moduleName,
|
|
1358
|
+
block: block,
|
|
1359
|
+
scope: scope,
|
|
1360
|
+
isStrictMode: isStrictMode
|
|
1965
1361
|
}) {
|
|
1966
1362
|
// TODO(template-refactors): This should be removed in the near future, as it
|
|
1967
1363
|
// appears that id is unused. It is currently kept for backwards compat reasons.
|
|
1968
|
-
let
|
|
1969
|
-
|
|
1364
|
+
let parsedBlock,
|
|
1365
|
+
id = templateId || "client-" + clientId++,
|
|
1366
|
+
ownerlessTemplate = null,
|
|
1367
|
+
templateCache = new WeakMap(),
|
|
1368
|
+
factory = owner => {
|
|
1369
|
+
if (void 0 === parsedBlock && (parsedBlock = JSON.parse(block)), void 0 === owner) return null === ownerlessTemplate ? (templateCacheCounters.cacheMiss++, ownerlessTemplate = new TemplateImpl({
|
|
1370
|
+
id: id,
|
|
1371
|
+
block: parsedBlock,
|
|
1372
|
+
moduleName: moduleName,
|
|
1373
|
+
owner: null,
|
|
1374
|
+
scope: scope,
|
|
1375
|
+
isStrictMode: isStrictMode
|
|
1376
|
+
})) : templateCacheCounters.cacheHit++, ownerlessTemplate;
|
|
1377
|
+
let result = templateCache.get(owner);
|
|
1378
|
+
return void 0 === result ? (templateCacheCounters.cacheMiss++, result = new TemplateImpl({
|
|
1379
|
+
id: id,
|
|
1380
|
+
block: parsedBlock,
|
|
1381
|
+
moduleName: moduleName,
|
|
1382
|
+
owner: owner,
|
|
1383
|
+
scope: scope,
|
|
1384
|
+
isStrictMode: isStrictMode
|
|
1385
|
+
}), templateCache.set(owner, result)) : templateCacheCounters.cacheHit++, result;
|
|
1386
|
+
};
|
|
1970
1387
|
// TODO: This caches JSON serialized output once in case a template is
|
|
1971
1388
|
// compiled by multiple owners, but we haven't verified if this is actually
|
|
1972
1389
|
// helpful. We should benchmark this in the future.
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
let factory = owner => {
|
|
1977
|
-
if (parsedBlock === undefined) {
|
|
1978
|
-
parsedBlock = JSON.parse(block);
|
|
1979
|
-
}
|
|
1980
|
-
if (owner === undefined) {
|
|
1981
|
-
if (ownerlessTemplate === null) {
|
|
1982
|
-
templateCacheCounters.cacheMiss++;
|
|
1983
|
-
ownerlessTemplate = new TemplateImpl({
|
|
1984
|
-
id,
|
|
1985
|
-
block: parsedBlock,
|
|
1986
|
-
moduleName,
|
|
1987
|
-
owner: null,
|
|
1988
|
-
scope,
|
|
1989
|
-
isStrictMode
|
|
1990
|
-
});
|
|
1991
|
-
} else {
|
|
1992
|
-
templateCacheCounters.cacheHit++;
|
|
1993
|
-
}
|
|
1994
|
-
return ownerlessTemplate;
|
|
1995
|
-
}
|
|
1996
|
-
let result = templateCache.get(owner);
|
|
1997
|
-
if (result === undefined) {
|
|
1998
|
-
templateCacheCounters.cacheMiss++;
|
|
1999
|
-
result = new TemplateImpl({
|
|
2000
|
-
id,
|
|
2001
|
-
block: parsedBlock,
|
|
2002
|
-
moduleName,
|
|
2003
|
-
owner,
|
|
2004
|
-
scope,
|
|
2005
|
-
isStrictMode
|
|
2006
|
-
});
|
|
2007
|
-
templateCache.set(owner, result);
|
|
2008
|
-
} else {
|
|
2009
|
-
templateCacheCounters.cacheHit++;
|
|
2010
|
-
}
|
|
2011
|
-
return result;
|
|
2012
|
-
};
|
|
2013
|
-
factory.__id = id;
|
|
2014
|
-
factory.__meta = {
|
|
2015
|
-
moduleName
|
|
2016
|
-
};
|
|
2017
|
-
return factory;
|
|
1390
|
+
return factory.__id = id, factory.__meta = {
|
|
1391
|
+
moduleName: moduleName
|
|
1392
|
+
}, factory;
|
|
2018
1393
|
}
|
|
2019
1394
|
class TemplateImpl {
|
|
2020
|
-
result =
|
|
1395
|
+
result = "ok";
|
|
2021
1396
|
layout = null;
|
|
2022
1397
|
wrappedLayout = null;
|
|
2023
1398
|
constructor(parsedLayout) {
|
|
@@ -2029,7 +1404,6 @@ class TemplateImpl {
|
|
|
2029
1404
|
get id() {
|
|
2030
1405
|
return this.parsedLayout.id;
|
|
2031
1406
|
}
|
|
2032
|
-
|
|
2033
1407
|
// TODO(template-refactors): This should be removed in the near future, it is
|
|
2034
1408
|
// only being exposed for backwards compatibility
|
|
2035
1409
|
get referrer() {
|
|
@@ -2039,12 +1413,10 @@ class TemplateImpl {
|
|
|
2039
1413
|
};
|
|
2040
1414
|
}
|
|
2041
1415
|
asLayout() {
|
|
2042
|
-
|
|
2043
|
-
return this.layout = compilable(assign({}, this.parsedLayout), this.moduleName);
|
|
1416
|
+
return this.layout ? this.layout : this.layout = compilable(assign({}, this.parsedLayout), this.moduleName);
|
|
2044
1417
|
}
|
|
2045
1418
|
asWrappedLayout() {
|
|
2046
|
-
|
|
2047
|
-
return this.wrappedLayout = new WrappedBuilder(assign({}, this.parsedLayout), this.moduleName);
|
|
1419
|
+
return this.wrappedLayout ? this.wrappedLayout : this.wrappedLayout = new WrappedBuilder(assign({}, this.parsedLayout), this.moduleName);
|
|
2048
1420
|
}
|
|
2049
1421
|
}
|
|
2050
1422
|
|