ember-source 5.6.0-alpha.2 → 5.6.0-alpha.4

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.
Files changed (55) hide show
  1. package/build-metadata.json +3 -3
  2. package/dist/dependencies/@glimmer/debug.js +1533 -0
  3. package/dist/dependencies/@glimmer/destroyable.js +30 -59
  4. package/dist/dependencies/@glimmer/encoder.js +13 -24
  5. package/dist/dependencies/@glimmer/global-context.js +38 -41
  6. package/dist/dependencies/@glimmer/manager.js +144 -326
  7. package/dist/dependencies/@glimmer/node.js +14 -46
  8. package/dist/dependencies/@glimmer/opcode-compiler.js +1673 -2478
  9. package/dist/dependencies/@glimmer/owner.js +2 -5
  10. package/dist/dependencies/@glimmer/program.js +102 -185
  11. package/dist/dependencies/@glimmer/reference.js +58 -126
  12. package/dist/dependencies/@glimmer/runtime.js +4674 -5639
  13. package/dist/dependencies/@glimmer/util.js +340 -326
  14. package/dist/dependencies/@glimmer/validator.js +160 -217
  15. package/dist/dependencies/@glimmer/vm.js +174 -23
  16. package/dist/dependencies/@glimmer/wire-format.js +91 -34
  17. package/dist/dependencies/@simple-dom/document.js +1 -1
  18. package/dist/dependencies/backburner.js.js +1 -1
  19. package/dist/dependencies/router_js.js +15 -16
  20. package/dist/dependencies/rsvp.js +89 -88
  21. package/dist/ember-template-compiler.js +8574 -8350
  22. package/dist/ember-template-compiler.map +1 -1
  23. package/dist/ember-testing.js +107 -107
  24. package/dist/ember-testing.map +1 -1
  25. package/dist/ember.debug.js +11216 -9634
  26. package/dist/ember.debug.map +1 -1
  27. package/dist/header/license.js +1 -1
  28. package/dist/packages/@ember/-internals/glimmer/index.js +109 -80
  29. package/dist/packages/@ember/-internals/metal/index.js +5 -4
  30. package/dist/packages/@ember/-internals/utils/index.js +3 -4
  31. package/dist/packages/@ember/array/-internals.js +1 -2
  32. package/dist/packages/@ember/debug/lib/inspect.js +0 -1
  33. package/dist/packages/@ember/object/core.js +0 -1
  34. package/dist/packages/@ember/object/mixin.js +1 -2
  35. package/dist/packages/@ember/routing/route.js +23 -101
  36. package/dist/packages/@ember/routing/router.js +25 -84
  37. package/dist/packages/ember/version.js +1 -1
  38. package/dist/packages/ember-babel.js +13 -0
  39. package/docs/data.json +217 -242
  40. package/lib/index.js +1 -5
  41. package/package.json +26 -21
  42. package/types/stable/@ember/-internals/glimmer/index.d.ts +1 -1
  43. package/types/stable/@ember/-internals/glimmer/lib/component-managers/curly.d.ts +4 -4
  44. package/types/stable/@ember/-internals/glimmer/lib/component-managers/mount.d.ts +3 -3
  45. package/types/stable/@ember/-internals/glimmer/lib/component-managers/outlet.d.ts +5 -8
  46. package/types/stable/@ember/-internals/glimmer/lib/component-managers/root.d.ts +3 -3
  47. package/types/stable/@ember/-internals/glimmer/lib/renderer.d.ts +3 -3
  48. package/types/stable/@ember/-internals/glimmer/lib/resolver.d.ts +3 -3
  49. package/types/stable/@ember/-internals/glimmer/lib/syntax/utils.d.ts +3 -2
  50. package/types/stable/@ember/-internals/glimmer/lib/utils/iterator.d.ts +2 -2
  51. package/types/stable/@ember/-internals/glimmer/lib/utils/outlet.d.ts +39 -18
  52. package/types/stable/@ember/-internals/utility-types/index.d.ts +1 -0
  53. package/types/stable/@ember/-internals/views/lib/system/utils.d.ts +4 -3
  54. package/types/stable/@ember/routing/route.d.ts +6 -28
  55. package/dist/dependencies/@glimmer/low-level.js +0 -77
@@ -1,1807 +1,524 @@
1
- import { $v0, $fp, $sp, $s0, $s1, isMachineOp } from '@glimmer/vm';
2
- import { hasCapability } from '@glimmer/manager';
3
- import { assign, dict, debugToString, EMPTY_STRING_ARRAY, EMPTY_ARRAY, isSmallInt, encodeImmediate, Stack, encodeHandle } from '@glimmer/util';
4
- import { assert, deprecate } from '@glimmer/global-context';
1
+ import { EMPTY_STRING_ARRAY, isSmallInt, encodeImmediate, unwrap, reverse, assert as assert$1, Stack, isPresentArray, encodeHandle, expect, assign, dict, enumerate, EMPTY_ARRAY, debugToString } from '@glimmer/util';
2
+ import '@glimmer/debug';
3
+ import { Op, MachineOp, $v0, $fp, $sp, InternalComponentCapabilities, $s0, ContentType, TYPE_SIZE, isMachineOp, MACHINE_MASK, $s1, ARG_SHIFT } from '@glimmer/vm';
5
4
  import { DEBUG } from '@glimmer/env';
6
5
  import { InstructionEncoderImpl } from '@glimmer/encoder';
6
+ import { SexpOpcodes } from '@glimmer/wire-format';
7
+ import { hasCapability } from '@glimmer/manager';
8
+ import { assert, deprecate } from '@glimmer/global-context';
7
9
 
8
- class NamedBlocksImpl {
9
- constructor(blocks) {
10
- this.blocks = blocks;
11
- this.names = blocks ? Object.keys(blocks) : [];
12
- }
13
-
14
- get(name) {
15
- if (!this.blocks) return null;
16
- return this.blocks[name] || null;
17
- }
18
-
19
- has(name) {
20
- let {
21
- blocks
22
- } = this;
23
- return blocks !== null && name in blocks;
24
- }
25
-
26
- with(name, block) {
27
- let {
28
- blocks
29
- } = this;
30
-
31
- if (blocks) {
32
- return new NamedBlocksImpl(assign({}, blocks, {
33
- [name]: block
34
- }));
35
- } else {
36
- return new NamedBlocksImpl({
37
- [name]: block
38
- });
39
- }
40
- }
41
-
42
- get hasAny() {
43
- return this.blocks !== null;
44
- }
45
-
46
- }
47
- const EMPTY_BLOCKS = new NamedBlocksImpl(null);
48
- function namedBlocks(blocks) {
49
- if (blocks === null) {
50
- return EMPTY_BLOCKS;
51
- }
52
-
53
- let out = dict();
54
- let [keys, values] = blocks;
55
-
56
- for (let i = 0; i < keys.length; i++) {
57
- out[keys[i]] = values[i];
58
- }
59
-
60
- return new NamedBlocksImpl(out);
61
- }
62
-
63
- function labelOperand(value) {
64
- return {
65
- type: 1
66
- /* Label */
67
- ,
68
- value
69
- };
70
- }
71
- function evalSymbolsOperand() {
72
- return {
73
- type: 3
74
- /* EvalSymbols */
75
- ,
76
- value: undefined
77
- };
78
- }
79
- function isStrictMode() {
80
- return {
81
- type: 2
82
- /* IsStrictMode */
83
- ,
84
- value: undefined
85
- };
86
- }
87
- function blockOperand(value) {
88
- return {
89
- type: 4
90
- /* Block */
91
- ,
92
- value
93
- };
94
- }
95
- function stdlibOperand(value) {
96
- return {
97
- type: 5
98
- /* StdLib */
99
- ,
100
- value
101
- };
102
- }
103
- function nonSmallIntOperand(value) {
104
- return {
105
- type: 6
106
- /* NonSmallInt */
107
- ,
108
- value
109
- };
110
- }
111
- function symbolTableOperand(value) {
112
- return {
113
- type: 7
114
- /* SymbolTable */
115
- ,
116
- value
117
- };
118
- }
119
- function layoutOperand(value) {
120
- return {
121
- type: 8
122
- /* Layout */
123
- ,
124
- value
125
- };
126
- }
10
+ let debugCompiler;
127
11
 
128
12
  function isGetLikeTuple(opcode) {
129
13
  return Array.isArray(opcode) && opcode.length === 2;
130
14
  }
131
-
132
15
  function makeResolutionTypeVerifier(typeToVerify) {
133
16
  return opcode => {
134
17
  if (!isGetLikeTuple(opcode)) return false;
135
18
  let type = opcode[0];
136
- return type === 31
137
- /* GetStrictFree */
138
- || type === 32
139
- /* GetTemplateSymbol */
140
- || type === typeToVerify;
19
+ return type === SexpOpcodes.GetStrictKeyword || type === SexpOpcodes.GetLexicalSymbol || type === typeToVerify;
141
20
  };
142
21
  }
143
-
144
- const isGetFreeComponent = makeResolutionTypeVerifier(39
145
- /* GetFreeAsComponentHead */
146
- );
147
- const isGetFreeModifier = makeResolutionTypeVerifier(38
148
- /* GetFreeAsModifierHead */
149
- );
150
- const isGetFreeHelper = makeResolutionTypeVerifier(37
151
- /* GetFreeAsHelperHead */
152
- );
153
- const isGetFreeComponentOrHelper = makeResolutionTypeVerifier(35
154
- /* GetFreeAsComponentOrHelperHead */
155
- );
156
- const isGetFreeOptionalComponentOrHelper = makeResolutionTypeVerifier(34
157
- /* GetFreeAsComponentOrHelperHeadOrThisFallback */
158
- );
159
-
22
+ const isGetFreeComponent = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsComponentHead);
23
+ const isGetFreeModifier = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsModifierHead);
24
+ const isGetFreeHelper = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsHelperHead);
25
+ const isGetFreeComponentOrHelper = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsComponentOrHelperHead);
26
+ const isGetFreeOptionalHelper = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsHelperHeadOrThisFallback);
27
+ function isGetFreeDeprecatedHelper(opcode) {
28
+ return Array.isArray(opcode) && opcode[0] === SexpOpcodes.GetFreeAsDeprecatedHelperHeadOrThisFallback;
29
+ }
30
+ const isGetFreeOptionalComponentOrHelper = makeResolutionTypeVerifier(SexpOpcodes.GetFreeAsComponentOrHelperHeadOrThisFallback);
160
31
  function assertResolverInvariants(meta) {
161
32
  if (DEBUG) {
162
33
  if (!meta.upvars) {
163
34
  throw new Error('Attempted to resolve a component, helper, or modifier, but no free vars were found');
164
35
  }
165
-
166
36
  if (!meta.owner) {
167
37
  throw new Error('Attempted to resolve a component, helper, or modifier, but no owner was associated with the template it was being resolved from');
168
38
  }
169
39
  }
170
-
171
40
  return meta;
172
41
  }
42
+
173
43
  /**
174
44
  * <Foo/>
175
45
  * <Foo></Foo>
176
46
  * <Foo @arg={{true}} />
177
47
  */
178
-
179
-
180
- function resolveComponent(resolver, constants, meta, [, expr, then]) {
48
+ function resolveComponent(resolver, constants, meta, _ref) {
49
+ let [, expr, then] = _ref;
50
+ assert$1(isGetFreeComponent(expr), 'Attempted to resolve a component with incorrect opcode');
181
51
  let type = expr[0];
182
-
183
- if (DEBUG && expr[0] === 31
184
- /* GetStrictFree */
185
- ) {
186
- throw new Error(`Attempted to resolve a component in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]]}`);
187
- }
188
-
189
- if (type === 32
190
- /* GetTemplateSymbol */
191
- ) {
192
- let {
193
- scopeValues,
194
- owner
195
- } = meta;
196
- let definition = scopeValues[expr[1]];
197
- then(constants.component(definition, owner));
198
- } else {
52
+ if (DEBUG && expr[0] === SexpOpcodes.GetStrictKeyword) {
53
+ 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}'}`);
54
+ }
55
+ if (type === SexpOpcodes.GetLexicalSymbol) {
56
+ let {
57
+ scopeValues,
58
+ owner
59
+ } = meta;
60
+ let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
61
+ then(constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition')));
62
+ } else {
199
63
  let {
200
64
  upvars,
201
65
  owner
202
66
  } = assertResolverInvariants(meta);
203
- let name = upvars[expr[1]];
67
+ let name = unwrap(upvars[expr[1]]);
204
68
  let definition = resolver.lookupComponent(name, owner);
205
-
206
69
  if (DEBUG && (typeof definition !== 'object' || definition === null)) {
207
70
  throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`);
208
71
  }
209
-
210
72
  then(constants.resolvedComponent(definition, name));
211
73
  }
212
74
  }
75
+
213
76
  /**
214
77
  * (helper)
215
78
  * (helper arg)
216
79
  */
217
-
218
- function resolveHelper(resolver, constants, meta, [, expr, then]) {
80
+ function resolveHelper(resolver, constants, meta, _ref2) {
81
+ let [, expr, then] = _ref2;
82
+ assert$1(isGetFreeHelper(expr), 'Attempted to resolve a helper with incorrect opcode');
219
83
  let type = expr[0];
220
-
221
- if (type === 32
222
- /* GetTemplateSymbol */
223
- ) {
224
- let {
225
- scopeValues
226
- } = meta;
227
- let definition = scopeValues[expr[1]];
228
- then(constants.helper(definition));
229
- } else if (type === 31
230
- /* GetStrictFree */
231
- ) {
232
- then(lookupBuiltInHelper(expr, resolver, meta, constants, 'helper'));
233
- } else {
84
+ if (type === SexpOpcodes.GetLexicalSymbol) {
85
+ let {
86
+ scopeValues
87
+ } = meta;
88
+ let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
89
+ then(constants.helper(definition));
90
+ } else if (type === SexpOpcodes.GetStrictKeyword) {
91
+ then(lookupBuiltInHelper(expr, resolver, meta, constants, 'helper'));
92
+ } else {
234
93
  let {
235
94
  upvars,
236
95
  owner
237
96
  } = assertResolverInvariants(meta);
238
- let name = upvars[expr[1]];
97
+ let name = unwrap(upvars[expr[1]]);
239
98
  let helper = resolver.lookupHelper(name, owner);
240
-
241
99
  if (DEBUG && helper === null) {
242
100
  throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a helper, but nothing was found.`);
243
101
  }
244
-
245
102
  then(constants.helper(helper, name));
246
103
  }
247
104
  }
105
+
248
106
  /**
249
107
  * <div {{modifier}}/>
250
108
  * <div {{modifier arg}}/>
251
109
  * <Foo {{modifier}}/>
252
110
  */
253
-
254
- function resolveModifier(resolver, constants, meta, [, expr, then]) {
111
+ function resolveModifier(resolver, constants, meta, _ref3) {
112
+ let [, expr, then] = _ref3;
113
+ assert$1(isGetFreeModifier(expr), 'Attempted to resolve a modifier with incorrect opcode');
255
114
  let type = expr[0];
256
-
257
- if (type === 32
258
- /* GetTemplateSymbol */
259
- ) {
260
- let {
261
- scopeValues
262
- } = meta;
263
- let definition = scopeValues[expr[1]];
264
- then(constants.modifier(definition));
265
- } else if (type === 31
266
- /* GetStrictFree */
267
- ) {
268
- let {
269
- upvars
270
- } = assertResolverInvariants(meta);
271
- let name = upvars[expr[1]];
272
- let modifier = resolver.lookupBuiltInModifier(name);
273
-
274
- if (DEBUG && modifier === null) {
275
- throw new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`);
276
- }
277
-
278
- then(constants.modifier(modifier, name));
279
- } else {
115
+ if (type === SexpOpcodes.GetLexicalSymbol) {
116
+ let {
117
+ scopeValues
118
+ } = meta;
119
+ let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
120
+ then(constants.modifier(definition));
121
+ } else if (type === SexpOpcodes.GetStrictKeyword) {
122
+ let {
123
+ upvars
124
+ } = assertResolverInvariants(meta);
125
+ let name = unwrap(upvars[expr[1]]);
126
+ let modifier = resolver.lookupBuiltInModifier(name);
127
+ if (DEBUG && modifier === null) {
128
+ throw new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`);
129
+ }
130
+ then(constants.modifier(modifier, name));
131
+ } else {
280
132
  let {
281
133
  upvars,
282
134
  owner
283
135
  } = assertResolverInvariants(meta);
284
- let name = upvars[expr[1]];
136
+ let name = unwrap(upvars[expr[1]]);
285
137
  let modifier = resolver.lookupModifier(name, owner);
286
-
287
138
  if (DEBUG && modifier === null) {
288
139
  throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a modifier, but nothing was found.`);
289
140
  }
290
-
291
141
  then(constants.modifier(modifier, name));
292
142
  }
293
143
  }
144
+
294
145
  /**
295
146
  * {{component-or-helper arg}}
296
147
  */
297
-
298
- function resolveComponentOrHelper(resolver, constants, meta, [, expr, {
299
- ifComponent,
300
- ifHelper
301
- }]) {
148
+ function resolveComponentOrHelper(resolver, constants, meta, _ref4) {
149
+ let [, expr, {
150
+ ifComponent,
151
+ ifHelper
152
+ }] = _ref4;
153
+ assert$1(isGetFreeComponentOrHelper(expr), 'Attempted to resolve a component or helper with incorrect opcode');
302
154
  let type = expr[0];
303
-
304
- if (type === 32
305
- /* GetTemplateSymbol */
306
- ) {
307
- let {
308
- scopeValues,
309
- owner
310
- } = meta;
311
- let definition = scopeValues[expr[1]];
312
- let component = constants.component(definition, owner, true);
313
-
314
- if (component !== null) {
315
- ifComponent(component);
316
- return;
317
- }
318
-
319
- let helper = constants.helper(definition, null, true);
320
-
321
- if (DEBUG && helper === null) {
322
- 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(definition)}`);
323
- }
324
-
325
- ifHelper(helper);
326
- } else if (type === 31
327
- /* GetStrictFree */
328
- ) {
329
- ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'component or helper'));
330
- } else {
155
+ if (type === SexpOpcodes.GetLexicalSymbol) {
156
+ let {
157
+ scopeValues,
158
+ owner
159
+ } = meta;
160
+ let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
161
+ let component = constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition'), true);
162
+ if (component !== null) {
163
+ ifComponent(component);
164
+ return;
165
+ }
166
+ let helper = constants.helper(definition, null, true);
167
+ if (DEBUG && helper === null) {
168
+ 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(definition)}`);
169
+ }
170
+ ifHelper(expect(helper, 'BUG: helper must exist'));
171
+ } else if (type === SexpOpcodes.GetStrictKeyword) {
172
+ ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'component or helper'));
173
+ } else {
331
174
  let {
332
175
  upvars,
333
176
  owner
334
177
  } = assertResolverInvariants(meta);
335
- let name = upvars[expr[1]];
178
+ let name = unwrap(upvars[expr[1]]);
336
179
  let definition = resolver.lookupComponent(name, owner);
337
-
338
180
  if (definition !== null) {
339
181
  ifComponent(constants.resolvedComponent(definition, name));
340
182
  } else {
341
183
  let helper = resolver.lookupHelper(name, owner);
342
-
343
184
  if (DEBUG && helper === null) {
344
185
  throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component or helper, but nothing was found.`);
345
186
  }
346
-
347
187
  ifHelper(constants.helper(helper, name));
348
188
  }
349
189
  }
350
190
  }
191
+
351
192
  /**
352
193
  * <Foo @arg={{helper}}>
353
194
  */
354
-
355
- function resolveOptionalHelper(resolver, constants, meta, [, expr, {
356
- ifHelper
357
- }]) {
195
+ function resolveOptionalHelper(resolver, constants, meta, _ref5) {
196
+ let [, expr, {
197
+ ifHelper
198
+ }] = _ref5;
199
+ assert$1(isGetFreeOptionalHelper(expr) || isGetFreeDeprecatedHelper(expr), 'Attempted to resolve a helper with incorrect opcode');
358
200
  let {
359
201
  upvars,
360
202
  owner
361
203
  } = assertResolverInvariants(meta);
362
- let name = upvars[expr[1]];
204
+ let name = unwrap(upvars[expr[1]]);
363
205
  let helper = resolver.lookupHelper(name, owner);
364
-
365
206
  if (helper) {
366
207
  ifHelper(constants.helper(helper, name), name, meta.moduleName);
367
208
  }
368
209
  }
210
+
369
211
  /**
370
212
  * {{maybeHelperOrComponent}}
371
213
  */
372
-
373
- function resolveOptionalComponentOrHelper(resolver, constants, meta, [, expr, {
374
- ifComponent,
375
- ifHelper,
376
- ifValue
377
- }]) {
214
+ function resolveOptionalComponentOrHelper(resolver, constants, meta, _ref6) {
215
+ let [, expr, {
216
+ ifComponent,
217
+ ifHelper,
218
+ ifValue
219
+ }] = _ref6;
220
+ assert$1(isGetFreeOptionalComponentOrHelper(expr), 'Attempted to resolve an optional component or helper with incorrect opcode');
378
221
  let type = expr[0];
379
-
380
- if (type === 32
381
- /* GetTemplateSymbol */
382
- ) {
383
- let {
384
- scopeValues,
385
- owner
386
- } = meta;
387
- let definition = scopeValues[expr[1]];
388
-
389
- if (typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) {
390
- // The value is not an object, so it can't be a component or helper.
391
- ifValue(constants.value(definition));
392
- return;
393
- }
394
-
395
- let component = constants.component(definition, owner, true);
396
-
397
- if (component !== null) {
398
- ifComponent(component);
399
- return;
400
- }
401
-
402
- let helper = constants.helper(definition, null, true);
403
-
404
- if (helper !== null) {
405
- ifHelper(helper);
406
- return;
407
- }
408
-
222
+ if (type === SexpOpcodes.GetLexicalSymbol) {
223
+ let {
224
+ scopeValues,
225
+ owner
226
+ } = meta;
227
+ let definition = expect(scopeValues, 'BUG: scopeValues must exist if template symbol is used')[expr[1]];
228
+ if (typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) {
229
+ // The value is not an object, so it can't be a component or helper.
409
230
  ifValue(constants.value(definition));
410
- } else if (type === 31
411
- /* GetStrictFree */
412
- ) {
413
- ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'value'));
414
- } else {
231
+ return;
232
+ }
233
+ let component = constants.component(definition, expect(owner, 'BUG: expected owner when resolving component definition'), true);
234
+ if (component !== null) {
235
+ ifComponent(component);
236
+ return;
237
+ }
238
+ let helper = constants.helper(definition, null, true);
239
+ if (helper !== null) {
240
+ ifHelper(helper);
241
+ return;
242
+ }
243
+ ifValue(constants.value(definition));
244
+ } else if (type === SexpOpcodes.GetStrictKeyword) {
245
+ ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'value'));
246
+ } else {
415
247
  let {
416
248
  upvars,
417
249
  owner
418
250
  } = assertResolverInvariants(meta);
419
- let name = upvars[expr[1]];
251
+ let name = unwrap(upvars[expr[1]]);
420
252
  let definition = resolver.lookupComponent(name, owner);
421
-
422
253
  if (definition !== null) {
423
254
  ifComponent(constants.resolvedComponent(definition, name));
424
255
  return;
425
256
  }
426
-
427
257
  let helper = resolver.lookupHelper(name, owner);
428
-
429
258
  if (helper !== null) {
430
259
  ifHelper(constants.helper(helper, name));
431
260
  }
432
261
  }
433
262
  }
434
-
435
263
  function lookupBuiltInHelper(expr, resolver, meta, constants, type) {
436
264
  let {
437
265
  upvars
438
266
  } = assertResolverInvariants(meta);
439
- let name = upvars[expr[1]];
267
+ let name = unwrap(upvars[expr[1]]);
440
268
  let helper = resolver.lookupBuiltInHelper(name);
441
-
442
269
  if (DEBUG && helper === null) {
443
270
  // Keyword helper did not exist, which means that we're attempting to use a
444
271
  // value of some kind that is not in scope
445
- throw new Error(`Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]]}`);
272
+ throw 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}'}`);
446
273
  }
447
-
448
274
  return constants.helper(helper, name);
449
275
  }
450
276
 
451
- class Compilers {
452
- constructor() {
453
- this.names = {};
454
- this.funcs = [];
455
- }
456
-
457
- add(name, func) {
458
- this.names[name] = this.funcs.push(func) - 1;
459
- }
460
-
461
- compile(op, sexp) {
462
- let name = sexp[0];
463
- let index = this.names[name];
464
- let func = this.funcs[index];
465
- func(op, sexp);
466
- }
277
+ const HighLevelResolutionOpcodes = {
278
+ Modifier: 1003,
279
+ Component: 1004,
280
+ Helper: 1005,
281
+ OptionalHelper: 1006,
282
+ ComponentOrHelper: 1007,
283
+ OptionalComponentOrHelper: 1008,
284
+ Free: 1009,
285
+ Local: 1010,
286
+ TemplateLocal: 1011
287
+ };
288
+ const HighLevelBuilderOpcodes = {
289
+ Label: 1000,
290
+ StartLabels: 1001,
291
+ StopLabels: 1002,
292
+ Start: 1000,
293
+ End: 1002
294
+ };
467
295
 
296
+ const HighLevelOperands = {
297
+ Label: 1,
298
+ IsStrictMode: 2,
299
+ DebugSymbols: 3,
300
+ Block: 4,
301
+ StdLib: 5,
302
+ NonSmallInt: 6,
303
+ SymbolTable: 7,
304
+ Layout: 8
305
+ };
306
+ function labelOperand(value) {
307
+ return {
308
+ type: HighLevelOperands.Label,
309
+ value
310
+ };
311
+ }
312
+ function debugSymbolsOperand() {
313
+ return {
314
+ type: HighLevelOperands.DebugSymbols,
315
+ value: undefined
316
+ };
317
+ }
318
+ function isStrictMode() {
319
+ return {
320
+ type: HighLevelOperands.IsStrictMode,
321
+ value: undefined
322
+ };
323
+ }
324
+ function blockOperand(value) {
325
+ return {
326
+ type: HighLevelOperands.Block,
327
+ value
328
+ };
329
+ }
330
+ function stdlibOperand(value) {
331
+ return {
332
+ type: HighLevelOperands.StdLib,
333
+ value
334
+ };
335
+ }
336
+ function nonSmallIntOperand(value) {
337
+ assert$1(!isSmallInt(value), 'Attempted to make a operand for an int that was not a small int, you should encode this as an immediate');
338
+ return {
339
+ type: HighLevelOperands.NonSmallInt,
340
+ value
341
+ };
342
+ }
343
+ function symbolTableOperand(value) {
344
+ return {
345
+ type: HighLevelOperands.SymbolTable,
346
+ value
347
+ };
348
+ }
349
+ function layoutOperand(value) {
350
+ return {
351
+ type: HighLevelOperands.Layout,
352
+ value
353
+ };
468
354
  }
469
355
 
470
- const EXPRESSIONS = new Compilers();
471
- EXPRESSIONS.add(29
472
- /* Concat */
473
- , (op, [, parts]) => {
474
- for (let part of parts) {
475
- expr(op, part);
356
+ class Labels {
357
+ labels = dict();
358
+ targets = [];
359
+ label(name, index) {
360
+ this.labels[name] = index;
476
361
  }
477
-
478
- op(27
479
- /* Concat */
480
- , parts.length);
481
- });
482
- EXPRESSIONS.add(28
483
- /* Call */
484
- , (op, [, expression, positional, named]) => {
485
- if (isGetFreeHelper(expression)) {
486
- op(1005
487
- /* ResolveHelper */
488
- , expression, handle => {
489
- Call(op, handle, positional, named);
490
- });
491
- } else {
492
- expr(op, expression);
493
- CallDynamic(op, positional, named);
494
- }
495
- });
496
- EXPRESSIONS.add(50
497
- /* Curry */
498
- , (op, [, expr, type, positional, named]) => {
499
- Curry(op, type, expr, positional, named);
500
- });
501
- EXPRESSIONS.add(30
502
- /* GetSymbol */
503
- , (op, [, sym, path]) => {
504
- op(21
505
- /* GetVariable */
506
- , sym);
507
- withPath(op, path);
508
- });
509
- EXPRESSIONS.add(32
510
- /* GetTemplateSymbol */
511
- , (op, [, sym, path]) => {
512
- op(1011
513
- /* ResolveTemplateLocal */
514
- , sym, handle => {
515
- op(29
516
- /* ConstantReference */
517
- , handle);
518
- withPath(op, path);
519
- });
520
- });
521
- EXPRESSIONS.add(31
522
- /* GetStrictFree */
523
- , (op, [, sym, _path]) => {
524
- op(1009
525
- /* ResolveFree */
526
- , sym, _handle => {// TODO: Implement in strict mode
527
- });
528
- });
529
- EXPRESSIONS.add(34
530
- /* GetFreeAsComponentOrHelperHeadOrThisFallback */
531
- , () => {
532
- // TODO: The logic for this opcode currently exists in STATEMENTS.Append, since
533
- // we want different wrapping logic depending on if we are invoking a component,
534
- // helper, or {{this}} fallback. Eventually we fix the opcodes so that we can
535
- // traverse the subexpression tree like normal in this location.
536
- throw new Error('unimplemented opcode');
537
- });
538
- EXPRESSIONS.add(36
539
- /* GetFreeAsHelperHeadOrThisFallback */
540
- , (op, expr) => {
541
- // <div id={{baz}}>
542
- op(1010
543
- /* ResolveLocal */
544
- , expr[1], _name => {
545
- op(1006
546
- /* ResolveOptionalHelper */
547
- , expr, {
548
- ifHelper: handle => {
549
- Call(op, handle, null, null);
550
- }
551
- });
552
- });
553
- });
554
- EXPRESSIONS.add(99
555
- /* GetFreeAsDeprecatedHelperHeadOrThisFallback */
556
- , (op, expr) => {
557
- // <Foo @bar={{baz}}>
558
- op(1010
559
- /* ResolveLocal */
560
- , expr[1], _name => {
561
- op(1006
562
- /* ResolveOptionalHelper */
563
- , expr, {
564
- ifHelper: (handle, name, moduleName) => {
565
- assert(expr[2] && expr[2].length === 1, '[BUG] Missing argument name');
566
- let arg = expr[2][0];
567
- deprecate(`The \`${name}\` helper was used in the \`${moduleName}\` template as \`${arg}={{${name}}}\`. ` + `This is ambigious between wanting the \`${arg}\` argument to be the \`${name}\` helper itself, ` + `or the result of invoking the \`${name}\` helper (current behavior). ` + `This implicit invocation behavior has been deprecated.\n\n` + `Instead, please explicitly invoke the helper with parenthesis, i.e. \`${arg}={{(${name})}}\`.\n\n` + `Note: the parenthesis are only required in this exact scenario where an ambiguity is present – where ` + `\`${name}\` referes to a global helper (as opposed to a local variable), AND ` + `the \`${name}\` helper invocation does not take any arguments, AND ` + `this occurs in a named argument position of a component invocation.\n\n` + `We expect this combination to be quite rare, as most helpers require at least one argument. ` + `There is no need to refactor helper invocations in cases where this deprecation was not triggered.`, false, {
568
- id: 'argument-less-helper-paren-less-invocation'
569
- });
570
- Call(op, handle, null, null);
571
- }
572
- });
573
- });
574
- });
575
-
576
- function withPath(op, path) {
577
- if (path === undefined || path.length === 0) return;
578
-
579
- for (let i = 0; i < path.length; i++) {
580
- op(22
581
- /* GetProperty */
582
- , path[i]);
583
- }
584
- }
585
-
586
- EXPRESSIONS.add(27
587
- /* Undefined */
588
- , op => PushPrimitiveReference(op, undefined));
589
- EXPRESSIONS.add(48
590
- /* HasBlock */
591
- , (op, [, block]) => {
592
- expr(op, block);
593
- op(25
594
- /* HasBlock */
595
- );
596
- });
597
- EXPRESSIONS.add(49
598
- /* HasBlockParams */
599
- , (op, [, block]) => {
600
- expr(op, block);
601
- op(24
602
- /* SpreadBlock */
603
- );
604
- op(61
605
- /* CompileBlock */
606
- );
607
- op(26
608
- /* HasBlockParams */
609
- );
610
- });
611
- EXPRESSIONS.add(52
612
- /* IfInline */
613
- , (op, [, condition, truthy, falsy]) => {
614
- // Push in reverse order
615
- expr(op, falsy);
616
- expr(op, truthy);
617
- expr(op, condition);
618
- op(109
619
- /* IfInline */
620
- );
621
- });
622
- EXPRESSIONS.add(51
623
- /* Not */
624
- , (op, [, value]) => {
625
- expr(op, value);
626
- op(110
627
- /* Not */
628
- );
629
- });
630
- EXPRESSIONS.add(53
631
- /* GetDynamicVar */
632
- , (op, [, expression]) => {
633
- expr(op, expression);
634
- op(111
635
- /* GetDynamicVar */
636
- );
637
- });
638
- EXPRESSIONS.add(54
639
- /* Log */
640
- , (op, [, positional]) => {
641
- op(0
642
- /* PushFrame */
643
- );
644
- SimpleArgs(op, positional, null, false);
645
- op(112
646
- /* Log */
647
- );
648
- op(1
649
- /* PopFrame */
650
- );
651
- op(36
652
- /* Fetch */
653
- , $v0);
654
- });
655
-
656
- function expr(op, expression) {
657
- if (Array.isArray(expression)) {
658
- EXPRESSIONS.compile(op, expression);
659
- } else {
660
- PushPrimitive(op, expression);
661
- op(31
662
- /* PrimitiveReference */
663
- );
664
- }
665
- }
666
-
667
- /**
668
- * Compile arguments, pushing an Arguments object onto the stack.
669
- *
670
- * @param args.params
671
- * @param args.hash
672
- * @param args.blocks
673
- * @param args.atNames
674
- */
675
-
676
- function CompileArgs(op, positional, named, blocks, atNames) {
677
- let blockNames = blocks.names;
678
-
679
- for (let i = 0; i < blockNames.length; i++) {
680
- PushYieldableBlock(op, blocks.get(blockNames[i]));
681
- }
682
-
683
- let count = CompilePositional(op, positional);
684
- let flags = count << 4;
685
- if (atNames) flags |= 0b1000;
686
-
687
- if (blocks) {
688
- flags |= 0b111;
689
- }
690
-
691
- let names = EMPTY_ARRAY;
692
-
693
- if (named) {
694
- names = named[0];
695
- let val = named[1];
696
-
697
- for (let i = 0; i < val.length; i++) {
698
- expr(op, val[i]);
699
- }
700
- }
701
-
702
- op(82
703
- /* PushArgs */
704
- , names, blockNames, flags);
705
- }
706
- function SimpleArgs(op, positional, named, atNames) {
707
- if (positional === null && named === null) {
708
- op(83
709
- /* PushEmptyArgs */
710
- );
711
- return;
712
- }
713
-
714
- let count = CompilePositional(op, positional);
715
- let flags = count << 4;
716
- if (atNames) flags |= 0b1000;
717
- let names = EMPTY_STRING_ARRAY;
718
-
719
- if (named) {
720
- names = named[0];
721
- let val = named[1];
722
-
723
- for (let i = 0; i < val.length; i++) {
724
- expr(op, val[i]);
725
- }
726
- }
727
-
728
- op(82
729
- /* PushArgs */
730
- , names, EMPTY_STRING_ARRAY, flags);
731
- }
732
- /**
733
- * Compile an optional list of positional arguments, which pushes each argument
734
- * onto the stack and returns the number of parameters compiled
735
- *
736
- * @param positional an optional list of positional arguments
737
- */
738
-
739
- function CompilePositional(op, positional) {
740
- if (positional === null) return 0;
741
-
742
- for (let i = 0; i < positional.length; i++) {
743
- expr(op, positional[i]);
744
- }
745
-
746
- return positional.length;
747
- }
748
- function meta(layout) {
749
- var _a, _b;
750
-
751
- let [, symbols,, upvars] = layout.block;
752
- return {
753
- evalSymbols: evalSymbols(layout),
754
- upvars: upvars,
755
- scopeValues: (_b = (_a = layout.scope) === null || _a === void 0 ? void 0 : _a.call(layout)) !== null && _b !== void 0 ? _b : null,
756
- isStrictMode: layout.isStrictMode,
757
- moduleName: layout.moduleName,
758
- owner: layout.owner,
759
- size: symbols.length
760
- };
761
- }
762
- function evalSymbols(layout) {
763
- let {
764
- block
765
- } = layout;
766
- let [, symbols, hasEval] = block;
767
- return hasEval ? symbols : null;
768
- }
769
-
770
- /**
771
- * Push a reference onto the stack corresponding to a statically known primitive
772
- * @param value A JavaScript primitive (undefined, null, boolean, number or string)
773
- */
774
-
775
- function PushPrimitiveReference(op, value) {
776
- PushPrimitive(op, value);
777
- op(31
778
- /* PrimitiveReference */
779
- );
780
- }
781
- /**
782
- * Push an encoded representation of a JavaScript primitive on the stack
783
- *
784
- * @param value A JavaScript primitive (undefined, null, boolean, number or string)
785
- */
786
-
787
- function PushPrimitive(op, primitive) {
788
- let p = primitive;
789
-
790
- if (typeof p === 'number') {
791
- p = isSmallInt(p) ? encodeImmediate(p) : nonSmallIntOperand(p);
792
- }
793
-
794
- op(30
795
- /* Primitive */
796
- , p);
797
- }
798
- /**
799
- * Invoke a foreign function (a "helper") based on a statically known handle
800
- *
801
- * @param op The op creation function
802
- * @param handle A handle
803
- * @param positional An optional list of expressions to compile
804
- * @param named An optional list of named arguments (name + expression) to compile
805
- */
806
-
807
- function Call(op, handle, positional, named) {
808
- op(0
809
- /* PushFrame */
810
- );
811
- SimpleArgs(op, positional, named, false);
812
- op(16
813
- /* Helper */
814
- , handle);
815
- op(1
816
- /* PopFrame */
817
- );
818
- op(36
819
- /* Fetch */
820
- , $v0);
821
- }
822
- /**
823
- * Invoke a foreign function (a "helper") based on a dynamically loaded definition
824
- *
825
- * @param op The op creation function
826
- * @param positional An optional list of expressions to compile
827
- * @param named An optional list of named arguments (name + expression) to compile
828
- */
829
-
830
- function CallDynamic(op, positional, named, append) {
831
- op(0
832
- /* PushFrame */
833
- );
834
- SimpleArgs(op, positional, named, false);
835
- op(33
836
- /* Dup */
837
- , $fp, 1);
838
- op(107
839
- /* DynamicHelper */
840
- );
841
-
842
- if (append) {
843
- op(36
844
- /* Fetch */
845
- , $v0);
846
- append();
847
- op(1
848
- /* PopFrame */
849
- );
850
- op(34
851
- /* Pop */
852
- , 1);
853
- } else {
854
- op(1
855
- /* PopFrame */
856
- );
857
- op(34
858
- /* Pop */
859
- , 1);
860
- op(36
861
- /* Fetch */
862
- , $v0);
863
- }
864
- }
865
- /**
866
- * Evaluate statements in the context of new dynamic scope entries. Move entries from the
867
- * stack into named entries in the dynamic scope, then evaluate the statements, then pop
868
- * the dynamic scope
869
- *
870
- * @param names a list of dynamic scope names
871
- * @param block a function that returns a list of statements to evaluate
872
- */
873
-
874
- function DynamicScope(op, names, block) {
875
- op(59
876
- /* PushDynamicScope */
877
- );
878
- op(58
879
- /* BindDynamicScope */
880
- , names);
881
- block();
882
- op(60
883
- /* PopDynamicScope */
884
- );
885
- }
886
- function Curry(op, type, definition, positional, named) {
887
- op(0
888
- /* PushFrame */
889
- );
890
- SimpleArgs(op, positional, named, false);
891
- op(86
892
- /* CaptureArgs */
893
- );
894
- expr(op, definition);
895
- op(77
896
- /* Curry */
897
- , type, isStrictMode());
898
- op(1
899
- /* PopFrame */
900
- );
901
- op(36
902
- /* Fetch */
903
- , $v0);
904
- }
905
-
906
- /**
907
- * Yield to a block located at a particular symbol location.
908
- *
909
- * @param to the symbol containing the block to yield to
910
- * @param params optional block parameters to yield to the block
911
- */
912
-
913
- function YieldBlock(op, to, positional) {
914
- SimpleArgs(op, positional, null, true);
915
- op(23
916
- /* GetBlock */
917
- , to);
918
- op(24
919
- /* SpreadBlock */
920
- );
921
- op(61
922
- /* CompileBlock */
923
- );
924
- op(64
925
- /* InvokeYield */
926
- );
927
- op(40
928
- /* PopScope */
929
- );
930
- op(1
931
- /* PopFrame */
932
- );
933
- }
934
- /**
935
- * Push an (optional) yieldable block onto the stack. The yieldable block must be known
936
- * statically at compile time.
937
- *
938
- * @param block An optional Compilable block
939
- */
940
-
941
- function PushYieldableBlock(op, block) {
942
- PushSymbolTable(op, block && block[1]);
943
- op(62
944
- /* PushBlockScope */
945
- );
946
- PushCompilable(op, block);
947
- }
948
- /**
949
- * Invoke a block that is known statically at compile time.
950
- *
951
- * @param block a Compilable block
952
- */
953
-
954
- function InvokeStaticBlock(op, block) {
955
- op(0
956
- /* PushFrame */
957
- );
958
- PushCompilable(op, block);
959
- op(61
960
- /* CompileBlock */
961
- );
962
- op(2
963
- /* InvokeVirtual */
964
- );
965
- op(1
966
- /* PopFrame */
967
- );
968
- }
969
- /**
970
- * Invoke a static block, preserving some number of stack entries for use in
971
- * updating.
972
- *
973
- * @param block A compilable block
974
- * @param callerCount A number of stack entries to preserve
975
- */
976
-
977
- function InvokeStaticBlockWithStack(op, block, callerCount) {
978
- let parameters = block[1];
979
- let calleeCount = parameters.length;
980
- let count = Math.min(callerCount, calleeCount);
981
-
982
- if (count === 0) {
983
- InvokeStaticBlock(op, block);
984
- return;
362
+ target(at, target) {
363
+ this.targets.push({
364
+ at,
365
+ target
366
+ });
985
367
  }
986
-
987
- op(0
988
- /* PushFrame */
989
- );
990
-
991
- if (count) {
992
- op(39
993
- /* ChildScope */
994
- );
995
-
996
- for (let i = 0; i < count; i++) {
997
- op(33
998
- /* Dup */
999
- , $fp, callerCount - i);
1000
- op(19
1001
- /* SetVariable */
1002
- , parameters[i]);
368
+ patch(heap) {
369
+ let {
370
+ targets,
371
+ labels
372
+ } = this;
373
+ for (const {
374
+ at,
375
+ target
376
+ } of targets) {
377
+ let address = labels[target] - at;
378
+ assert$1(heap.getbyaddr(at) === -1, 'Expected heap to contain a placeholder, but it did not');
379
+ heap.setbyaddr(at, address);
1003
380
  }
1004
381
  }
1005
-
1006
- PushCompilable(op, block);
1007
- op(61
1008
- /* CompileBlock */
1009
- );
1010
- op(2
1011
- /* InvokeVirtual */
1012
- );
1013
-
1014
- if (count) {
1015
- op(40
1016
- /* PopScope */
1017
- );
1018
- }
1019
-
1020
- op(1
1021
- /* PopFrame */
1022
- );
1023
- }
1024
- function PushSymbolTable(op, parameters) {
1025
- if (parameters !== null) {
1026
- op(63
1027
- /* PushSymbolTable */
1028
- , symbolTableOperand({
1029
- parameters
1030
- }));
1031
- } else {
1032
- PushPrimitive(op, null);
1033
- }
1034
382
  }
1035
- function PushCompilable(op, _block) {
1036
- if (_block === null) {
1037
- PushPrimitive(op, null);
383
+ function encodeOp(encoder, constants, resolver, meta, op) {
384
+ if (isBuilderOpcode(op[0])) {
385
+ let [type, ...operands] = op;
386
+ encoder.push(constants, type, ...operands);
1038
387
  } else {
1039
- op(28
1040
- /* Constant */
1041
- , blockOperand(_block));
1042
- }
1043
- }
1044
-
1045
- function SwitchCases(op, bootstrap, callback) {
1046
- // Setup the switch DSL
1047
- let clauses = [];
1048
- let count = 0;
1049
-
1050
- function when(match, callback) {
1051
- clauses.push({
1052
- match,
1053
- callback,
1054
- label: `CLAUSE${count++}`
1055
- });
1056
- } // Call the callback
1057
-
1058
-
1059
- callback(when); // Emit the opcodes for the switch
1060
-
1061
- op(69
1062
- /* Enter */
1063
- , 1);
1064
- bootstrap();
1065
- op(1001
1066
- /* StartLabels */
1067
- ); // First, emit the jump opcodes. We don't need a jump for the last
1068
- // opcode, since it bleeds directly into its clause.
1069
-
1070
- for (let clause of clauses.slice(0, -1)) {
1071
- op(67
1072
- /* JumpEq */
1073
- , labelOperand(clause.label), clause.match);
1074
- } // Enumerate the clauses in reverse order. Earlier matches will
1075
- // require fewer checks.
1076
-
1077
-
1078
- for (let i = clauses.length - 1; i >= 0; i--) {
1079
- let clause = clauses[i];
1080
- op(1000
1081
- /* Label */
1082
- , clause.label);
1083
- op(34
1084
- /* Pop */
1085
- , 1);
1086
- clause.callback(); // The first match is special: it is placed directly before the END
1087
- // label, so no additional jump is needed at the end of it.
1088
-
1089
- if (i !== 0) {
1090
- op(4
1091
- /* Jump */
1092
- , labelOperand('END'));
1093
- }
1094
- }
1095
-
1096
- op(1000
1097
- /* Label */
1098
- , 'END');
1099
- op(1002
1100
- /* StopLabels */
1101
- );
1102
- op(70
1103
- /* Exit */
1104
- );
1105
- }
1106
- /**
1107
- * A convenience for pushing some arguments on the stack and
1108
- * running some code if the code needs to be re-executed during
1109
- * updating execution if some of the arguments have changed.
1110
- *
1111
- * # Initial Execution
1112
- *
1113
- * The `args` function should push zero or more arguments onto
1114
- * the stack and return the number of arguments pushed.
1115
- *
1116
- * The `body` function provides the instructions to execute both
1117
- * during initial execution and during updating execution.
1118
- *
1119
- * Internally, this function starts by pushing a new frame, so
1120
- * that the body can return and sets the return point ($ra) to
1121
- * the ENDINITIAL label.
1122
- *
1123
- * It then executes the `args` function, which adds instructions
1124
- * responsible for pushing the arguments for the block to the
1125
- * stack. These arguments will be restored to the stack before
1126
- * updating execution.
1127
- *
1128
- * Next, it adds the Enter opcode, which marks the current position
1129
- * in the DOM, and remembers the current $pc (the next instruction)
1130
- * as the first instruction to execute during updating execution.
1131
- *
1132
- * Next, it runs `body`, which adds the opcodes that should
1133
- * execute both during initial execution and during updating execution.
1134
- * If the `body` wishes to finish early, it should Jump to the
1135
- * `FINALLY` label.
1136
- *
1137
- * Next, it adds the FINALLY label, followed by:
1138
- *
1139
- * - the Exit opcode, which finalizes the marked DOM started by the
1140
- * Enter opcode.
1141
- * - the Return opcode, which returns to the current return point
1142
- * ($ra).
1143
- *
1144
- * Finally, it adds the ENDINITIAL label followed by the PopFrame
1145
- * instruction, which restores $fp, $sp and $ra.
1146
- *
1147
- * # Updating Execution
1148
- *
1149
- * Updating execution for this `replayable` occurs if the `body` added an
1150
- * assertion, via one of the `JumpIf`, `JumpUnless` or `AssertSame` opcodes.
1151
- *
1152
- * If, during updating executon, the assertion fails, the initial VM is
1153
- * restored, and the stored arguments are pushed onto the stack. The DOM
1154
- * between the starting and ending markers is cleared, and the VM's cursor
1155
- * is set to the area just cleared.
1156
- *
1157
- * The return point ($ra) is set to -1, the exit instruction.
1158
- *
1159
- * Finally, the $pc is set to to the instruction saved off by the
1160
- * Enter opcode during initial execution, and execution proceeds as
1161
- * usual.
1162
- *
1163
- * The only difference is that when a `Return` instruction is
1164
- * encountered, the program jumps to -1 rather than the END label,
1165
- * and the PopFrame opcode is not needed.
1166
- */
1167
-
1168
- function Replayable(op, args, body) {
1169
- // Start a new label frame, to give END and RETURN
1170
- // a unique meaning.
1171
- op(1001
1172
- /* StartLabels */
1173
- );
1174
- op(0
1175
- /* PushFrame */
1176
- ); // If the body invokes a block, its return will return to
1177
- // END. Otherwise, the return in RETURN will return to END.
1178
-
1179
- op(6
1180
- /* ReturnTo */
1181
- , labelOperand('ENDINITIAL')); // Push the arguments onto the stack. The args() function
1182
- // tells us how many stack elements to retain for re-execution
1183
- // when updating.
1184
-
1185
- let count = args(); // Start a new updating closure, remembering `count` elements
1186
- // from the stack. Everything after this point, and before END,
1187
- // will execute both initially and to update the block.
1188
- //
1189
- // The enter and exit opcodes also track the area of the DOM
1190
- // associated with this block. If an assertion inside the block
1191
- // fails (for example, the test value changes from true to false
1192
- // in an #if), the DOM is cleared and the program is re-executed,
1193
- // restoring `count` elements to the stack and executing the
1194
- // instructions between the enter and exit.
1195
-
1196
- op(69
1197
- /* Enter */
1198
- , count); // Evaluate the body of the block. The body of the block may
1199
- // return, which will jump execution to END during initial
1200
- // execution, and exit the updating routine.
1201
-
1202
- body(); // All execution paths in the body should run the FINALLY once
1203
- // they are done. It is executed both during initial execution
1204
- // and during updating execution.
1205
-
1206
- op(1000
1207
- /* Label */
1208
- , 'FINALLY'); // Finalize the DOM.
1209
-
1210
- op(70
1211
- /* Exit */
1212
- ); // In initial execution, this is a noop: it returns to the
1213
- // immediately following opcode. In updating execution, this
1214
- // exits the updating routine.
1215
-
1216
- op(5
1217
- /* Return */
1218
- ); // Cleanup code for the block. Runs on initial execution
1219
- // but not on updating.
1220
-
1221
- op(1000
1222
- /* Label */
1223
- , 'ENDINITIAL');
1224
- op(1
1225
- /* PopFrame */
1226
- );
1227
- op(1002
1228
- /* StopLabels */
1229
- );
1230
- }
1231
- /**
1232
- * A specialized version of the `replayable` convenience that allows the
1233
- * caller to provide different code based upon whether the item at
1234
- * the top of the stack is true or false.
1235
- *
1236
- * As in `replayable`, the `ifTrue` and `ifFalse` code can invoke `return`.
1237
- *
1238
- * During the initial execution, a `return` will continue execution
1239
- * in the cleanup code, which finalizes the current DOM block and pops
1240
- * the current frame.
1241
- *
1242
- * During the updating execution, a `return` will exit the updating
1243
- * routine, as it can reuse the DOM block and is always only a single
1244
- * frame deep.
1245
- */
1246
-
1247
- function ReplayableIf(op, args, ifTrue, ifFalse) {
1248
- return Replayable(op, args, () => {
1249
- // If the conditional is false, jump to the ELSE label.
1250
- op(66
1251
- /* JumpUnless */
1252
- , labelOperand('ELSE')); // Otherwise, execute the code associated with the true branch.
1253
-
1254
- ifTrue(); // We're done, so return. In the initial execution, this runs
1255
- // the cleanup code. In the updating VM, it exits the updating
1256
- // routine.
1257
-
1258
- op(4
1259
- /* Jump */
1260
- , labelOperand('FINALLY'));
1261
- op(1000
1262
- /* Label */
1263
- , 'ELSE'); // If the conditional is false, and code associatied ith the
1264
- // false branch was provided, execute it. If there was no code
1265
- // associated with the false branch, jumping to the else statement
1266
- // has no other behavior.
1267
-
1268
- if (ifFalse !== undefined) {
1269
- ifFalse();
388
+ switch (op[0]) {
389
+ case HighLevelBuilderOpcodes.Label:
390
+ return encoder.label(op[1]);
391
+ case HighLevelBuilderOpcodes.StartLabels:
392
+ return encoder.startLabels();
393
+ case HighLevelBuilderOpcodes.StopLabels:
394
+ return encoder.stopLabels();
395
+ case HighLevelResolutionOpcodes.Component:
396
+ return resolveComponent(resolver, constants, meta, op);
397
+ case HighLevelResolutionOpcodes.Modifier:
398
+ return resolveModifier(resolver, constants, meta, op);
399
+ case HighLevelResolutionOpcodes.Helper:
400
+ return resolveHelper(resolver, constants, meta, op);
401
+ case HighLevelResolutionOpcodes.ComponentOrHelper:
402
+ return resolveComponentOrHelper(resolver, constants, meta, op);
403
+ case HighLevelResolutionOpcodes.OptionalHelper:
404
+ return resolveOptionalHelper(resolver, constants, meta, op);
405
+ case HighLevelResolutionOpcodes.OptionalComponentOrHelper:
406
+ return resolveOptionalComponentOrHelper(resolver, constants, meta, op);
407
+ case HighLevelResolutionOpcodes.Local:
408
+ {
409
+ let freeVar = op[1];
410
+ let name = expect(meta.upvars, 'BUG: attempted to resolve value but no upvars found')[freeVar];
411
+ let andThen = op[2];
412
+ andThen(name, meta.moduleName);
413
+ break;
414
+ }
415
+ case HighLevelResolutionOpcodes.TemplateLocal:
416
+ {
417
+ let [, valueIndex, then] = op;
418
+ let value = expect(meta.scopeValues, 'BUG: Attempted to gect a template local, but template does not have any')[valueIndex];
419
+ then(constants.value(value));
420
+ break;
421
+ }
422
+ case HighLevelResolutionOpcodes.Free:
423
+ if (DEBUG) {
424
+ let [, upvarIndex] = op;
425
+ let freeName = expect(meta.upvars, 'BUG: attempted to resolve value but no upvars found')[upvarIndex];
426
+ throw new Error(`Attempted to resolve a value in a strict mode template, but that value was not in scope: ${freeName}`);
427
+ }
428
+ break;
429
+ default:
430
+ throw new Error(`Unexpected high level opcode ${op[0]}`);
1270
431
  }
1271
- });
1272
- }
1273
-
1274
- const ATTRS_BLOCK = '&attrs';
1275
- function InvokeComponent(op, component, _elementBlock, positional, named, _blocks) {
1276
- let {
1277
- compilable,
1278
- capabilities,
1279
- handle
1280
- } = component;
1281
- let elementBlock = _elementBlock ? [_elementBlock, []] : null;
1282
- let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks;
1283
-
1284
- if (compilable) {
1285
- op(78
1286
- /* PushComponentDefinition */
1287
- , handle);
1288
- InvokeStaticComponent(op, {
1289
- capabilities: capabilities,
1290
- layout: compilable,
1291
- elementBlock,
1292
- positional,
1293
- named,
1294
- blocks
1295
- });
1296
- } else {
1297
- op(78
1298
- /* PushComponentDefinition */
1299
- , handle);
1300
- InvokeNonStaticComponent(op, {
1301
- capabilities: capabilities,
1302
- elementBlock,
1303
- positional,
1304
- named,
1305
- atNames: true,
1306
- blocks
1307
- });
1308
432
  }
1309
433
  }
1310
- function InvokeDynamicComponent(op, definition, _elementBlock, positional, named, _blocks, atNames, curried) {
1311
- let elementBlock = _elementBlock ? [_elementBlock, []] : null;
1312
- let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks;
1313
- Replayable(op, () => {
1314
- expr(op, definition);
1315
- op(33
1316
- /* Dup */
1317
- , $sp, 0);
1318
- return 2;
1319
- }, () => {
1320
- op(66
1321
- /* JumpUnless */
1322
- , labelOperand('ELSE'));
1323
-
1324
- if (curried) {
1325
- op(81
1326
- /* ResolveCurriedComponent */
1327
- );
434
+ class EncoderImpl {
435
+ labelsStack = new Stack();
436
+ encoder = new InstructionEncoderImpl([]);
437
+ errors = [];
438
+ handle;
439
+ constructor(heap, meta, stdlib) {
440
+ this.heap = heap;
441
+ this.meta = meta;
442
+ this.stdlib = stdlib;
443
+ this.handle = heap.malloc();
444
+ }
445
+ error(error) {
446
+ this.encoder.encode(Op.Primitive, 0);
447
+ this.errors.push(error);
448
+ }
449
+ commit(size) {
450
+ let handle = this.handle;
451
+ this.heap.pushMachine(MachineOp.Return);
452
+ this.heap.finishMalloc(handle, size);
453
+ if (isPresentArray(this.errors)) {
454
+ return {
455
+ errors: this.errors,
456
+ handle
457
+ };
1328
458
  } else {
1329
- op(80
1330
- /* ResolveDynamicComponent */
1331
- , isStrictMode());
459
+ return handle;
1332
460
  }
1333
-
1334
- op(79
1335
- /* PushDynamicComponentInstance */
1336
- );
1337
- InvokeNonStaticComponent(op, {
1338
- capabilities: true,
1339
- elementBlock,
1340
- positional,
1341
- named,
1342
- atNames,
1343
- blocks
1344
- });
1345
- op(1000
1346
- /* Label */
1347
- , 'ELSE');
1348
- });
1349
- }
1350
-
1351
- function InvokeStaticComponent(op, {
1352
- capabilities,
1353
- layout,
1354
- elementBlock,
1355
- positional,
1356
- named,
1357
- blocks
1358
- }) {
1359
- let {
1360
- symbolTable
1361
- } = layout;
1362
- let bailOut = symbolTable.hasEval || hasCapability(capabilities, 4
1363
- /* PrepareArgs */
1364
- );
1365
-
1366
- if (bailOut) {
1367
- InvokeNonStaticComponent(op, {
1368
- capabilities,
1369
- elementBlock,
1370
- positional,
1371
- named,
1372
- atNames: true,
1373
- blocks,
1374
- layout
1375
- });
1376
- return;
1377
461
  }
1378
-
1379
- op(36
1380
- /* Fetch */
1381
- , $s0);
1382
- op(33
1383
- /* Dup */
1384
- , $sp, 1);
1385
- op(35
1386
- /* Load */
1387
- , $s0);
1388
- op(0
1389
- /* PushFrame */
1390
- ); // Setup arguments
1391
-
1392
- let {
1393
- symbols
1394
- } = symbolTable; // As we push values onto the stack, we store the symbols associated with them
1395
- // so that we can set them on the scope later on with SetVariable and SetBlock
1396
-
1397
- let blockSymbols = [];
1398
- let argSymbols = [];
1399
- let argNames = []; // First we push the blocks onto the stack
1400
-
1401
- let blockNames = blocks.names; // Starting with the attrs block, if it exists and is referenced in the component
1402
-
1403
- if (elementBlock !== null) {
1404
- let symbol = symbols.indexOf(ATTRS_BLOCK);
1405
-
1406
- if (symbol !== -1) {
1407
- PushYieldableBlock(op, elementBlock);
1408
- blockSymbols.push(symbol);
462
+ push(constants, type) {
463
+ let {
464
+ heap
465
+ } = this;
466
+ if (DEBUG && type > TYPE_SIZE) {
467
+ throw new Error(`Opcode type over 8-bits. Got ${type}.`);
1409
468
  }
1410
- } // Followed by the other blocks, if they exist and are referenced in the component.
1411
- // Also store the index of the associated symbol.
1412
-
1413
-
1414
- for (let i = 0; i < blockNames.length; i++) {
1415
- let name = blockNames[i];
1416
- let symbol = symbols.indexOf(`&${name}`);
1417
-
1418
- if (symbol !== -1) {
1419
- PushYieldableBlock(op, blocks.get(name));
1420
- blockSymbols.push(symbol);
469
+ let machine = isMachineOp(type) ? MACHINE_MASK : 0;
470
+ let first = type | machine | (arguments.length <= 2 ? 0 : arguments.length - 2) << ARG_SHIFT;
471
+ heap.pushRaw(first);
472
+ for (let i = 0; i < (arguments.length <= 2 ? 0 : arguments.length - 2); i++) {
473
+ let op = i + 2 < 2 || arguments.length <= i + 2 ? undefined : arguments[i + 2];
474
+ heap.pushRaw(this.operand(constants, op));
1421
475
  }
1422
- } // Next up we have arguments. If the component has the `createArgs` capability,
1423
- // then it wants access to the arguments in JavaScript. We can't know whether
1424
- // or not an argument is used, so we have to give access to all of them.
1425
-
1426
-
1427
- if (hasCapability(capabilities, 8
1428
- /* CreateArgs */
1429
- )) {
1430
- // First we push positional arguments
1431
- let count = CompilePositional(op, positional); // setup the flags with the count of positionals, and to indicate that atNames
1432
- // are used
1433
-
1434
- let flags = count << 4;
1435
- flags |= 0b1000;
1436
- let names = EMPTY_STRING_ARRAY; // Next, if named args exist, push them all. If they have an associated symbol
1437
- // in the invoked component (e.g. they are used within its template), we push
1438
- // that symbol. If not, we still push the expression as it may be used, and
1439
- // we store the symbol as -1 (this is used later).
1440
-
1441
- if (named !== null) {
1442
- names = named[0];
1443
- let val = named[1];
1444
-
1445
- for (let i = 0; i < val.length; i++) {
1446
- let symbol = symbols.indexOf(names[i]);
1447
- expr(op, val[i]);
1448
- argSymbols.push(symbol);
1449
- }
1450
- } // Finally, push the VM arguments themselves. These args won't need access
1451
- // to blocks (they aren't accessible from userland anyways), so we push an
1452
- // empty array instead of the actual block names.
1453
-
1454
-
1455
- op(82
1456
- /* PushArgs */
1457
- , names, EMPTY_STRING_ARRAY, flags); // And push an extra pop operation to remove the args before we begin setting
1458
- // variables on the local context
1459
-
1460
- argSymbols.push(-1);
1461
- } else if (named !== null) {
1462
- // If the component does not have the `createArgs` capability, then the only
1463
- // expressions we need to push onto the stack are those that are actually
1464
- // referenced in the template of the invoked component (e.g. have symbols).
1465
- let names = named[0];
1466
- let val = named[1];
1467
-
1468
- for (let i = 0; i < val.length; i++) {
1469
- let name = names[i];
1470
- let symbol = symbols.indexOf(name);
1471
-
1472
- if (symbol !== -1) {
1473
- expr(op, val[i]);
1474
- argSymbols.push(symbol);
1475
- argNames.push(name);
476
+ }
477
+ operand(constants, operand) {
478
+ if (typeof operand === 'number') {
479
+ return operand;
480
+ }
481
+ if (typeof operand === 'object' && operand !== null) {
482
+ if (Array.isArray(operand)) {
483
+ return encodeHandle(constants.array(operand));
484
+ } else {
485
+ switch (operand.type) {
486
+ case HighLevelOperands.Label:
487
+ this.currentLabels.target(this.heap.offset, operand.value);
488
+ return -1;
489
+ case HighLevelOperands.IsStrictMode:
490
+ return encodeHandle(constants.value(this.meta.isStrictMode));
491
+ case HighLevelOperands.DebugSymbols:
492
+ return encodeHandle(constants.array(this.meta.evalSymbols || EMPTY_STRING_ARRAY));
493
+ case HighLevelOperands.Block:
494
+ return encodeHandle(constants.value(compilableBlock(operand.value, this.meta)));
495
+ case HighLevelOperands.StdLib:
496
+ 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];
497
+ case HighLevelOperands.NonSmallInt:
498
+ case HighLevelOperands.SymbolTable:
499
+ case HighLevelOperands.Layout:
500
+ return constants.value(operand.value);
501
+ }
1476
502
  }
1477
503
  }
504
+ return encodeHandle(constants.value(operand));
1478
505
  }
1479
-
1480
- op(97
1481
- /* BeginComponentTransaction */
1482
- , $s0);
1483
-
1484
- if (hasCapability(capabilities, 64
1485
- /* DynamicScope */
1486
- )) {
1487
- op(59
1488
- /* PushDynamicScope */
1489
- );
506
+ get currentLabels() {
507
+ return expect(this.labelsStack.current, 'bug: not in a label stack');
1490
508
  }
1491
-
1492
- if (hasCapability(capabilities, 512
1493
- /* CreateInstance */
1494
- )) {
1495
- op(87
1496
- /* CreateComponent */
1497
- , blocks.has('default') | 0, $s0);
509
+ label(name) {
510
+ this.currentLabels.label(name, this.heap.offset + 1);
1498
511
  }
1499
-
1500
- op(88
1501
- /* RegisterComponentDestructor */
1502
- , $s0);
1503
-
1504
- if (hasCapability(capabilities, 8
1505
- /* CreateArgs */
1506
- )) {
1507
- op(90
1508
- /* GetComponentSelf */
1509
- , $s0);
1510
- } else {
1511
- op(90
1512
- /* GetComponentSelf */
1513
- , $s0, argNames);
1514
- } // Setup the new root scope for the component
1515
-
1516
-
1517
- op(37
1518
- /* RootScope */
1519
- , symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0); // Pop the self reference off the stack and set it to the symbol for `this`
1520
- // in the new scope. This is why all subsequent symbols are increased by one.
1521
-
1522
- op(19
1523
- /* SetVariable */
1524
- , 0); // Going in reverse, now we pop the args/blocks off the stack, starting with
1525
- // arguments, and assign them to their symbols in the new scope.
1526
-
1527
- for (let i = argSymbols.length - 1; i >= 0; i--) {
1528
- let symbol = argSymbols[i];
1529
-
1530
- if (symbol === -1) {
1531
- // The expression was not bound to a local symbol, it was only pushed to be
1532
- // used with VM args in the javascript side
1533
- op(34
1534
- /* Pop */
1535
- , 1);
1536
- } else {
1537
- op(19
1538
- /* SetVariable */
1539
- , symbol + 1);
1540
- }
1541
- } // if any positional params exist, pop them off the stack as well
1542
-
1543
-
1544
- if (positional !== null) {
1545
- op(34
1546
- /* Pop */
1547
- , positional.length);
1548
- } // Finish up by popping off and assigning blocks
1549
-
1550
-
1551
- for (let i = blockSymbols.length - 1; i >= 0; i--) {
1552
- let symbol = blockSymbols[i];
1553
- op(20
1554
- /* SetBlock */
1555
- , symbol + 1);
1556
- }
1557
-
1558
- op(28
1559
- /* Constant */
1560
- , layoutOperand(layout));
1561
- op(61
1562
- /* CompileBlock */
1563
- );
1564
- op(2
1565
- /* InvokeVirtual */
1566
- );
1567
- op(100
1568
- /* DidRenderLayout */
1569
- , $s0);
1570
- op(1
1571
- /* PopFrame */
1572
- );
1573
- op(40
1574
- /* PopScope */
1575
- );
1576
-
1577
- if (hasCapability(capabilities, 64
1578
- /* DynamicScope */
1579
- )) {
1580
- op(60
1581
- /* PopDynamicScope */
1582
- );
1583
- }
1584
-
1585
- op(98
1586
- /* CommitComponentTransaction */
1587
- );
1588
- op(35
1589
- /* Load */
1590
- , $s0);
1591
- }
1592
-
1593
- function InvokeNonStaticComponent(op, {
1594
- capabilities,
1595
- elementBlock,
1596
- positional,
1597
- named,
1598
- atNames,
1599
- blocks: namedBlocks,
1600
- layout
1601
- }) {
1602
- let bindableBlocks = !!namedBlocks;
1603
- let bindableAtNames = capabilities === true || hasCapability(capabilities, 4
1604
- /* PrepareArgs */
1605
- ) || !!(named && named[0].length !== 0);
1606
- let blocks = namedBlocks.with('attrs', elementBlock);
1607
- op(36
1608
- /* Fetch */
1609
- , $s0);
1610
- op(33
1611
- /* Dup */
1612
- , $sp, 1);
1613
- op(35
1614
- /* Load */
1615
- , $s0);
1616
- op(0
1617
- /* PushFrame */
1618
- );
1619
- CompileArgs(op, positional, named, blocks, atNames);
1620
- op(85
1621
- /* PrepareArgs */
1622
- , $s0);
1623
- invokePreparedComponent(op, blocks.has('default'), bindableBlocks, bindableAtNames, () => {
1624
- if (layout) {
1625
- op(63
1626
- /* PushSymbolTable */
1627
- , symbolTableOperand(layout.symbolTable));
1628
- op(28
1629
- /* Constant */
1630
- , layoutOperand(layout));
1631
- op(61
1632
- /* CompileBlock */
1633
- );
1634
- } else {
1635
- op(92
1636
- /* GetComponentLayout */
1637
- , $s0);
1638
- }
1639
-
1640
- op(95
1641
- /* PopulateLayout */
1642
- , $s0);
1643
- });
1644
- op(35
1645
- /* Load */
1646
- , $s0);
1647
- }
1648
- function WrappedComponent(op, layout, attrsBlockNumber) {
1649
- op(1001
1650
- /* StartLabels */
1651
- );
1652
- WithSavedRegister(op, $s1, () => {
1653
- op(91
1654
- /* GetComponentTagName */
1655
- , $s0);
1656
- op(31
1657
- /* PrimitiveReference */
1658
- );
1659
- op(33
1660
- /* Dup */
1661
- , $sp, 0);
1662
- });
1663
- op(66
1664
- /* JumpUnless */
1665
- , labelOperand('BODY'));
1666
- op(36
1667
- /* Fetch */
1668
- , $s1);
1669
- op(89
1670
- /* PutComponentOperations */
1671
- );
1672
- op(49
1673
- /* OpenDynamicElement */
1674
- );
1675
- op(99
1676
- /* DidCreateElement */
1677
- , $s0);
1678
- YieldBlock(op, attrsBlockNumber, null);
1679
- op(54
1680
- /* FlushElement */
1681
- );
1682
- op(1000
1683
- /* Label */
1684
- , 'BODY');
1685
- InvokeStaticBlock(op, [layout.block[0], []]);
1686
- op(36
1687
- /* Fetch */
1688
- , $s1);
1689
- op(66
1690
- /* JumpUnless */
1691
- , labelOperand('END'));
1692
- op(55
1693
- /* CloseElement */
1694
- );
1695
- op(1000
1696
- /* Label */
1697
- , 'END');
1698
- op(35
1699
- /* Load */
1700
- , $s1);
1701
- op(1002
1702
- /* StopLabels */
1703
- );
1704
- }
1705
- function invokePreparedComponent(op, hasBlock, bindableBlocks, bindableAtNames, populateLayout = null) {
1706
- op(97
1707
- /* BeginComponentTransaction */
1708
- , $s0);
1709
- op(59
1710
- /* PushDynamicScope */
1711
- );
1712
- op(87
1713
- /* CreateComponent */
1714
- , hasBlock | 0, $s0); // this has to run after createComponent to allow
1715
- // for late-bound layouts, but a caller is free
1716
- // to populate the layout earlier if it wants to
1717
- // and do nothing here.
1718
-
1719
- if (populateLayout) {
1720
- populateLayout();
512
+ startLabels() {
513
+ this.labelsStack.push(new Labels());
514
+ }
515
+ stopLabels() {
516
+ let label = expect(this.labelsStack.pop(), 'unbalanced push and pop labels');
517
+ label.patch(this.heap);
1721
518
  }
1722
-
1723
- op(88
1724
- /* RegisterComponentDestructor */
1725
- , $s0);
1726
- op(90
1727
- /* GetComponentSelf */
1728
- , $s0);
1729
- op(38
1730
- /* VirtualRootScope */
1731
- , $s0);
1732
- op(19
1733
- /* SetVariable */
1734
- , 0);
1735
- op(94
1736
- /* SetupForEval */
1737
- , $s0);
1738
- if (bindableAtNames) op(17
1739
- /* SetNamedVariables */
1740
- , $s0);
1741
- if (bindableBlocks) op(18
1742
- /* SetBlocks */
1743
- , $s0);
1744
- op(34
1745
- /* Pop */
1746
- , 1);
1747
- op(96
1748
- /* InvokeComponentLayout */
1749
- , $s0);
1750
- op(100
1751
- /* DidRenderLayout */
1752
- , $s0);
1753
- op(1
1754
- /* PopFrame */
1755
- );
1756
- op(40
1757
- /* PopScope */
1758
- );
1759
- op(60
1760
- /* PopDynamicScope */
1761
- );
1762
- op(98
1763
- /* CommitComponentTransaction */
1764
- );
1765
- }
1766
- function InvokeBareComponent(op) {
1767
- op(36
1768
- /* Fetch */
1769
- , $s0);
1770
- op(33
1771
- /* Dup */
1772
- , $sp, 1);
1773
- op(35
1774
- /* Load */
1775
- , $s0);
1776
- op(0
1777
- /* PushFrame */
1778
- );
1779
- op(83
1780
- /* PushEmptyArgs */
1781
- );
1782
- op(85
1783
- /* PrepareArgs */
1784
- , $s0);
1785
- invokePreparedComponent(op, false, false, true, () => {
1786
- op(92
1787
- /* GetComponentLayout */
1788
- , $s0);
1789
- op(95
1790
- /* PopulateLayout */
1791
- , $s0);
1792
- });
1793
- op(35
1794
- /* Load */
1795
- , $s0);
1796
519
  }
1797
- function WithSavedRegister(op, register, block) {
1798
- op(36
1799
- /* Fetch */
1800
- , register);
1801
- block();
1802
- op(35
1803
- /* Load */
1804
- , register);
520
+ function isBuilderOpcode(op) {
521
+ return op < HighLevelBuilderOpcodes.Start;
1805
522
  }
1806
523
 
1807
524
  class StdLib {
@@ -1812,837 +529,1008 @@ class StdLib {
1812
529
  this.trustingNonDynamicAppend = trustingNonDynamicAppend;
1813
530
  this.cautiousNonDynamicAppend = cautiousNonDynamicAppend;
1814
531
  }
1815
-
1816
532
  get 'trusting-append'() {
1817
533
  return this.trustingGuardedAppend;
1818
534
  }
1819
-
1820
535
  get 'cautious-append'() {
1821
536
  return this.cautiousGuardedAppend;
1822
537
  }
1823
-
1824
538
  get 'trusting-non-dynamic-append'() {
1825
539
  return this.trustingNonDynamicAppend;
1826
540
  }
541
+ get 'cautious-non-dynamic-append'() {
542
+ return this.cautiousNonDynamicAppend;
543
+ }
544
+ getAppend(trusting) {
545
+ return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend;
546
+ }
547
+ }
548
+
549
+ class NamedBlocksImpl {
550
+ names;
551
+ constructor(blocks) {
552
+ this.blocks = blocks;
553
+ this.names = blocks ? Object.keys(blocks) : [];
554
+ }
555
+ get(name) {
556
+ if (!this.blocks) return null;
557
+ return this.blocks[name] || null;
558
+ }
559
+ has(name) {
560
+ let {
561
+ blocks
562
+ } = this;
563
+ return blocks !== null && name in blocks;
564
+ }
565
+ with(name, block) {
566
+ let {
567
+ blocks
568
+ } = this;
569
+ if (blocks) {
570
+ return new NamedBlocksImpl(assign({}, blocks, {
571
+ [name]: block
572
+ }));
573
+ } else {
574
+ return new NamedBlocksImpl({
575
+ [name]: block
576
+ });
577
+ }
578
+ }
579
+ get hasAny() {
580
+ return this.blocks !== null;
581
+ }
582
+ }
583
+ const EMPTY_BLOCKS = new NamedBlocksImpl(null);
584
+ function namedBlocks(blocks) {
585
+ if (blocks === null) {
586
+ return EMPTY_BLOCKS;
587
+ }
588
+ let out = dict();
589
+ let [keys, values] = blocks;
590
+ for (const [i, key] of enumerate(keys)) {
591
+ out[key] = unwrap(values[i]);
592
+ }
593
+ return new NamedBlocksImpl(out);
594
+ }
595
+
596
+ /**
597
+ * Push a reference onto the stack corresponding to a statically known primitive
598
+ * @param value A JavaScript primitive (undefined, null, boolean, number or string)
599
+ */
600
+ function PushPrimitiveReference(op, value) {
601
+ PushPrimitive(op, value);
602
+ op(Op.PrimitiveReference);
603
+ }
604
+
605
+ /**
606
+ * Push an encoded representation of a JavaScript primitive on the stack
607
+ *
608
+ * @param value A JavaScript primitive (undefined, null, boolean, number or string)
609
+ */
610
+ function PushPrimitive(op, primitive) {
611
+ let p = primitive;
612
+ if (typeof p === 'number') {
613
+ p = isSmallInt(p) ? encodeImmediate(p) : nonSmallIntOperand(p);
614
+ }
615
+ op(Op.Primitive, p);
616
+ }
1827
617
 
1828
- get 'cautious-non-dynamic-append'() {
1829
- return this.cautiousNonDynamicAppend;
1830
- }
618
+ /**
619
+ * Invoke a foreign function (a "helper") based on a statically known handle
620
+ *
621
+ * @param op The op creation function
622
+ * @param handle A handle
623
+ * @param positional An optional list of expressions to compile
624
+ * @param named An optional list of named arguments (name + expression) to compile
625
+ */
626
+ function Call(op, handle, positional, named) {
627
+ op(MachineOp.PushFrame);
628
+ SimpleArgs(op, positional, named, false);
629
+ op(Op.Helper, handle);
630
+ op(MachineOp.PopFrame);
631
+ op(Op.Fetch, $v0);
632
+ }
1831
633
 
1832
- getAppend(trusting) {
1833
- return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend;
634
+ /**
635
+ * Invoke a foreign function (a "helper") based on a dynamically loaded definition
636
+ *
637
+ * @param op The op creation function
638
+ * @param positional An optional list of expressions to compile
639
+ * @param named An optional list of named arguments (name + expression) to compile
640
+ */
641
+ function CallDynamic(op, positional, named, append) {
642
+ op(MachineOp.PushFrame);
643
+ SimpleArgs(op, positional, named, false);
644
+ op(Op.Dup, $fp, 1);
645
+ op(Op.DynamicHelper);
646
+ if (append) {
647
+ op(Op.Fetch, $v0);
648
+ append();
649
+ op(MachineOp.PopFrame);
650
+ op(Op.Pop, 1);
651
+ } else {
652
+ op(MachineOp.PopFrame);
653
+ op(Op.Pop, 1);
654
+ op(Op.Fetch, $v0);
1834
655
  }
1835
-
1836
656
  }
1837
657
 
1838
- function programCompilationContext(artifacts, resolver) {
1839
- return new CompileTimeCompilationContextImpl(artifacts, resolver);
658
+ /**
659
+ * Evaluate statements in the context of new dynamic scope entries. Move entries from the
660
+ * stack into named entries in the dynamic scope, then evaluate the statements, then pop
661
+ * the dynamic scope
662
+ *
663
+ * @param names a list of dynamic scope names
664
+ * @param block a function that returns a list of statements to evaluate
665
+ */
666
+ function DynamicScope(op, names, block) {
667
+ op(Op.PushDynamicScope);
668
+ op(Op.BindDynamicScope, names);
669
+ block();
670
+ op(Op.PopDynamicScope);
1840
671
  }
1841
- function templateCompilationContext(program, meta) {
1842
- let encoder = new EncoderImpl(program.heap, meta, program.stdlib);
1843
- return {
1844
- program,
1845
- encoder,
1846
- meta
1847
- };
672
+ function Curry(op, type, definition, positional, named) {
673
+ op(MachineOp.PushFrame);
674
+ SimpleArgs(op, positional, named, false);
675
+ op(Op.CaptureArgs);
676
+ expr(op, definition);
677
+ op(Op.Curry, type, isStrictMode());
678
+ op(MachineOp.PopFrame);
679
+ op(Op.Fetch, $v0);
1848
680
  }
1849
681
 
1850
- let debugCompiler;
1851
-
1852
- const STATEMENTS = new Compilers();
1853
- const INFLATE_ATTR_TABLE = ['class', 'id', 'value', 'name', 'type', 'style', 'href'];
1854
- const INFLATE_TAG_TABLE = ['div', 'span', 'p', 'a'];
1855
- function inflateTagName(tagName) {
1856
- return typeof tagName === 'string' ? tagName : INFLATE_TAG_TABLE[tagName];
1857
- }
1858
- function inflateAttrName(attrName) {
1859
- return typeof attrName === 'string' ? attrName : INFLATE_ATTR_TABLE[attrName];
682
+ class Compilers {
683
+ names = {};
684
+ funcs = [];
685
+ add(name, func) {
686
+ this.names[name] = this.funcs.push(func) - 1;
687
+ }
688
+ compile(op, sexp) {
689
+ let name = sexp[0];
690
+ let index = unwrap(this.names[name]);
691
+ let func = this.funcs[index];
692
+ assert$1(!!func, `expected an implementation for ${sexp[0]}`);
693
+ func(op, sexp);
694
+ }
1860
695
  }
1861
- STATEMENTS.add(3
1862
- /* Comment */
1863
- , (op, sexp) => op(42
1864
- /* Comment */
1865
- , sexp[1]));
1866
- STATEMENTS.add(13
1867
- /* CloseElement */
1868
- , op => op(55
1869
- /* CloseElement */
1870
- ));
1871
- STATEMENTS.add(12
1872
- /* FlushElement */
1873
- , op => op(54
1874
- /* FlushElement */
1875
- ));
1876
- STATEMENTS.add(4
1877
- /* Modifier */
1878
- , (op, [, expression, positional, named]) => {
1879
- if (isGetFreeModifier(expression)) {
1880
- op(1003
1881
- /* ResolveModifier */
1882
- , expression, handle => {
1883
- op(0
1884
- /* PushFrame */
1885
- );
1886
- SimpleArgs(op, positional, named, false);
1887
- op(57
1888
- /* Modifier */
1889
- , handle);
1890
- op(1
1891
- /* PopFrame */
1892
- );
696
+
697
+ const EXPRESSIONS = new Compilers();
698
+ EXPRESSIONS.add(SexpOpcodes.Concat, (op, _ref) => {
699
+ let [, parts] = _ref;
700
+ for (let part of parts) {
701
+ expr(op, part);
702
+ }
703
+ op(Op.Concat, parts.length);
704
+ });
705
+ EXPRESSIONS.add(SexpOpcodes.Call, (op, _ref2) => {
706
+ let [, expression, positional, named] = _ref2;
707
+ if (isGetFreeHelper(expression)) {
708
+ op(HighLevelResolutionOpcodes.Helper, expression, handle => {
709
+ Call(op, handle, positional, named);
1893
710
  });
1894
711
  } else {
1895
712
  expr(op, expression);
1896
- op(0
1897
- /* PushFrame */
1898
- );
1899
- SimpleArgs(op, positional, named, false);
1900
- op(33
1901
- /* Dup */
1902
- , $fp, 1);
1903
- op(108
1904
- /* DynamicModifier */
1905
- );
1906
- op(1
1907
- /* PopFrame */
1908
- );
713
+ CallDynamic(op, positional, named);
1909
714
  }
1910
715
  });
1911
- STATEMENTS.add(14
1912
- /* StaticAttr */
1913
- , (op, [, name, value, namespace]) => {
1914
- op(51
1915
- /* StaticAttr */
1916
- , inflateAttrName(name), value, namespace !== null && namespace !== void 0 ? namespace : null);
1917
- });
1918
- STATEMENTS.add(24
1919
- /* StaticComponentAttr */
1920
- , (op, [, name, value, namespace]) => {
1921
- op(105
1922
- /* StaticComponentAttr */
1923
- , inflateAttrName(name), value, namespace !== null && namespace !== void 0 ? namespace : null);
1924
- });
1925
- STATEMENTS.add(15
1926
- /* DynamicAttr */
1927
- , (op, [, name, value, namespace]) => {
1928
- expr(op, value);
1929
- op(52
1930
- /* DynamicAttr */
1931
- , inflateAttrName(name), false, namespace !== null && namespace !== void 0 ? namespace : null);
1932
- });
1933
- STATEMENTS.add(22
1934
- /* TrustingDynamicAttr */
1935
- , (op, [, name, value, namespace]) => {
1936
- expr(op, value);
1937
- op(52
1938
- /* DynamicAttr */
1939
- , inflateAttrName(name), true, namespace !== null && namespace !== void 0 ? namespace : null);
1940
- });
1941
- STATEMENTS.add(16
1942
- /* ComponentAttr */
1943
- , (op, [, name, value, namespace]) => {
1944
- expr(op, value);
1945
- op(53
1946
- /* ComponentAttr */
1947
- , inflateAttrName(name), false, namespace !== null && namespace !== void 0 ? namespace : null);
716
+ EXPRESSIONS.add(SexpOpcodes.Curry, (op, _ref3) => {
717
+ let [, expr, type, positional, named] = _ref3;
718
+ Curry(op, type, expr, positional, named);
1948
719
  });
1949
- STATEMENTS.add(23
1950
- /* TrustingComponentAttr */
1951
- , (op, [, name, value, namespace]) => {
1952
- expr(op, value);
1953
- op(53
1954
- /* ComponentAttr */
1955
- , inflateAttrName(name), true, namespace !== null && namespace !== void 0 ? namespace : null);
720
+ EXPRESSIONS.add(SexpOpcodes.GetSymbol, (op, _ref4) => {
721
+ let [, sym, path] = _ref4;
722
+ op(Op.GetVariable, sym);
723
+ withPath(op, path);
1956
724
  });
1957
- STATEMENTS.add(10
1958
- /* OpenElement */
1959
- , (op, [, tag]) => {
1960
- op(48
1961
- /* OpenElement */
1962
- , inflateTagName(tag));
725
+ EXPRESSIONS.add(SexpOpcodes.GetLexicalSymbol, (op, _ref5) => {
726
+ let [, sym, path] = _ref5;
727
+ op(HighLevelResolutionOpcodes.TemplateLocal, sym, handle => {
728
+ op(Op.ConstantReference, handle);
729
+ withPath(op, path);
730
+ });
1963
731
  });
1964
- STATEMENTS.add(11
1965
- /* OpenElementWithSplat */
1966
- , (op, [, tag]) => {
1967
- op(89
1968
- /* PutComponentOperations */
1969
- );
1970
- op(48
1971
- /* OpenElement */
1972
- , inflateTagName(tag));
732
+ EXPRESSIONS.add(SexpOpcodes.GetStrictKeyword, (op, _ref6) => {
733
+ let [, sym, _path] = _ref6;
734
+ op(HighLevelResolutionOpcodes.Free, sym, _handle => {
735
+ // TODO: Implement in strict mode
736
+ });
1973
737
  });
1974
- STATEMENTS.add(8
1975
- /* Component */
1976
- , (op, [, expr, elementBlock, named, blocks]) => {
1977
- if (isGetFreeComponent(expr)) {
1978
- op(1004
1979
- /* ResolveComponent */
1980
- , expr, component => {
1981
- InvokeComponent(op, component, elementBlock, null, named, blocks);
1982
- });
1983
- } else {
1984
- // otherwise, the component name was an expression, so resolve the expression
1985
- // and invoke it as a dynamic component
1986
- InvokeDynamicComponent(op, expr, elementBlock, null, named, blocks, true, true);
1987
- }
738
+ EXPRESSIONS.add(SexpOpcodes.GetFreeAsComponentOrHelperHeadOrThisFallback, () => {
739
+ // TODO: The logic for this opcode currently exists in STATEMENTS.Append, since
740
+ // we want different wrapping logic depending on if we are invoking a component,
741
+ // helper, or {{this}} fallback. Eventually we fix the opcodes so that we can
742
+ // traverse the subexpression tree like normal in this location.
743
+ throw new Error('unimplemented opcode');
1988
744
  });
1989
- STATEMENTS.add(18
1990
- /* Yield */
1991
- , (op, [, to, params]) => YieldBlock(op, to, params));
1992
- STATEMENTS.add(17
1993
- /* AttrSplat */
1994
- , (op, [, to]) => YieldBlock(op, to, null));
1995
- STATEMENTS.add(26
1996
- /* Debugger */
1997
- , (op, [, evalInfo]) => op(103
1998
- /* Debugger */
1999
- , evalSymbolsOperand(), evalInfo));
2000
- STATEMENTS.add(1
2001
- /* Append */
2002
- , (op, [, value]) => {
2003
- // Special case for static values
2004
- if (!Array.isArray(value)) {
2005
- op(41
2006
- /* Text */
2007
- , value === null || value === undefined ? '' : String(value));
2008
- } else if (isGetFreeOptionalComponentOrHelper(value)) {
2009
- op(1008
2010
- /* ResolveOptionalComponentOrHelper */
2011
- , value, {
2012
- ifComponent(component) {
2013
- InvokeComponent(op, component, null, null, null, null);
2014
- },
745
+ EXPRESSIONS.add(SexpOpcodes.GetFreeAsHelperHeadOrThisFallback, (op, expr) => {
746
+ // <div id={{baz}}>
2015
747
 
2016
- ifHelper(handle) {
2017
- op(0
2018
- /* PushFrame */
2019
- );
748
+ op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
749
+ op(HighLevelResolutionOpcodes.OptionalHelper, expr, {
750
+ ifHelper: handle => {
2020
751
  Call(op, handle, null, null);
2021
- op(3
2022
- /* InvokeStatic */
2023
- , stdlibOperand('cautious-non-dynamic-append'));
2024
- op(1
2025
- /* PopFrame */
2026
- );
2027
- },
2028
-
2029
- ifValue(handle) {
2030
- op(0
2031
- /* PushFrame */
2032
- );
2033
- op(29
2034
- /* ConstantReference */
2035
- , handle);
2036
- op(3
2037
- /* InvokeStatic */
2038
- , stdlibOperand('cautious-non-dynamic-append'));
2039
- op(1
2040
- /* PopFrame */
2041
- );
2042
752
  }
2043
-
2044
753
  });
2045
- } else if (value[0] === 28
2046
- /* Call */
2047
- ) {
2048
- let [, expression, positional, named] = value;
2049
-
2050
- if (isGetFreeComponentOrHelper(expression)) {
2051
- op(1007
2052
- /* ResolveComponentOrHelper */
2053
- , expression, {
2054
- ifComponent(component) {
2055
- InvokeComponent(op, component, null, positional, hashToArgs(named), null);
2056
- },
2057
-
2058
- ifHelper(handle) {
2059
- op(0
2060
- /* PushFrame */
2061
- );
2062
- Call(op, handle, positional, named);
2063
- op(3
2064
- /* InvokeStatic */
2065
- , stdlibOperand('cautious-non-dynamic-append'));
2066
- op(1
2067
- /* PopFrame */
2068
- );
2069
- }
754
+ });
755
+ });
756
+ EXPRESSIONS.add(SexpOpcodes.GetFreeAsDeprecatedHelperHeadOrThisFallback, (op, expr) => {
757
+ // <Foo @bar={{baz}}>
2070
758
 
759
+ op(HighLevelResolutionOpcodes.Local, expr[1], _name => {
760
+ op(HighLevelResolutionOpcodes.OptionalHelper, expr, {
761
+ ifHelper: (handle, name, moduleName) => {
762
+ assert(expr[2] && expr[2].length === 1, '[BUG] Missing argument name');
763
+ let arg = expr[2][0];
764
+ deprecate(`The \`${name}\` helper was used in the \`${moduleName}\` template as \`${arg}={{${name}}}\`. ` + `This is ambigious between wanting the \`${arg}\` argument to be the \`${name}\` helper itself, ` + `or the result of invoking the \`${name}\` helper (current behavior). ` + `This implicit invocation behavior has been deprecated.\n\n` + `Instead, please explicitly invoke the helper with parenthesis, i.e. \`${arg}={{(${name})}}\`.\n\n` + `Note: the parenthesis are only required in this exact scenario where an ambiguity is present – where ` + `\`${name}\` referes to a global helper (as opposed to a local variable), AND ` + `the \`${name}\` helper invocation does not take any arguments, AND ` + `this occurs in a named argument position of a component invocation.\n\n` + `We expect this combination to be quite rare, as most helpers require at least one argument. ` + `There is no need to refactor helper invocations in cases where this deprecation was not triggered.`, false, {
765
+ id: 'argument-less-helper-paren-less-invocation'
2071
766
  });
2072
- } else {
2073
- SwitchCases(op, () => {
2074
- expr(op, expression);
2075
- op(106
2076
- /* DynamicContentType */
2077
- );
2078
- }, when => {
2079
- when(0
2080
- /* Component */
2081
- , () => {
2082
- op(81
2083
- /* ResolveCurriedComponent */
2084
- );
2085
- op(79
2086
- /* PushDynamicComponentInstance */
2087
- );
2088
- InvokeNonStaticComponent(op, {
2089
- capabilities: true,
2090
- elementBlock: null,
2091
- positional,
2092
- named,
2093
- atNames: false,
2094
- blocks: namedBlocks(null)
2095
- });
2096
- });
2097
- when(1
2098
- /* Helper */
2099
- , () => {
2100
- CallDynamic(op, positional, named, () => {
2101
- op(3
2102
- /* InvokeStatic */
2103
- , stdlibOperand('cautious-non-dynamic-append'));
2104
- });
2105
- });
2106
- });
767
+ Call(op, handle, null, null);
2107
768
  }
2108
- } else {
2109
- op(0
2110
- /* PushFrame */
2111
- );
2112
- expr(op, value);
2113
- op(3
2114
- /* InvokeStatic */
2115
- , stdlibOperand('cautious-append'));
2116
- op(1
2117
- /* PopFrame */
2118
- );
2119
- }
2120
- });
2121
- STATEMENTS.add(2
2122
- /* TrustingAppend */
2123
- , (op, [, value]) => {
2124
- if (!Array.isArray(value)) {
2125
- op(41
2126
- /* Text */
2127
- , value === null || value === undefined ? '' : String(value));
2128
- } else {
2129
- op(0
2130
- /* PushFrame */
2131
- );
2132
- expr(op, value);
2133
- op(3
2134
- /* InvokeStatic */
2135
- , stdlibOperand('trusting-append'));
2136
- op(1
2137
- /* PopFrame */
2138
- );
2139
- }
2140
- });
2141
- STATEMENTS.add(6
2142
- /* Block */
2143
- , (op, [, expr, positional, named, blocks]) => {
2144
- if (isGetFreeComponent(expr)) {
2145
- op(1004
2146
- /* ResolveComponent */
2147
- , expr, component => {
2148
- InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
2149
769
  });
2150
- } else {
2151
- InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
770
+ });
771
+ });
772
+ function withPath(op, path) {
773
+ if (path === undefined || path.length === 0) return;
774
+ for (let i = 0; i < path.length; i++) {
775
+ op(Op.GetProperty, path[i]);
2152
776
  }
777
+ }
778
+ EXPRESSIONS.add(SexpOpcodes.Undefined, op => PushPrimitiveReference(op, undefined));
779
+ EXPRESSIONS.add(SexpOpcodes.HasBlock, (op, _ref7) => {
780
+ let [, block] = _ref7;
781
+ expr(op, block);
782
+ op(Op.HasBlock);
2153
783
  });
2154
- STATEMENTS.add(40
2155
- /* InElement */
2156
- , (op, [, block, guid, destination, insertBefore]) => {
2157
- ReplayableIf(op, () => {
2158
- expr(op, guid);
2159
-
2160
- if (insertBefore === undefined) {
2161
- PushPrimitiveReference(op, undefined);
2162
- } else {
2163
- expr(op, insertBefore);
2164
- }
2165
-
2166
- expr(op, destination);
2167
- op(33
2168
- /* Dup */
2169
- , $sp, 0);
2170
- return 4;
2171
- }, () => {
2172
- op(50
2173
- /* PushRemoteElement */
2174
- );
2175
- InvokeStaticBlock(op, block);
2176
- op(56
2177
- /* PopRemoteElement */
2178
- );
2179
- });
784
+ EXPRESSIONS.add(SexpOpcodes.HasBlockParams, (op, _ref8) => {
785
+ let [, block] = _ref8;
786
+ expr(op, block);
787
+ op(Op.SpreadBlock);
788
+ op(Op.CompileBlock);
789
+ op(Op.HasBlockParams);
2180
790
  });
2181
- STATEMENTS.add(41
2182
- /* If */
2183
- , (op, [, condition, block, inverse]) => ReplayableIf(op, () => {
791
+ EXPRESSIONS.add(SexpOpcodes.IfInline, (op, _ref9) => {
792
+ let [, condition, truthy, falsy] = _ref9;
793
+ // Push in reverse order
794
+ expr(op, falsy);
795
+ expr(op, truthy);
2184
796
  expr(op, condition);
2185
- op(71
2186
- /* ToBoolean */
2187
- );
2188
- return 1;
2189
- }, () => {
2190
- InvokeStaticBlock(op, block);
2191
- }, inverse ? () => {
2192
- InvokeStaticBlock(op, inverse);
2193
- } : undefined));
2194
- STATEMENTS.add(42
2195
- /* Each */
2196
- , (op, [, value, key, block, inverse]) => Replayable(op, () => {
2197
- if (key) {
2198
- expr(op, key);
797
+ op(Op.IfInline);
798
+ });
799
+ EXPRESSIONS.add(SexpOpcodes.Not, (op, _ref10) => {
800
+ let [, value] = _ref10;
801
+ expr(op, value);
802
+ op(Op.Not);
803
+ });
804
+ EXPRESSIONS.add(SexpOpcodes.GetDynamicVar, (op, _ref11) => {
805
+ let [, expression] = _ref11;
806
+ expr(op, expression);
807
+ op(Op.GetDynamicVar);
808
+ });
809
+ EXPRESSIONS.add(SexpOpcodes.Log, (op, _ref12) => {
810
+ let [, positional] = _ref12;
811
+ op(MachineOp.PushFrame);
812
+ SimpleArgs(op, positional, null, false);
813
+ op(Op.Log);
814
+ op(MachineOp.PopFrame);
815
+ op(Op.Fetch, $v0);
816
+ });
817
+
818
+ function expr(op, expression) {
819
+ if (Array.isArray(expression)) {
820
+ EXPRESSIONS.compile(op, expression);
2199
821
  } else {
2200
- PushPrimitiveReference(op, null);
822
+ PushPrimitive(op, expression);
823
+ op(Op.PrimitiveReference);
2201
824
  }
825
+ }
2202
826
 
2203
- expr(op, value);
2204
- return 2;
2205
- }, () => {
2206
- op(72
2207
- /* EnterList */
2208
- , labelOperand('BODY'), labelOperand('ELSE'));
2209
- op(0
2210
- /* PushFrame */
2211
- );
2212
- op(33
2213
- /* Dup */
2214
- , $fp, 1);
2215
- op(6
2216
- /* ReturnTo */
2217
- , labelOperand('ITER'));
2218
- op(1000
2219
- /* Label */
2220
- , 'ITER');
2221
- op(74
2222
- /* Iterate */
2223
- , labelOperand('BREAK'));
2224
- op(1000
2225
- /* Label */
2226
- , 'BODY');
2227
- InvokeStaticBlockWithStack(op, block, 2);
2228
- op(34
2229
- /* Pop */
2230
- , 2);
2231
- op(4
2232
- /* Jump */
2233
- , labelOperand('FINALLY'));
2234
- op(1000
2235
- /* Label */
2236
- , 'BREAK');
2237
- op(1
2238
- /* PopFrame */
2239
- );
2240
- op(73
2241
- /* ExitList */
2242
- );
2243
- op(4
2244
- /* Jump */
2245
- , labelOperand('FINALLY'));
2246
- op(1000
2247
- /* Label */
2248
- , 'ELSE');
2249
-
2250
- if (inverse) {
2251
- InvokeStaticBlock(op, inverse);
827
+ /**
828
+ * Compile arguments, pushing an Arguments object onto the stack.
829
+ *
830
+ * @param args.params
831
+ * @param args.hash
832
+ * @param args.blocks
833
+ * @param args.atNames
834
+ */
835
+ function CompileArgs(op, positional, named, blocks, atNames) {
836
+ let blockNames = blocks.names;
837
+ for (const name of blockNames) {
838
+ PushYieldableBlock(op, blocks.get(name));
2252
839
  }
2253
- }));
2254
- STATEMENTS.add(43
2255
- /* With */
2256
- , (op, [, value, block, inverse]) => {
2257
- ReplayableIf(op, () => {
2258
- expr(op, value);
2259
- op(33
2260
- /* Dup */
2261
- , $sp, 0);
2262
- op(71
2263
- /* ToBoolean */
2264
- );
2265
- return 2;
2266
- }, () => {
2267
- InvokeStaticBlockWithStack(op, block, 1);
2268
- }, () => {
2269
- if (inverse) {
2270
- InvokeStaticBlock(op, inverse);
2271
- }
2272
- });
2273
- });
2274
- STATEMENTS.add(44
2275
- /* Let */
2276
- , (op, [, positional, block]) => {
2277
840
  let count = CompilePositional(op, positional);
2278
- InvokeStaticBlockWithStack(op, block, count);
2279
- });
2280
- STATEMENTS.add(45
2281
- /* WithDynamicVars */
2282
- , (op, [, named, block]) => {
841
+ let flags = count << 4;
842
+ if (atNames) flags |= 0b1000;
843
+ if (blocks) {
844
+ flags |= 0b111;
845
+ }
846
+ let names = EMPTY_ARRAY;
2283
847
  if (named) {
2284
- let [names, expressions] = named;
2285
- CompilePositional(op, expressions);
2286
- DynamicScope(op, names, () => {
2287
- InvokeStaticBlock(op, block);
2288
- });
2289
- } else {
2290
- InvokeStaticBlock(op, block);
848
+ names = named[0];
849
+ let val = named[1];
850
+ for (let i = 0; i < val.length; i++) {
851
+ expr(op, val[i]);
852
+ }
2291
853
  }
2292
- });
2293
- STATEMENTS.add(46
2294
- /* InvokeComponent */
2295
- , (op, [, expr, positional, named, blocks]) => {
2296
- if (isGetFreeComponent(expr)) {
2297
- op(1004
2298
- /* ResolveComponent */
2299
- , expr, component => {
2300
- InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
2301
- });
2302
- } else {
2303
- InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
854
+ op(Op.PushArgs, names, blockNames, flags);
855
+ }
856
+ function SimpleArgs(op, positional, named, atNames) {
857
+ if (positional === null && named === null) {
858
+ op(Op.PushEmptyArgs);
859
+ return;
2304
860
  }
2305
- });
2306
-
2307
- function hashToArgs(hash) {
2308
- if (hash === null) return null;
2309
- let names = hash[0].map(key => `@${key}`);
2310
- return [names, hash[1]];
861
+ let count = CompilePositional(op, positional);
862
+ let flags = count << 4;
863
+ if (atNames) flags |= 0b1000;
864
+ let names = EMPTY_STRING_ARRAY;
865
+ if (named) {
866
+ names = named[0];
867
+ let val = named[1];
868
+ for (let i = 0; i < val.length; i++) {
869
+ expr(op, val[i]);
870
+ }
871
+ }
872
+ op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags);
2311
873
  }
2312
874
 
2313
- const PLACEHOLDER_HANDLE = -1;
2314
-
2315
- class CompilableTemplateImpl {
2316
- constructor(statements, meta, // Part of CompilableTemplate
2317
- symbolTable, // Used for debugging
2318
- moduleName = 'plain block') {
2319
- this.statements = statements;
2320
- this.meta = meta;
2321
- this.symbolTable = symbolTable;
2322
- this.moduleName = moduleName;
2323
- this.compiled = null;
2324
- } // Part of CompilableTemplate
2325
-
2326
-
2327
- compile(context) {
2328
- return maybeCompile(this, context);
875
+ /**
876
+ * Compile an optional list of positional arguments, which pushes each argument
877
+ * onto the stack and returns the number of parameters compiled
878
+ *
879
+ * @param positional an optional list of positional arguments
880
+ */
881
+ function CompilePositional(op, positional) {
882
+ if (positional === null) return 0;
883
+ for (let i = 0; i < positional.length; i++) {
884
+ expr(op, positional[i]);
2329
885
  }
886
+ return positional.length;
887
+ }
888
+ function meta(layout) {
889
+ let [, symbols,, upvars] = layout.block;
890
+ return {
891
+ evalSymbols: evalSymbols(layout),
892
+ upvars: upvars,
893
+ scopeValues: layout.scope?.() ?? null,
894
+ isStrictMode: layout.isStrictMode,
895
+ moduleName: layout.moduleName,
896
+ owner: layout.owner,
897
+ size: symbols.length
898
+ };
899
+ }
900
+ function evalSymbols(layout) {
901
+ let {
902
+ block
903
+ } = layout;
904
+ let [, symbols, hasEval] = block;
905
+ return hasEval ? symbols : null;
906
+ }
2330
907
 
908
+ /**
909
+ * Yield to a block located at a particular symbol location.
910
+ *
911
+ * @param to the symbol containing the block to yield to
912
+ * @param params optional block parameters to yield to the block
913
+ */
914
+ function YieldBlock(op, to, positional) {
915
+ SimpleArgs(op, positional, null, true);
916
+ op(Op.GetBlock, to);
917
+ op(Op.SpreadBlock);
918
+ op(Op.CompileBlock);
919
+ op(Op.InvokeYield);
920
+ op(Op.PopScope);
921
+ op(MachineOp.PopFrame);
2331
922
  }
2332
923
 
2333
- function compilable(layout, moduleName) {
2334
- let [statements, symbols, hasEval] = layout.block;
2335
- return new CompilableTemplateImpl(statements, meta(layout), {
2336
- symbols,
2337
- hasEval
2338
- }, moduleName);
924
+ /**
925
+ * Push an (optional) yieldable block onto the stack. The yieldable block must be known
926
+ * statically at compile time.
927
+ *
928
+ * @param block An optional Compilable block
929
+ */
930
+ function PushYieldableBlock(op, block) {
931
+ PushSymbolTable(op, block && block[1]);
932
+ op(Op.PushBlockScope);
933
+ PushCompilable(op, block);
2339
934
  }
2340
935
 
2341
- function maybeCompile(compilable, context) {
2342
- if (compilable.compiled !== null) return compilable.compiled;
2343
- compilable.compiled = PLACEHOLDER_HANDLE;
2344
- let {
2345
- statements,
2346
- meta
2347
- } = compilable;
2348
- let result = compileStatements(statements, meta, context);
2349
- compilable.compiled = result;
2350
- return result;
936
+ /**
937
+ * Invoke a block that is known statically at compile time.
938
+ *
939
+ * @param block a Compilable block
940
+ */
941
+ function InvokeStaticBlock(op, block) {
942
+ op(MachineOp.PushFrame);
943
+ PushCompilable(op, block);
944
+ op(Op.CompileBlock);
945
+ op(MachineOp.InvokeVirtual);
946
+ op(MachineOp.PopFrame);
2351
947
  }
2352
948
 
2353
- function compileStatements(statements, meta, syntaxContext) {
2354
- let sCompiler = STATEMENTS;
2355
- let context = templateCompilationContext(syntaxContext, meta);
2356
- let {
2357
- encoder,
2358
- program: {
2359
- constants,
2360
- resolver
949
+ /**
950
+ * Invoke a static block, preserving some number of stack entries for use in
951
+ * updating.
952
+ *
953
+ * @param block A compilable block
954
+ * @param callerCount A number of stack entries to preserve
955
+ */
956
+ function InvokeStaticBlockWithStack(op, block, callerCount) {
957
+ let parameters = block[1];
958
+ let calleeCount = parameters.length;
959
+ let count = Math.min(callerCount, calleeCount);
960
+ if (count === 0) {
961
+ InvokeStaticBlock(op, block);
962
+ return;
963
+ }
964
+ op(MachineOp.PushFrame);
965
+ if (count) {
966
+ op(Op.ChildScope);
967
+ for (let i = 0; i < count; i++) {
968
+ op(Op.Dup, $fp, callerCount - i);
969
+ op(Op.SetVariable, parameters[i]);
2361
970
  }
2362
- } = context;
2363
-
2364
- function pushOp(...op) {
2365
- encodeOp(encoder, constants, resolver, meta, op);
2366
971
  }
2367
-
2368
- for (let i = 0; i < statements.length; i++) {
2369
- sCompiler.compile(pushOp, statements[i]);
972
+ PushCompilable(op, block);
973
+ op(Op.CompileBlock);
974
+ op(MachineOp.InvokeVirtual);
975
+ if (count) {
976
+ op(Op.PopScope);
2370
977
  }
2371
-
2372
- let handle = context.encoder.commit(meta.size);
2373
-
2374
- return handle;
978
+ op(MachineOp.PopFrame);
2375
979
  }
2376
- function compilableBlock(block, containing) {
2377
- return new CompilableTemplateImpl(block[0], containing, {
2378
- parameters: block[1] || EMPTY_ARRAY
2379
- });
980
+ function PushSymbolTable(op, parameters) {
981
+ if (parameters !== null) {
982
+ op(Op.PushSymbolTable, symbolTableOperand({
983
+ parameters
984
+ }));
985
+ } else {
986
+ PushPrimitive(op, null);
987
+ }
2380
988
  }
2381
-
2382
- class Labels {
2383
- constructor() {
2384
- this.labels = dict();
2385
- this.targets = [];
989
+ function PushCompilable(op, _block) {
990
+ if (_block === null) {
991
+ PushPrimitive(op, null);
992
+ } else {
993
+ op(Op.Constant, blockOperand(_block));
2386
994
  }
995
+ }
2387
996
 
2388
- label(name, index) {
2389
- this.labels[name] = index;
997
+ function SwitchCases(op, bootstrap, matcher) {
998
+ // Setup the switch DSL
999
+ let clauses = [];
1000
+ let count = 0;
1001
+ function when(match, callback) {
1002
+ clauses.push({
1003
+ match,
1004
+ callback,
1005
+ label: `CLAUSE${count++}`
1006
+ });
2390
1007
  }
2391
1008
 
2392
- target(at, target) {
2393
- this.targets.push({
2394
- at,
2395
- target
2396
- });
1009
+ // Call the callback
1010
+ matcher(when);
1011
+
1012
+ // Emit the opcodes for the switch
1013
+ op(Op.Enter, 1);
1014
+ bootstrap();
1015
+ op(HighLevelBuilderOpcodes.StartLabels);
1016
+
1017
+ // First, emit the jump opcodes. We don't need a jump for the last
1018
+ // opcode, since it bleeds directly into its clause.
1019
+ for (let clause of clauses.slice(0, -1)) {
1020
+ op(Op.JumpEq, labelOperand(clause.label), clause.match);
2397
1021
  }
2398
1022
 
2399
- patch(heap) {
2400
- let {
2401
- targets,
2402
- labels
2403
- } = this;
1023
+ // Enumerate the clauses in reverse order. Earlier matches will
1024
+ // require fewer checks.
1025
+ for (let i = clauses.length - 1; i >= 0; i--) {
1026
+ let clause = unwrap(clauses[i]);
1027
+ op(HighLevelBuilderOpcodes.Label, clause.label);
1028
+ op(Op.Pop, 1);
1029
+ clause.callback();
2404
1030
 
2405
- for (let i = 0; i < targets.length; i++) {
2406
- let {
2407
- at,
2408
- target
2409
- } = targets[i];
2410
- let address = labels[target] - at;
2411
- heap.setbyaddr(at, address);
1031
+ // The first match is special: it is placed directly before the END
1032
+ // label, so no additional jump is needed at the end of it.
1033
+ if (i !== 0) {
1034
+ op(MachineOp.Jump, labelOperand('END'));
2412
1035
  }
2413
1036
  }
2414
-
1037
+ op(HighLevelBuilderOpcodes.Label, 'END');
1038
+ op(HighLevelBuilderOpcodes.StopLabels);
1039
+ op(Op.Exit);
2415
1040
  }
2416
- function encodeOp(encoder, constants, resolver, meta, op) {
2417
- if (isBuilderOpcode(op[0])) {
2418
- let [type, ...operands] = op;
2419
- encoder.push(constants, type, ...operands);
2420
- } else {
2421
- switch (op[0]) {
2422
- case 1000
2423
- /* Label */
2424
- :
2425
- return encoder.label(op[1]);
2426
1041
 
2427
- case 1001
2428
- /* StartLabels */
2429
- :
2430
- return encoder.startLabels();
1042
+ /**
1043
+ * A convenience for pushing some arguments on the stack and
1044
+ * running some code if the code needs to be re-executed during
1045
+ * updating execution if some of the arguments have changed.
1046
+ *
1047
+ * # Initial Execution
1048
+ *
1049
+ * The `args` function should push zero or more arguments onto
1050
+ * the stack and return the number of arguments pushed.
1051
+ *
1052
+ * The `body` function provides the instructions to execute both
1053
+ * during initial execution and during updating execution.
1054
+ *
1055
+ * Internally, this function starts by pushing a new frame, so
1056
+ * that the body can return and sets the return point ($ra) to
1057
+ * the ENDINITIAL label.
1058
+ *
1059
+ * It then executes the `args` function, which adds instructions
1060
+ * responsible for pushing the arguments for the block to the
1061
+ * stack. These arguments will be restored to the stack before
1062
+ * updating execution.
1063
+ *
1064
+ * Next, it adds the Enter opcode, which marks the current position
1065
+ * in the DOM, and remembers the current $pc (the next instruction)
1066
+ * as the first instruction to execute during updating execution.
1067
+ *
1068
+ * Next, it runs `body`, which adds the opcodes that should
1069
+ * execute both during initial execution and during updating execution.
1070
+ * If the `body` wishes to finish early, it should Jump to the
1071
+ * `FINALLY` label.
1072
+ *
1073
+ * Next, it adds the FINALLY label, followed by:
1074
+ *
1075
+ * - the Exit opcode, which finalizes the marked DOM started by the
1076
+ * Enter opcode.
1077
+ * - the Return opcode, which returns to the current return point
1078
+ * ($ra).
1079
+ *
1080
+ * Finally, it adds the ENDINITIAL label followed by the PopFrame
1081
+ * instruction, which restores $fp, $sp and $ra.
1082
+ *
1083
+ * # Updating Execution
1084
+ *
1085
+ * Updating execution for this `replayable` occurs if the `body` added an
1086
+ * assertion, via one of the `JumpIf`, `JumpUnless` or `AssertSame` opcodes.
1087
+ *
1088
+ * If, during updating executon, the assertion fails, the initial VM is
1089
+ * restored, and the stored arguments are pushed onto the stack. The DOM
1090
+ * between the starting and ending markers is cleared, and the VM's cursor
1091
+ * is set to the area just cleared.
1092
+ *
1093
+ * The return point ($ra) is set to -1, the exit instruction.
1094
+ *
1095
+ * Finally, the $pc is set to to the instruction saved off by the
1096
+ * Enter opcode during initial execution, and execution proceeds as
1097
+ * usual.
1098
+ *
1099
+ * The only difference is that when a `Return` instruction is
1100
+ * encountered, the program jumps to -1 rather than the END label,
1101
+ * and the PopFrame opcode is not needed.
1102
+ */
1103
+ function Replayable(op, args, body) {
1104
+ // Start a new label frame, to give END and RETURN
1105
+ // a unique meaning.
1106
+
1107
+ op(HighLevelBuilderOpcodes.StartLabels);
1108
+ op(MachineOp.PushFrame);
1109
+
1110
+ // If the body invokes a block, its return will return to
1111
+ // END. Otherwise, the return in RETURN will return to END.
1112
+ op(MachineOp.ReturnTo, labelOperand('ENDINITIAL'));
1113
+
1114
+ // Push the arguments onto the stack. The args() function
1115
+ // tells us how many stack elements to retain for re-execution
1116
+ // when updating.
1117
+ let count = args();
1118
+
1119
+ // Start a new updating closure, remembering `count` elements
1120
+ // from the stack. Everything after this point, and before END,
1121
+ // will execute both initially and to update the block.
1122
+ //
1123
+ // The enter and exit opcodes also track the area of the DOM
1124
+ // associated with this block. If an assertion inside the block
1125
+ // fails (for example, the test value changes from true to false
1126
+ // in an #if), the DOM is cleared and the program is re-executed,
1127
+ // restoring `count` elements to the stack and executing the
1128
+ // instructions between the enter and exit.
1129
+ op(Op.Enter, count);
2431
1130
 
2432
- case 1002
2433
- /* StopLabels */
2434
- :
2435
- return encoder.stopLabels();
1131
+ // Evaluate the body of the block. The body of the block may
1132
+ // return, which will jump execution to END during initial
1133
+ // execution, and exit the updating routine.
1134
+ body();
2436
1135
 
2437
- case 1004
2438
- /* ResolveComponent */
2439
- :
2440
- return resolveComponent(resolver, constants, meta, op);
1136
+ // All execution paths in the body should run the FINALLY once
1137
+ // they are done. It is executed both during initial execution
1138
+ // and during updating execution.
1139
+ op(HighLevelBuilderOpcodes.Label, 'FINALLY');
2441
1140
 
2442
- case 1003
2443
- /* ResolveModifier */
2444
- :
2445
- return resolveModifier(resolver, constants, meta, op);
1141
+ // Finalize the DOM.
1142
+ op(Op.Exit);
2446
1143
 
2447
- case 1005
2448
- /* ResolveHelper */
2449
- :
2450
- return resolveHelper(resolver, constants, meta, op);
1144
+ // In initial execution, this is a noop: it returns to the
1145
+ // immediately following opcode. In updating execution, this
1146
+ // exits the updating routine.
1147
+ op(MachineOp.Return);
2451
1148
 
2452
- case 1007
2453
- /* ResolveComponentOrHelper */
2454
- :
2455
- return resolveComponentOrHelper(resolver, constants, meta, op);
1149
+ // Cleanup code for the block. Runs on initial execution
1150
+ // but not on updating.
1151
+ op(HighLevelBuilderOpcodes.Label, 'ENDINITIAL');
1152
+ op(MachineOp.PopFrame);
1153
+ op(HighLevelBuilderOpcodes.StopLabels);
1154
+ }
2456
1155
 
2457
- case 1006
2458
- /* ResolveOptionalHelper */
2459
- :
2460
- return resolveOptionalHelper(resolver, constants, meta, op);
1156
+ /**
1157
+ * A specialized version of the `replayable` convenience that allows the
1158
+ * caller to provide different code based upon whether the item at
1159
+ * the top of the stack is true or false.
1160
+ *
1161
+ * As in `replayable`, the `ifTrue` and `ifFalse` code can invoke `return`.
1162
+ *
1163
+ * During the initial execution, a `return` will continue execution
1164
+ * in the cleanup code, which finalizes the current DOM block and pops
1165
+ * the current frame.
1166
+ *
1167
+ * During the updating execution, a `return` will exit the updating
1168
+ * routine, as it can reuse the DOM block and is always only a single
1169
+ * frame deep.
1170
+ */
1171
+ function ReplayableIf(op, args, ifTrue, ifFalse) {
1172
+ return Replayable(op, args, () => {
1173
+ // If the conditional is false, jump to the ELSE label.
1174
+ op(Op.JumpUnless, labelOperand('ELSE'));
1175
+ // Otherwise, execute the code associated with the true branch.
1176
+ ifTrue();
1177
+ // We're done, so return. In the initial execution, this runs
1178
+ // the cleanup code. In the updating VM, it exits the updating
1179
+ // routine.
1180
+ op(MachineOp.Jump, labelOperand('FINALLY'));
1181
+ op(HighLevelBuilderOpcodes.Label, 'ELSE');
2461
1182
 
2462
- case 1008
2463
- /* ResolveOptionalComponentOrHelper */
2464
- :
2465
- return resolveOptionalComponentOrHelper(resolver, constants, meta, op);
1183
+ // If the conditional is false, and code associatied ith the
1184
+ // false branch was provided, execute it. If there was no code
1185
+ // associated with the false branch, jumping to the else statement
1186
+ // has no other behavior.
1187
+ if (ifFalse !== undefined) {
1188
+ ifFalse();
1189
+ }
1190
+ });
1191
+ }
2466
1192
 
2467
- case 1010
2468
- /* ResolveLocal */
2469
- :
2470
- let freeVar = op[1];
2471
- let name = meta.upvars[freeVar];
2472
- let andThen = op[2];
2473
- andThen(name, meta.moduleName);
2474
- break;
1193
+ const ATTRS_BLOCK = '&attrs';
2475
1194
 
2476
- case 1011
2477
- /* ResolveTemplateLocal */
2478
- :
2479
- let [, valueIndex, then] = op;
2480
- let value = meta.scopeValues[valueIndex];
2481
- then(constants.value(value));
2482
- break;
1195
+ // {{component}}
2483
1196
 
2484
- case 1009
2485
- /* ResolveFree */
2486
- :
2487
- if (DEBUG) {
2488
- let [, upvarIndex] = op;
2489
- let freeName = meta.upvars[upvarIndex];
2490
- throw new Error(`Attempted to resolve a value in a strict mode template, but that value was not in scope: ${freeName}`);
2491
- }
1197
+ // <Component>
2492
1198
 
2493
- break;
1199
+ // chokepoint
2494
1200
 
2495
- default:
2496
- throw new Error(`Unexpected high level opcode ${op[0]}`);
2497
- }
1201
+ function InvokeComponent(op, component, _elementBlock, positional, named, _blocks) {
1202
+ let {
1203
+ compilable,
1204
+ capabilities,
1205
+ handle
1206
+ } = component;
1207
+ let elementBlock = _elementBlock ? [_elementBlock, []] : null;
1208
+ let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks;
1209
+ if (compilable) {
1210
+ op(Op.PushComponentDefinition, handle);
1211
+ InvokeStaticComponent(op, {
1212
+ capabilities: capabilities,
1213
+ layout: compilable,
1214
+ elementBlock,
1215
+ positional,
1216
+ named,
1217
+ blocks
1218
+ });
1219
+ } else {
1220
+ op(Op.PushComponentDefinition, handle);
1221
+ InvokeNonStaticComponent(op, {
1222
+ capabilities: capabilities,
1223
+ elementBlock,
1224
+ positional,
1225
+ named,
1226
+ atNames: true,
1227
+ blocks
1228
+ });
2498
1229
  }
2499
1230
  }
2500
- class EncoderImpl {
2501
- constructor(heap, meta, stdlib) {
2502
- this.heap = heap;
2503
- this.meta = meta;
2504
- this.stdlib = stdlib;
2505
- this.labelsStack = new Stack();
2506
- this.encoder = new InstructionEncoderImpl([]);
2507
- this.errors = [];
2508
- this.handle = heap.malloc();
2509
- }
2510
-
2511
- error(error) {
2512
- this.encoder.encode(30
2513
- /* Primitive */
2514
- , 0);
2515
- this.errors.push(error);
2516
- }
2517
-
2518
- commit(size) {
2519
- let handle = this.handle;
2520
- this.heap.push(5
2521
- /* Return */
2522
- | 1024
2523
- /* MACHINE_MASK */
2524
- );
2525
- this.heap.finishMalloc(handle, size);
2526
-
2527
- if (this.errors.length) {
2528
- return {
2529
- errors: this.errors,
2530
- handle
2531
- };
1231
+ function InvokeDynamicComponent(op, definition, _elementBlock, positional, named, _blocks, atNames, curried) {
1232
+ let elementBlock = _elementBlock ? [_elementBlock, []] : null;
1233
+ let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks;
1234
+ Replayable(op, () => {
1235
+ expr(op, definition);
1236
+ op(Op.Dup, $sp, 0);
1237
+ return 2;
1238
+ }, () => {
1239
+ op(Op.JumpUnless, labelOperand('ELSE'));
1240
+ if (curried) {
1241
+ op(Op.ResolveCurriedComponent);
2532
1242
  } else {
2533
- return handle;
1243
+ op(Op.ResolveDynamicComponent, isStrictMode());
2534
1244
  }
1245
+ op(Op.PushDynamicComponentInstance);
1246
+ InvokeNonStaticComponent(op, {
1247
+ capabilities: true,
1248
+ elementBlock,
1249
+ positional,
1250
+ named,
1251
+ atNames,
1252
+ blocks
1253
+ });
1254
+ op(HighLevelBuilderOpcodes.Label, 'ELSE');
1255
+ });
1256
+ }
1257
+ function InvokeStaticComponent(op, _ref) {
1258
+ let {
1259
+ capabilities,
1260
+ layout,
1261
+ elementBlock,
1262
+ positional,
1263
+ named,
1264
+ blocks
1265
+ } = _ref;
1266
+ let {
1267
+ symbolTable
1268
+ } = layout;
1269
+ let bailOut = symbolTable.hasEval || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs);
1270
+ if (bailOut) {
1271
+ InvokeNonStaticComponent(op, {
1272
+ capabilities,
1273
+ elementBlock,
1274
+ positional,
1275
+ named,
1276
+ atNames: true,
1277
+ blocks,
1278
+ layout
1279
+ });
1280
+ return;
2535
1281
  }
1282
+ op(Op.Fetch, $s0);
1283
+ op(Op.Dup, $sp, 1);
1284
+ op(Op.Load, $s0);
1285
+ op(MachineOp.PushFrame);
2536
1286
 
2537
- push(constants, type, ...args) {
2538
- let {
2539
- heap
2540
- } = this;
1287
+ // Setup arguments
1288
+ let {
1289
+ symbols
1290
+ } = symbolTable;
2541
1291
 
2542
- if (DEBUG && type > 255
2543
- /* TYPE_SIZE */
2544
- ) {
2545
- throw new Error(`Opcode type over 8-bits. Got ${type}.`);
2546
- }
1292
+ // As we push values onto the stack, we store the symbols associated with them
1293
+ // so that we can set them on the scope later on with SetVariable and SetBlock
1294
+ let blockSymbols = [];
1295
+ let argSymbols = [];
1296
+ let argNames = [];
2547
1297
 
2548
- let machine = isMachineOp(type) ? 1024
2549
- /* MACHINE_MASK */
2550
- : 0;
2551
- let first = type | machine | args.length << 8
2552
- /* ARG_SHIFT */
2553
- ;
2554
- heap.push(first);
2555
-
2556
- for (let i = 0; i < args.length; i++) {
2557
- let op = args[i];
2558
- heap.push(this.operand(constants, op));
1298
+ // First we push the blocks onto the stack
1299
+ let blockNames = blocks.names;
1300
+
1301
+ // Starting with the attrs block, if it exists and is referenced in the component
1302
+ if (elementBlock !== null) {
1303
+ let symbol = symbols.indexOf(ATTRS_BLOCK);
1304
+ if (symbol !== -1) {
1305
+ PushYieldableBlock(op, elementBlock);
1306
+ blockSymbols.push(symbol);
2559
1307
  }
2560
1308
  }
2561
1309
 
2562
- operand(constants, operand) {
2563
- if (typeof operand === 'number') {
2564
- return operand;
1310
+ // Followed by the other blocks, if they exist and are referenced in the component.
1311
+ // Also store the index of the associated symbol.
1312
+ for (const name of blockNames) {
1313
+ let symbol = symbols.indexOf(`&${name}`);
1314
+ if (symbol !== -1) {
1315
+ PushYieldableBlock(op, blocks.get(name));
1316
+ blockSymbols.push(symbol);
2565
1317
  }
1318
+ }
2566
1319
 
2567
- if (typeof operand === 'object' && operand !== null) {
2568
- if (Array.isArray(operand)) {
2569
- return encodeHandle(constants.array(operand));
2570
- } else {
2571
- switch (operand.type) {
2572
- case 1
2573
- /* Label */
2574
- :
2575
- this.currentLabels.target(this.heap.offset, operand.value);
2576
- return -1;
1320
+ // Next up we have arguments. If the component has the `createArgs` capability,
1321
+ // then it wants access to the arguments in JavaScript. We can't know whether
1322
+ // or not an argument is used, so we have to give access to all of them.
1323
+ if (hasCapability(capabilities, InternalComponentCapabilities.createArgs)) {
1324
+ // First we push positional arguments
1325
+ let count = CompilePositional(op, positional);
2577
1326
 
2578
- case 2
2579
- /* IsStrictMode */
2580
- :
2581
- return encodeHandle(constants.value(this.meta.isStrictMode));
1327
+ // setup the flags with the count of positionals, and to indicate that atNames
1328
+ // are used
1329
+ let flags = count << 4;
1330
+ flags |= 0b1000;
1331
+ let names = EMPTY_STRING_ARRAY;
2582
1332
 
2583
- case 3
2584
- /* EvalSymbols */
2585
- :
2586
- return encodeHandle(constants.array(this.meta.evalSymbols || EMPTY_STRING_ARRAY));
1333
+ // Next, if named args exist, push them all. If they have an associated symbol
1334
+ // in the invoked component (e.g. they are used within its template), we push
1335
+ // that symbol. If not, we still push the expression as it may be used, and
1336
+ // we store the symbol as -1 (this is used later).
1337
+ if (named !== null) {
1338
+ names = named[0];
1339
+ let val = named[1];
1340
+ for (let i = 0; i < val.length; i++) {
1341
+ let symbol = symbols.indexOf(unwrap(names[i]));
1342
+ expr(op, val[i]);
1343
+ argSymbols.push(symbol);
1344
+ }
1345
+ }
2587
1346
 
2588
- case 4
2589
- /* Block */
2590
- :
2591
- return encodeHandle(constants.value(compilableBlock(operand.value, this.meta)));
1347
+ // Finally, push the VM arguments themselves. These args won't need access
1348
+ // to blocks (they aren't accessible from userland anyways), so we push an
1349
+ // empty array instead of the actual block names.
1350
+ op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags);
2592
1351
 
2593
- case 5
2594
- /* StdLib */
2595
- :
2596
- return this.stdlib[operand.value];
2597
-
2598
- case 6
2599
- /* NonSmallInt */
2600
- :
2601
- case 7
2602
- /* SymbolTable */
2603
- :
2604
- case 8
2605
- /* Layout */
2606
- :
2607
- return constants.value(operand.value);
2608
- }
1352
+ // And push an extra pop operation to remove the args before we begin setting
1353
+ // variables on the local context
1354
+ argSymbols.push(-1);
1355
+ } else if (named !== null) {
1356
+ // If the component does not have the `createArgs` capability, then the only
1357
+ // expressions we need to push onto the stack are those that are actually
1358
+ // referenced in the template of the invoked component (e.g. have symbols).
1359
+ let names = named[0];
1360
+ let val = named[1];
1361
+ for (let i = 0; i < val.length; i++) {
1362
+ let name = unwrap(names[i]);
1363
+ let symbol = symbols.indexOf(name);
1364
+ if (symbol !== -1) {
1365
+ expr(op, val[i]);
1366
+ argSymbols.push(symbol);
1367
+ argNames.push(name);
2609
1368
  }
2610
1369
  }
2611
-
2612
- return encodeHandle(constants.value(operand));
2613
1370
  }
2614
-
2615
- get currentLabels() {
2616
- return this.labelsStack.current;
1371
+ op(Op.BeginComponentTransaction, $s0);
1372
+ if (hasCapability(capabilities, InternalComponentCapabilities.dynamicScope)) {
1373
+ op(Op.PushDynamicScope);
2617
1374
  }
2618
-
2619
- label(name) {
2620
- this.currentLabels.label(name, this.heap.offset + 1);
1375
+ if (hasCapability(capabilities, InternalComponentCapabilities.createInstance)) {
1376
+ op(Op.CreateComponent, blocks.has('default') | 0, $s0);
1377
+ }
1378
+ op(Op.RegisterComponentDestructor, $s0);
1379
+ if (hasCapability(capabilities, InternalComponentCapabilities.createArgs)) {
1380
+ op(Op.GetComponentSelf, $s0);
1381
+ } else {
1382
+ op(Op.GetComponentSelf, $s0, argNames);
2621
1383
  }
2622
1384
 
2623
- startLabels() {
2624
- this.labelsStack.push(new Labels());
1385
+ // Setup the new root scope for the component
1386
+ op(Op.RootScope, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0);
1387
+
1388
+ // Pop the self reference off the stack and set it to the symbol for `this`
1389
+ // in the new scope. This is why all subsequent symbols are increased by one.
1390
+ op(Op.SetVariable, 0);
1391
+
1392
+ // Going in reverse, now we pop the args/blocks off the stack, starting with
1393
+ // arguments, and assign them to their symbols in the new scope.
1394
+ for (const symbol of reverse(argSymbols)) {
1395
+ // for (let i = argSymbols.length - 1; i >= 0; i--) {
1396
+ // let symbol = argSymbols[i];
1397
+
1398
+ if (symbol === -1) {
1399
+ // The expression was not bound to a local symbol, it was only pushed to be
1400
+ // used with VM args in the javascript side
1401
+ op(Op.Pop, 1);
1402
+ } else {
1403
+ op(Op.SetVariable, symbol + 1);
1404
+ }
2625
1405
  }
2626
1406
 
2627
- stopLabels() {
2628
- let label = this.labelsStack.pop();
2629
- label.patch(this.heap);
1407
+ // if any positional params exist, pop them off the stack as well
1408
+ if (positional !== null) {
1409
+ op(Op.Pop, positional.length);
2630
1410
  }
2631
1411
 
1412
+ // Finish up by popping off and assigning blocks
1413
+ for (const symbol of reverse(blockSymbols)) {
1414
+ op(Op.SetBlock, symbol + 1);
1415
+ }
1416
+ op(Op.Constant, layoutOperand(layout));
1417
+ op(Op.CompileBlock);
1418
+ op(MachineOp.InvokeVirtual);
1419
+ op(Op.DidRenderLayout, $s0);
1420
+ op(MachineOp.PopFrame);
1421
+ op(Op.PopScope);
1422
+ if (hasCapability(capabilities, InternalComponentCapabilities.dynamicScope)) {
1423
+ op(Op.PopDynamicScope);
1424
+ }
1425
+ op(Op.CommitComponentTransaction);
1426
+ op(Op.Load, $s0);
1427
+ }
1428
+ function InvokeNonStaticComponent(op, _ref2) {
1429
+ let {
1430
+ capabilities,
1431
+ elementBlock,
1432
+ positional,
1433
+ named,
1434
+ atNames,
1435
+ blocks: namedBlocks,
1436
+ layout
1437
+ } = _ref2;
1438
+ let bindableBlocks = !!namedBlocks;
1439
+ let bindableAtNames = capabilities === true || hasCapability(capabilities, InternalComponentCapabilities.prepareArgs) || !!(named && named[0].length !== 0);
1440
+ let blocks = namedBlocks.with('attrs', elementBlock);
1441
+ op(Op.Fetch, $s0);
1442
+ op(Op.Dup, $sp, 1);
1443
+ op(Op.Load, $s0);
1444
+ op(MachineOp.PushFrame);
1445
+ CompileArgs(op, positional, named, blocks, atNames);
1446
+ op(Op.PrepareArgs, $s0);
1447
+ invokePreparedComponent(op, blocks.has('default'), bindableBlocks, bindableAtNames, () => {
1448
+ if (layout) {
1449
+ op(Op.PushSymbolTable, symbolTableOperand(layout.symbolTable));
1450
+ op(Op.Constant, layoutOperand(layout));
1451
+ op(Op.CompileBlock);
1452
+ } else {
1453
+ op(Op.GetComponentLayout, $s0);
1454
+ }
1455
+ op(Op.PopulateLayout, $s0);
1456
+ });
1457
+ op(Op.Load, $s0);
1458
+ }
1459
+ function WrappedComponent(op, layout, attrsBlockNumber) {
1460
+ op(HighLevelBuilderOpcodes.StartLabels);
1461
+ WithSavedRegister(op, $s1, () => {
1462
+ op(Op.GetComponentTagName, $s0);
1463
+ op(Op.PrimitiveReference);
1464
+ op(Op.Dup, $sp, 0);
1465
+ });
1466
+ op(Op.JumpUnless, labelOperand('BODY'));
1467
+ op(Op.Fetch, $s1);
1468
+ op(Op.PutComponentOperations);
1469
+ op(Op.OpenDynamicElement);
1470
+ op(Op.DidCreateElement, $s0);
1471
+ YieldBlock(op, attrsBlockNumber, null);
1472
+ op(Op.FlushElement);
1473
+ op(HighLevelBuilderOpcodes.Label, 'BODY');
1474
+ InvokeStaticBlock(op, [layout.block[0], []]);
1475
+ op(Op.Fetch, $s1);
1476
+ op(Op.JumpUnless, labelOperand('END'));
1477
+ op(Op.CloseElement);
1478
+ op(HighLevelBuilderOpcodes.Label, 'END');
1479
+ op(Op.Load, $s1);
1480
+ op(HighLevelBuilderOpcodes.StopLabels);
1481
+ }
1482
+ function invokePreparedComponent(op, hasBlock, bindableBlocks, bindableAtNames) {
1483
+ let populateLayout = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
1484
+ op(Op.BeginComponentTransaction, $s0);
1485
+ op(Op.PushDynamicScope);
1486
+ op(Op.CreateComponent, hasBlock | 0, $s0);
1487
+
1488
+ // this has to run after createComponent to allow
1489
+ // for late-bound layouts, but a caller is free
1490
+ // to populate the layout earlier if it wants to
1491
+ // and do nothing here.
1492
+ if (populateLayout) {
1493
+ populateLayout();
1494
+ }
1495
+ op(Op.RegisterComponentDestructor, $s0);
1496
+ op(Op.GetComponentSelf, $s0);
1497
+ op(Op.VirtualRootScope, $s0);
1498
+ op(Op.SetVariable, 0);
1499
+ op(Op.SetupForEval, $s0);
1500
+ if (bindableAtNames) op(Op.SetNamedVariables, $s0);
1501
+ if (bindableBlocks) op(Op.SetBlocks, $s0);
1502
+ op(Op.Pop, 1);
1503
+ op(Op.InvokeComponentLayout, $s0);
1504
+ op(Op.DidRenderLayout, $s0);
1505
+ op(MachineOp.PopFrame);
1506
+ op(Op.PopScope);
1507
+ op(Op.PopDynamicScope);
1508
+ op(Op.CommitComponentTransaction);
1509
+ }
1510
+ function InvokeBareComponent(op) {
1511
+ op(Op.Fetch, $s0);
1512
+ op(Op.Dup, $sp, 1);
1513
+ op(Op.Load, $s0);
1514
+ op(MachineOp.PushFrame);
1515
+ op(Op.PushEmptyArgs);
1516
+ op(Op.PrepareArgs, $s0);
1517
+ invokePreparedComponent(op, false, false, true, () => {
1518
+ op(Op.GetComponentLayout, $s0);
1519
+ op(Op.PopulateLayout, $s0);
1520
+ });
1521
+ op(Op.Load, $s0);
2632
1522
  }
2633
-
2634
- function isBuilderOpcode(op) {
2635
- return op < 1000
2636
- /* Start */
2637
- ;
1523
+ function WithSavedRegister(op, register, block) {
1524
+ op(Op.Fetch, register);
1525
+ block();
1526
+ op(Op.Load, register);
2638
1527
  }
2639
1528
 
2640
1529
  function main(op) {
2641
- op(75
2642
- /* Main */
2643
- , $s0);
1530
+ op(Op.Main, $s0);
2644
1531
  invokePreparedComponent(op, false, false, true);
2645
1532
  }
1533
+
2646
1534
  /**
2647
1535
  * Append content to the DOM. This standard function triages content and does the
2648
1536
  * right thing based upon whether it's a string, safe string, component, fragment
@@ -2651,97 +1539,48 @@ function main(op) {
2651
1539
  * @param trusting whether to interpolate a string as raw HTML (corresponds to
2652
1540
  * triple curlies)
2653
1541
  */
2654
-
2655
1542
  function StdAppend(op, trusting, nonDynamicAppend) {
2656
- SwitchCases(op, () => op(76
2657
- /* ContentType */
2658
- ), when => {
2659
- when(2
2660
- /* String */
2661
- , () => {
1543
+ SwitchCases(op, () => op(Op.ContentType), when => {
1544
+ when(ContentType.String, () => {
2662
1545
  if (trusting) {
2663
- op(68
2664
- /* AssertSame */
2665
- );
2666
- op(43
2667
- /* AppendHTML */
2668
- );
1546
+ op(Op.AssertSame);
1547
+ op(Op.AppendHTML);
2669
1548
  } else {
2670
- op(47
2671
- /* AppendText */
2672
- );
1549
+ op(Op.AppendText);
2673
1550
  }
2674
1551
  });
2675
-
2676
1552
  if (typeof nonDynamicAppend === 'number') {
2677
- when(0
2678
- /* Component */
2679
- , () => {
2680
- op(81
2681
- /* ResolveCurriedComponent */
2682
- );
2683
- op(79
2684
- /* PushDynamicComponentInstance */
2685
- );
1553
+ when(ContentType.Component, () => {
1554
+ op(Op.ResolveCurriedComponent);
1555
+ op(Op.PushDynamicComponentInstance);
2686
1556
  InvokeBareComponent(op);
2687
1557
  });
2688
- when(1
2689
- /* Helper */
2690
- , () => {
1558
+ when(ContentType.Helper, () => {
2691
1559
  CallDynamic(op, null, null, () => {
2692
- op(3
2693
- /* InvokeStatic */
2694
- , nonDynamicAppend);
1560
+ op(MachineOp.InvokeStatic, nonDynamicAppend);
2695
1561
  });
2696
1562
  });
2697
1563
  } else {
2698
1564
  // when non-dynamic, we can no longer call the value (potentially because we've already called it)
2699
1565
  // this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM.
2700
- when(0
2701
- /* Component */
2702
- , () => {
2703
- op(47
2704
- /* AppendText */
2705
- );
1566
+ when(ContentType.Component, () => {
1567
+ op(Op.AppendText);
2706
1568
  });
2707
- when(1
2708
- /* Helper */
2709
- , () => {
2710
- op(47
2711
- /* AppendText */
2712
- );
1569
+ when(ContentType.Helper, () => {
1570
+ op(Op.AppendText);
2713
1571
  });
2714
1572
  }
2715
-
2716
- when(4
2717
- /* SafeString */
2718
- , () => {
2719
- op(68
2720
- /* AssertSame */
2721
- );
2722
- op(44
2723
- /* AppendSafeHTML */
2724
- );
1573
+ when(ContentType.SafeString, () => {
1574
+ op(Op.AssertSame);
1575
+ op(Op.AppendSafeHTML);
2725
1576
  });
2726
- when(5
2727
- /* Fragment */
2728
- , () => {
2729
- op(68
2730
- /* AssertSame */
2731
- );
2732
- op(45
2733
- /* AppendDocumentFragment */
2734
- );
1577
+ when(ContentType.Fragment, () => {
1578
+ op(Op.AssertSame);
1579
+ op(Op.AppendDocumentFragment);
2735
1580
  });
2736
- when(6
2737
- /* Node */
2738
- , () => {
2739
- op(68
2740
- /* AssertSame */
2741
- );
2742
- op(46
2743
- /* AppendNode */
2744
- );
1581
+ when(ContentType.Node, () => {
1582
+ op(Op.AssertSame);
1583
+ op(Op.AppendNode);
2745
1584
  });
2746
1585
  });
2747
1586
  }
@@ -2763,22 +1602,21 @@ const STDLIB_META = {
2763
1602
  owner: null,
2764
1603
  size: 0
2765
1604
  };
2766
-
2767
- function build(program, callback) {
1605
+ function build(program, builder) {
2768
1606
  let {
2769
1607
  constants,
2770
1608
  heap,
2771
1609
  resolver
2772
1610
  } = program;
2773
1611
  let encoder = new EncoderImpl(heap, STDLIB_META);
2774
-
2775
- function pushOp(...op) {
1612
+ function pushOp() {
1613
+ for (var _len = arguments.length, op = new Array(_len), _key = 0; _key < _len; _key++) {
1614
+ op[_key] = arguments[_key];
1615
+ }
2776
1616
  encodeOp(encoder, constants, resolver, STDLIB_META, op);
2777
1617
  }
2778
-
2779
- callback(pushOp);
1618
+ builder(pushOp);
2780
1619
  let result = encoder.commit(0);
2781
-
2782
1620
  if (typeof result !== 'number') {
2783
1621
  // This shouldn't be possible
2784
1622
  throw new Error(`Unexpected errors compiling std`);
@@ -2788,16 +1626,385 @@ function build(program, callback) {
2788
1626
  }
2789
1627
 
2790
1628
  class CompileTimeCompilationContextImpl {
2791
- constructor({
2792
- constants,
2793
- heap
2794
- }, resolver) {
1629
+ constants;
1630
+ heap;
1631
+ stdlib;
1632
+ constructor(_ref, resolver, createOp) {
1633
+ let {
1634
+ constants,
1635
+ heap
1636
+ } = _ref;
2795
1637
  this.resolver = resolver;
1638
+ this.createOp = createOp;
2796
1639
  this.constants = constants;
2797
1640
  this.heap = heap;
2798
1641
  this.stdlib = compileStd(this);
2799
1642
  }
1643
+ }
1644
+
1645
+ function programCompilationContext(artifacts, resolver, createOp) {
1646
+ return new CompileTimeCompilationContextImpl(artifacts, resolver, createOp);
1647
+ }
1648
+ function templateCompilationContext(program, meta) {
1649
+ let encoder = new EncoderImpl(program.heap, meta, program.stdlib);
1650
+ return {
1651
+ program,
1652
+ encoder,
1653
+ meta
1654
+ };
1655
+ }
1656
+
1657
+ const STATEMENTS = new Compilers();
1658
+ const INFLATE_ATTR_TABLE = ['class', 'id', 'value', 'name', 'type', 'style', 'href'];
1659
+ const INFLATE_TAG_TABLE = ['div', 'span', 'p', 'a'];
1660
+ function inflateTagName(tagName) {
1661
+ return typeof tagName === 'string' ? tagName : INFLATE_TAG_TABLE[tagName];
1662
+ }
1663
+ function inflateAttrName(attrName) {
1664
+ return typeof attrName === 'string' ? attrName : INFLATE_ATTR_TABLE[attrName];
1665
+ }
1666
+ STATEMENTS.add(SexpOpcodes.Comment, (op, sexp) => op(Op.Comment, sexp[1]));
1667
+ STATEMENTS.add(SexpOpcodes.CloseElement, op => op(Op.CloseElement));
1668
+ STATEMENTS.add(SexpOpcodes.FlushElement, op => op(Op.FlushElement));
1669
+ STATEMENTS.add(SexpOpcodes.Modifier, (op, _ref) => {
1670
+ let [, expression, positional, named] = _ref;
1671
+ if (isGetFreeModifier(expression)) {
1672
+ op(HighLevelResolutionOpcodes.Modifier, expression, handle => {
1673
+ op(MachineOp.PushFrame);
1674
+ SimpleArgs(op, positional, named, false);
1675
+ op(Op.Modifier, handle);
1676
+ op(MachineOp.PopFrame);
1677
+ });
1678
+ } else {
1679
+ expr(op, expression);
1680
+ op(MachineOp.PushFrame);
1681
+ SimpleArgs(op, positional, named, false);
1682
+ op(Op.Dup, $fp, 1);
1683
+ op(Op.DynamicModifier);
1684
+ op(MachineOp.PopFrame);
1685
+ }
1686
+ });
1687
+ STATEMENTS.add(SexpOpcodes.StaticAttr, (op, _ref2) => {
1688
+ let [, name, value, namespace] = _ref2;
1689
+ op(Op.StaticAttr, inflateAttrName(name), value, namespace ?? null);
1690
+ });
1691
+ STATEMENTS.add(SexpOpcodes.StaticComponentAttr, (op, _ref3) => {
1692
+ let [, name, value, namespace] = _ref3;
1693
+ op(Op.StaticComponentAttr, inflateAttrName(name), value, namespace ?? null);
1694
+ });
1695
+ STATEMENTS.add(SexpOpcodes.DynamicAttr, (op, _ref4) => {
1696
+ let [, name, value, namespace] = _ref4;
1697
+ expr(op, value);
1698
+ op(Op.DynamicAttr, inflateAttrName(name), false, namespace ?? null);
1699
+ });
1700
+ STATEMENTS.add(SexpOpcodes.TrustingDynamicAttr, (op, _ref5) => {
1701
+ let [, name, value, namespace] = _ref5;
1702
+ expr(op, value);
1703
+ op(Op.DynamicAttr, inflateAttrName(name), true, namespace ?? null);
1704
+ });
1705
+ STATEMENTS.add(SexpOpcodes.ComponentAttr, (op, _ref6) => {
1706
+ let [, name, value, namespace] = _ref6;
1707
+ expr(op, value);
1708
+ op(Op.ComponentAttr, inflateAttrName(name), false, namespace ?? null);
1709
+ });
1710
+ STATEMENTS.add(SexpOpcodes.TrustingComponentAttr, (op, _ref7) => {
1711
+ let [, name, value, namespace] = _ref7;
1712
+ expr(op, value);
1713
+ op(Op.ComponentAttr, inflateAttrName(name), true, namespace ?? null);
1714
+ });
1715
+ STATEMENTS.add(SexpOpcodes.OpenElement, (op, _ref8) => {
1716
+ let [, tag] = _ref8;
1717
+ op(Op.OpenElement, inflateTagName(tag));
1718
+ });
1719
+ STATEMENTS.add(SexpOpcodes.OpenElementWithSplat, (op, _ref9) => {
1720
+ let [, tag] = _ref9;
1721
+ op(Op.PutComponentOperations);
1722
+ op(Op.OpenElement, inflateTagName(tag));
1723
+ });
1724
+ STATEMENTS.add(SexpOpcodes.Component, (op, _ref10) => {
1725
+ let [, expr, elementBlock, named, blocks] = _ref10;
1726
+ if (isGetFreeComponent(expr)) {
1727
+ op(HighLevelResolutionOpcodes.Component, expr, component => {
1728
+ InvokeComponent(op, component, elementBlock, null, named, blocks);
1729
+ });
1730
+ } else {
1731
+ // otherwise, the component name was an expression, so resolve the expression
1732
+ // and invoke it as a dynamic component
1733
+ InvokeDynamicComponent(op, expr, elementBlock, null, named, blocks, true, true);
1734
+ }
1735
+ });
1736
+ STATEMENTS.add(SexpOpcodes.Yield, (op, _ref11) => {
1737
+ let [, to, params] = _ref11;
1738
+ return YieldBlock(op, to, params);
1739
+ });
1740
+ STATEMENTS.add(SexpOpcodes.AttrSplat, (op, _ref12) => {
1741
+ let [, to] = _ref12;
1742
+ return YieldBlock(op, to, null);
1743
+ });
1744
+ STATEMENTS.add(SexpOpcodes.Debugger, (op, _ref13) => {
1745
+ let [, debugInfo] = _ref13;
1746
+ return op(Op.Debugger, debugSymbolsOperand(), debugInfo);
1747
+ });
1748
+ STATEMENTS.add(SexpOpcodes.Append, (op, _ref14) => {
1749
+ let [, value] = _ref14;
1750
+ // Special case for static values
1751
+ if (!Array.isArray(value)) {
1752
+ op(Op.Text, value === null || value === undefined ? '' : String(value));
1753
+ } else if (isGetFreeOptionalComponentOrHelper(value)) {
1754
+ op(HighLevelResolutionOpcodes.OptionalComponentOrHelper, value, {
1755
+ ifComponent(component) {
1756
+ InvokeComponent(op, component, null, null, null, null);
1757
+ },
1758
+ ifHelper(handle) {
1759
+ op(MachineOp.PushFrame);
1760
+ Call(op, handle, null, null);
1761
+ op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
1762
+ op(MachineOp.PopFrame);
1763
+ },
1764
+ ifValue(handle) {
1765
+ op(MachineOp.PushFrame);
1766
+ op(Op.ConstantReference, handle);
1767
+ op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
1768
+ op(MachineOp.PopFrame);
1769
+ }
1770
+ });
1771
+ } else if (value[0] === SexpOpcodes.Call) {
1772
+ let [, expression, positional, named] = value;
1773
+ if (isGetFreeComponentOrHelper(expression)) {
1774
+ op(HighLevelResolutionOpcodes.ComponentOrHelper, expression, {
1775
+ ifComponent(component) {
1776
+ InvokeComponent(op, component, null, positional, hashToArgs(named), null);
1777
+ },
1778
+ ifHelper(handle) {
1779
+ op(MachineOp.PushFrame);
1780
+ Call(op, handle, positional, named);
1781
+ op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
1782
+ op(MachineOp.PopFrame);
1783
+ }
1784
+ });
1785
+ } else {
1786
+ SwitchCases(op, () => {
1787
+ expr(op, expression);
1788
+ op(Op.DynamicContentType);
1789
+ }, when => {
1790
+ when(ContentType.Component, () => {
1791
+ op(Op.ResolveCurriedComponent);
1792
+ op(Op.PushDynamicComponentInstance);
1793
+ InvokeNonStaticComponent(op, {
1794
+ capabilities: true,
1795
+ elementBlock: null,
1796
+ positional,
1797
+ named,
1798
+ atNames: false,
1799
+ blocks: namedBlocks(null)
1800
+ });
1801
+ });
1802
+ when(ContentType.Helper, () => {
1803
+ CallDynamic(op, positional, named, () => {
1804
+ op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append'));
1805
+ });
1806
+ });
1807
+ });
1808
+ }
1809
+ } else {
1810
+ op(MachineOp.PushFrame);
1811
+ expr(op, value);
1812
+ op(MachineOp.InvokeStatic, stdlibOperand('cautious-append'));
1813
+ op(MachineOp.PopFrame);
1814
+ }
1815
+ });
1816
+ STATEMENTS.add(SexpOpcodes.TrustingAppend, (op, _ref15) => {
1817
+ let [, value] = _ref15;
1818
+ if (!Array.isArray(value)) {
1819
+ op(Op.Text, value === null || value === undefined ? '' : String(value));
1820
+ } else {
1821
+ op(MachineOp.PushFrame);
1822
+ expr(op, value);
1823
+ op(MachineOp.InvokeStatic, stdlibOperand('trusting-append'));
1824
+ op(MachineOp.PopFrame);
1825
+ }
1826
+ });
1827
+ STATEMENTS.add(SexpOpcodes.Block, (op, _ref16) => {
1828
+ let [, expr, positional, named, blocks] = _ref16;
1829
+ if (isGetFreeComponent(expr)) {
1830
+ op(HighLevelResolutionOpcodes.Component, expr, component => {
1831
+ InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
1832
+ });
1833
+ } else {
1834
+ InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
1835
+ }
1836
+ });
1837
+ STATEMENTS.add(SexpOpcodes.InElement, (op, _ref17) => {
1838
+ let [, block, guid, destination, insertBefore] = _ref17;
1839
+ ReplayableIf(op, () => {
1840
+ expr(op, guid);
1841
+ if (insertBefore === undefined) {
1842
+ PushPrimitiveReference(op, undefined);
1843
+ } else {
1844
+ expr(op, insertBefore);
1845
+ }
1846
+ expr(op, destination);
1847
+ op(Op.Dup, $sp, 0);
1848
+ return 4;
1849
+ }, () => {
1850
+ op(Op.PushRemoteElement);
1851
+ InvokeStaticBlock(op, block);
1852
+ op(Op.PopRemoteElement);
1853
+ });
1854
+ });
1855
+ STATEMENTS.add(SexpOpcodes.If, (op, _ref18) => {
1856
+ let [, condition, block, inverse] = _ref18;
1857
+ return ReplayableIf(op, () => {
1858
+ expr(op, condition);
1859
+ op(Op.ToBoolean);
1860
+ return 1;
1861
+ }, () => {
1862
+ InvokeStaticBlock(op, block);
1863
+ }, inverse ? () => {
1864
+ InvokeStaticBlock(op, inverse);
1865
+ } : undefined);
1866
+ });
1867
+ STATEMENTS.add(SexpOpcodes.Each, (op, _ref19) => {
1868
+ let [, value, key, block, inverse] = _ref19;
1869
+ return Replayable(op, () => {
1870
+ if (key) {
1871
+ expr(op, key);
1872
+ } else {
1873
+ PushPrimitiveReference(op, null);
1874
+ }
1875
+ expr(op, value);
1876
+ return 2;
1877
+ }, () => {
1878
+ op(Op.EnterList, labelOperand('BODY'), labelOperand('ELSE'));
1879
+ op(MachineOp.PushFrame);
1880
+ op(Op.Dup, $fp, 1);
1881
+ op(MachineOp.ReturnTo, labelOperand('ITER'));
1882
+ op(HighLevelBuilderOpcodes.Label, 'ITER');
1883
+ op(Op.Iterate, labelOperand('BREAK'));
1884
+ op(HighLevelBuilderOpcodes.Label, 'BODY');
1885
+ InvokeStaticBlockWithStack(op, block, 2);
1886
+ op(Op.Pop, 2);
1887
+ op(MachineOp.Jump, labelOperand('FINALLY'));
1888
+ op(HighLevelBuilderOpcodes.Label, 'BREAK');
1889
+ op(MachineOp.PopFrame);
1890
+ op(Op.ExitList);
1891
+ op(MachineOp.Jump, labelOperand('FINALLY'));
1892
+ op(HighLevelBuilderOpcodes.Label, 'ELSE');
1893
+ if (inverse) {
1894
+ InvokeStaticBlock(op, inverse);
1895
+ }
1896
+ });
1897
+ });
1898
+ STATEMENTS.add(SexpOpcodes.With, (op, _ref20) => {
1899
+ let [, value, block, inverse] = _ref20;
1900
+ ReplayableIf(op, () => {
1901
+ expr(op, value);
1902
+ op(Op.Dup, $sp, 0);
1903
+ op(Op.ToBoolean);
1904
+ return 2;
1905
+ }, () => {
1906
+ InvokeStaticBlockWithStack(op, block, 1);
1907
+ }, () => {
1908
+ if (inverse) {
1909
+ InvokeStaticBlock(op, inverse);
1910
+ }
1911
+ });
1912
+ });
1913
+ STATEMENTS.add(SexpOpcodes.Let, (op, _ref21) => {
1914
+ let [, positional, block] = _ref21;
1915
+ let count = CompilePositional(op, positional);
1916
+ InvokeStaticBlockWithStack(op, block, count);
1917
+ });
1918
+ STATEMENTS.add(SexpOpcodes.WithDynamicVars, (op, _ref22) => {
1919
+ let [, named, block] = _ref22;
1920
+ if (named) {
1921
+ let [names, expressions] = named;
1922
+ CompilePositional(op, expressions);
1923
+ DynamicScope(op, names, () => {
1924
+ InvokeStaticBlock(op, block);
1925
+ });
1926
+ } else {
1927
+ InvokeStaticBlock(op, block);
1928
+ }
1929
+ });
1930
+ STATEMENTS.add(SexpOpcodes.InvokeComponent, (op, _ref23) => {
1931
+ let [, expr, positional, named, blocks] = _ref23;
1932
+ if (isGetFreeComponent(expr)) {
1933
+ op(HighLevelResolutionOpcodes.Component, expr, component => {
1934
+ InvokeComponent(op, component, null, positional, hashToArgs(named), blocks);
1935
+ });
1936
+ } else {
1937
+ InvokeDynamicComponent(op, expr, null, positional, named, blocks, false, false);
1938
+ }
1939
+ });
1940
+ function hashToArgs(hash) {
1941
+ if (hash === null) return null;
1942
+ let names = hash[0].map(key => `@${key}`);
1943
+ return [names, hash[1]];
1944
+ }
1945
+
1946
+ const PLACEHOLDER_HANDLE = -1;
1947
+ class CompilableTemplateImpl {
1948
+ compiled = null;
1949
+ constructor(statements, meta,
1950
+ // Part of CompilableTemplate
1951
+ symbolTable) {
1952
+ let moduleName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'plain block';
1953
+ this.statements = statements;
1954
+ this.meta = meta;
1955
+ this.symbolTable = symbolTable;
1956
+ this.moduleName = moduleName;
1957
+ }
2800
1958
 
1959
+ // Part of CompilableTemplate
1960
+ compile(context) {
1961
+ return maybeCompile(this, context);
1962
+ }
1963
+ }
1964
+ function compilable(layout, moduleName) {
1965
+ let [statements, symbols, hasEval] = layout.block;
1966
+ return new CompilableTemplateImpl(statements, meta(layout), {
1967
+ symbols,
1968
+ hasEval
1969
+ }, moduleName);
1970
+ }
1971
+ function maybeCompile(compilable, context) {
1972
+ if (compilable.compiled !== null) return compilable.compiled;
1973
+ compilable.compiled = PLACEHOLDER_HANDLE;
1974
+ let {
1975
+ statements,
1976
+ meta
1977
+ } = compilable;
1978
+ let result = compileStatements(statements, meta, context);
1979
+ compilable.compiled = result;
1980
+ return result;
1981
+ }
1982
+ function compileStatements(statements, meta, syntaxContext) {
1983
+ let sCompiler = STATEMENTS;
1984
+ let context = templateCompilationContext(syntaxContext, meta);
1985
+ let {
1986
+ encoder,
1987
+ program: {
1988
+ constants,
1989
+ resolver
1990
+ }
1991
+ } = context;
1992
+ function pushOp() {
1993
+ for (var _len = arguments.length, op = new Array(_len), _key = 0; _key < _len; _key++) {
1994
+ op[_key] = arguments[_key];
1995
+ }
1996
+ encodeOp(encoder, constants, resolver, meta, op);
1997
+ }
1998
+ for (const statement of statements) {
1999
+ sCompiler.compile(pushOp, statement);
2000
+ }
2001
+ let handle = context.encoder.commit(meta.size);
2002
+ return handle;
2003
+ }
2004
+ function compilableBlock(block, containing) {
2005
+ return new CompilableTemplateImpl(block[0], containing, {
2006
+ parameters: block[1] || EMPTY_ARRAY
2007
+ });
2801
2008
  }
2802
2009
 
2803
2010
  const DEFAULT_CAPABILITIES = {
@@ -2832,30 +2039,30 @@ const MINIMAL_CAPABILITIES = {
2832
2039
  };
2833
2040
 
2834
2041
  class WrappedBuilder {
2042
+ symbolTable;
2043
+ compiled = null;
2044
+ attrsBlockNumber;
2835
2045
  constructor(layout, moduleName) {
2836
2046
  this.layout = layout;
2837
2047
  this.moduleName = moduleName;
2838
- this.compiled = null;
2839
2048
  let {
2840
2049
  block
2841
2050
  } = layout;
2842
2051
  let [, symbols, hasEval] = block;
2843
- symbols = symbols.slice(); // ensure ATTRS_BLOCK is always included (only once) in the list of symbols
2052
+ symbols = symbols.slice();
2844
2053
 
2054
+ // ensure ATTRS_BLOCK is always included (only once) in the list of symbols
2845
2055
  let attrsBlockIndex = symbols.indexOf(ATTRS_BLOCK);
2846
-
2847
2056
  if (attrsBlockIndex === -1) {
2848
2057
  this.attrsBlockNumber = symbols.push(ATTRS_BLOCK);
2849
2058
  } else {
2850
2059
  this.attrsBlockNumber = attrsBlockIndex + 1;
2851
2060
  }
2852
-
2853
2061
  this.symbolTable = {
2854
2062
  hasEval,
2855
2063
  symbols
2856
2064
  };
2857
2065
  }
2858
-
2859
2066
  compile(syntax) {
2860
2067
  if (this.compiled !== null) return this.compiled;
2861
2068
  let m = meta(this.layout);
@@ -2867,23 +2074,20 @@ class WrappedBuilder {
2867
2074
  resolver
2868
2075
  }
2869
2076
  } = context;
2870
-
2871
- function pushOp(...op) {
2077
+ function pushOp() {
2078
+ for (var _len = arguments.length, op = new Array(_len), _key = 0; _key < _len; _key++) {
2079
+ op[_key] = arguments[_key];
2080
+ }
2872
2081
  encodeOp(encoder, constants, resolver, m, op);
2873
2082
  }
2874
-
2875
2083
  WrappedComponent(pushOp, this.layout, this.attrsBlockNumber);
2876
2084
  let handle = context.encoder.commit(m.size);
2877
-
2878
2085
  if (typeof handle !== 'number') {
2879
2086
  return handle;
2880
2087
  }
2881
-
2882
2088
  this.compiled = handle;
2883
-
2884
2089
  return handle;
2885
2090
  }
2886
-
2887
2091
  }
2888
2092
 
2889
2093
  let clientId = 0;
@@ -2891,34 +2095,36 @@ let templateCacheCounters = {
2891
2095
  cacheHit: 0,
2892
2096
  cacheMiss: 0
2893
2097
  };
2098
+
2099
+ // These interfaces are for backwards compatibility, some addons use these intimate APIs
2100
+
2894
2101
  /**
2895
2102
  * Wraps a template js in a template module to change it into a factory
2896
2103
  * that handles lazy parsing the template and to create per env singletons
2897
2104
  * of the template.
2898
2105
  */
2899
-
2900
- function templateFactory({
2901
- id: templateId,
2902
- moduleName,
2903
- block,
2904
- scope,
2905
- isStrictMode
2906
- }) {
2106
+ function templateFactory(_ref) {
2107
+ let {
2108
+ id: templateId,
2109
+ moduleName,
2110
+ block,
2111
+ scope,
2112
+ isStrictMode
2113
+ } = _ref;
2907
2114
  // TODO(template-refactors): This should be removed in the near future, as it
2908
2115
  // appears that id is unused. It is currently kept for backwards compat reasons.
2909
- let id = templateId || `client-${clientId++}`; // TODO: This caches JSON serialized output once in case a template is
2116
+ let id = templateId || `client-${clientId++}`;
2117
+
2118
+ // TODO: This caches JSON serialized output once in case a template is
2910
2119
  // compiled by multiple owners, but we haven't verified if this is actually
2911
2120
  // helpful. We should benchmark this in the future.
2912
-
2913
2121
  let parsedBlock;
2914
2122
  let ownerlessTemplate = null;
2915
2123
  let templateCache = new WeakMap();
2916
-
2917
2124
  let factory = owner => {
2918
2125
  if (parsedBlock === undefined) {
2919
2126
  parsedBlock = JSON.parse(block);
2920
2127
  }
2921
-
2922
2128
  if (owner === undefined) {
2923
2129
  if (ownerlessTemplate === null) {
2924
2130
  templateCacheCounters.cacheMiss++;
@@ -2933,12 +2139,9 @@ function templateFactory({
2933
2139
  } else {
2934
2140
  templateCacheCounters.cacheHit++;
2935
2141
  }
2936
-
2937
2142
  return ownerlessTemplate;
2938
2143
  }
2939
-
2940
2144
  let result = templateCache.get(owner);
2941
-
2942
2145
  if (result === undefined) {
2943
2146
  templateCacheCounters.cacheMiss++;
2944
2147
  result = new TemplateImpl({
@@ -2953,52 +2156,44 @@ function templateFactory({
2953
2156
  } else {
2954
2157
  templateCacheCounters.cacheHit++;
2955
2158
  }
2956
-
2957
2159
  return result;
2958
2160
  };
2959
-
2960
2161
  factory.__id = id;
2961
2162
  factory.__meta = {
2962
2163
  moduleName
2963
2164
  };
2964
2165
  return factory;
2965
2166
  }
2966
-
2967
2167
  class TemplateImpl {
2168
+ result = 'ok';
2169
+ layout = null;
2170
+ wrappedLayout = null;
2968
2171
  constructor(parsedLayout) {
2969
2172
  this.parsedLayout = parsedLayout;
2970
- this.result = 'ok';
2971
- this.layout = null;
2972
- this.wrappedLayout = null;
2973
2173
  }
2974
-
2975
2174
  get moduleName() {
2976
2175
  return this.parsedLayout.moduleName;
2977
2176
  }
2978
-
2979
2177
  get id() {
2980
2178
  return this.parsedLayout.id;
2981
- } // TODO(template-refactors): This should be removed in the near future, it is
2982
- // only being exposed for backwards compatibility
2983
-
2179
+ }
2984
2180
 
2181
+ // TODO(template-refactors): This should be removed in the near future, it is
2182
+ // only being exposed for backwards compatibility
2985
2183
  get referrer() {
2986
2184
  return {
2987
2185
  moduleName: this.parsedLayout.moduleName,
2988
2186
  owner: this.parsedLayout.owner
2989
2187
  };
2990
2188
  }
2991
-
2992
2189
  asLayout() {
2993
2190
  if (this.layout) return this.layout;
2994
2191
  return this.layout = compilable(assign({}, this.parsedLayout), this.moduleName);
2995
2192
  }
2996
-
2997
2193
  asWrappedLayout() {
2998
2194
  if (this.wrappedLayout) return this.wrappedLayout;
2999
2195
  return this.wrappedLayout = new WrappedBuilder(assign({}, this.parsedLayout), this.moduleName);
3000
2196
  }
3001
-
3002
2197
  }
3003
2198
 
3004
2199
  export { CompileTimeCompilationContextImpl, DEFAULT_CAPABILITIES, EMPTY_BLOCKS, MINIMAL_CAPABILITIES, StdLib, WrappedBuilder, compilable, compileStatements, compileStd, debugCompiler, InvokeStaticBlock as invokeStaticBlock, InvokeStaticBlockWithStack as invokeStaticBlockWithStack, meta, programCompilationContext, templateCacheCounters, templateCompilationContext, templateFactory };