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