-
-
Notifications
You must be signed in to change notification settings - Fork 147
/
template-compiler.js
307 lines (307 loc) · 15.5 KB
/
template-compiler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "tslib", "@aurelia/jit", "@aurelia/kernel", "@aurelia/runtime", "@aurelia/runtime-html", "./attribute-syntax-transformer", "./template-binder", "./template-element-factory"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jit_1 = require("@aurelia/jit");
const kernel_1 = require("@aurelia/kernel");
const runtime_1 = require("@aurelia/runtime");
const runtime_html_1 = require("@aurelia/runtime-html");
const attribute_syntax_transformer_1 = require("./attribute-syntax-transformer");
const template_binder_1 = require("./template-binder");
const template_element_factory_1 = require("./template-element-factory");
class CustomElementCompilationUnit {
constructor(partialDefinition, surrogate, template) {
this.partialDefinition = partialDefinition;
this.surrogate = surrogate;
this.template = template;
this.instructions = [];
this.surrogates = [];
this.scopeParts = [];
this.parts = {};
}
toDefinition() {
const def = this.partialDefinition;
return runtime_1.CustomElementDefinition.create({
...def,
instructions: kernel_1.mergeArrays(def.instructions, this.instructions),
surrogates: kernel_1.mergeArrays(def.surrogates, this.surrogates),
scopeParts: kernel_1.mergeArrays(def.scopeParts, this.scopeParts),
template: this.template,
needsCompile: false,
hasSlots: this.surrogate.hasSlots,
});
}
}
/**
* Default (runtime-agnostic) implementation for `ITemplateCompiler`.
*
* @internal
*/
let TemplateCompiler = class TemplateCompiler {
constructor(factory, attrParser, exprParser, attrSyntaxModifier) {
this.factory = factory;
this.attrParser = attrParser;
this.exprParser = exprParser;
this.attrSyntaxModifier = attrSyntaxModifier;
}
get name() {
return 'default';
}
static register(container) {
return kernel_1.Registration.singleton(runtime_1.ITemplateCompiler, this).register(container);
}
compile(partialDefinition, context) {
const definition = runtime_1.CustomElementDefinition.getOrCreate(partialDefinition);
if (definition.template === null || definition.template === void 0) {
return definition;
}
const resources = jit_1.ResourceModel.getOrCreate(context);
const { attrParser, exprParser, attrSyntaxModifier, factory } = this;
const binder = new template_binder_1.TemplateBinder(context.get(runtime_1.IDOM), resources, attrParser, exprParser, attrSyntaxModifier);
const template = factory.createTemplate(definition.template);
const surrogate = binder.bind(template);
const compilation = this.compilation = new CustomElementCompilationUnit(definition, surrogate, template);
const customAttributes = surrogate.customAttributes;
const plainAttributes = surrogate.plainAttributes;
const customAttributeLength = customAttributes.length;
const plainAttributeLength = plainAttributes.length;
if (customAttributeLength + plainAttributeLength > 0) {
let offset = 0;
for (let i = 0; customAttributeLength > i; ++i) {
compilation.surrogates[offset] = this.compileCustomAttribute(customAttributes[i]);
offset++;
}
for (let i = 0; i < plainAttributeLength; ++i) {
compilation.surrogates[offset] = this.compilePlainAttribute(plainAttributes[i], true);
offset++;
}
}
this.compileChildNodes(surrogate, compilation.instructions, compilation.scopeParts);
const compiledDefinition = compilation.toDefinition();
this.compilation = null;
return compiledDefinition;
}
compileChildNodes(parent, instructionRows, scopeParts) {
if ((parent.flags & 8192 /* hasChildNodes */) > 0) {
const childNodes = parent.childNodes;
const ii = childNodes.length;
let childNode;
for (let i = 0; i < ii; ++i) {
childNode = childNodes[i];
if ((childNode.flags & 128 /* isText */) > 0) {
instructionRows.push([new runtime_html_1.TextBindingInstruction(childNode.interpolation)]);
}
else if ((childNode.flags & 32 /* isLetElement */) > 0) {
const bindings = childNode.bindings;
const instructions = [];
let binding;
const jj = bindings.length;
for (let j = 0; j < jj; ++j) {
binding = bindings[j];
instructions[j] = new runtime_1.LetBindingInstruction(binding.expression, binding.target);
}
instructionRows.push([new runtime_1.LetElementInstruction(instructions, childNode.toBindingContext)]);
}
else {
this.compileParentNode(childNode, instructionRows, scopeParts);
}
}
}
}
compileCustomElement(symbol, instructionRows, scopeParts) {
// offset 1 to leave a spot for the hydrate instruction so we don't need to create 2 arrays with a spread etc
const instructionRow = this.compileAttributes(symbol, 1);
instructionRow[0] = new runtime_1.HydrateElementInstruction(symbol.res, this.compileBindings(symbol), this.compileParts(symbol, scopeParts));
instructionRows.push(instructionRow);
this.compileChildNodes(symbol, instructionRows, scopeParts);
}
compilePlainElement(symbol, instructionRows, scopeParts) {
const attributes = this.compileAttributes(symbol, 0);
if (attributes.length > 0) {
instructionRows.push(attributes);
}
this.compileChildNodes(symbol, instructionRows, scopeParts);
}
compileParentNode(symbol, instructionRows, scopeParts) {
switch (symbol.flags & 511 /* type */) {
case 16 /* isCustomElement */:
this.compileCustomElement(symbol, instructionRows, scopeParts);
break;
case 64 /* isPlainElement */:
this.compilePlainElement(symbol, instructionRows, scopeParts);
break;
case 1 /* isTemplateController */:
this.compileTemplateController(symbol, instructionRows, scopeParts);
}
}
compileTemplateController(symbol, instructionRows, scopeParts) {
const bindings = this.compileBindings(symbol);
const controllerInstructionRows = [];
const controllerScopeParts = [];
this.compileParentNode(symbol.template, controllerInstructionRows, controllerScopeParts);
kernel_1.mergeDistinct(scopeParts, controllerScopeParts, false);
const def = runtime_1.CustomElementDefinition.create({
name: symbol.partName === null ? symbol.res : symbol.partName,
scopeParts: controllerScopeParts,
template: symbol.physicalNode,
instructions: controllerInstructionRows,
needsCompile: false,
});
let parts = void 0;
if ((symbol.flags & 16384 /* hasParts */) > 0) {
parts = {};
for (const part of symbol.parts) {
parts[part.name] = this.compilation.parts[part.name];
}
}
instructionRows.push([new runtime_1.HydrateTemplateController(def, symbol.res, bindings, symbol.res === 'else', parts)]);
}
compileBindings(symbol) {
let bindingInstructions;
if ((symbol.flags & 4096 /* hasBindings */) > 0) {
// either a custom element with bindings, a custom attribute / template controller with dynamic options,
// or a single value custom attribute binding
const { bindings } = symbol;
const len = bindings.length;
bindingInstructions = Array(len);
let i = 0;
for (; i < len; ++i) {
bindingInstructions[i] = this.compileBinding(bindings[i]);
}
}
else {
bindingInstructions = kernel_1.PLATFORM.emptyArray;
}
return bindingInstructions;
}
compileBinding(symbol) {
if (symbol.command === null) {
// either an interpolation or a normal string value assigned to an element or attribute binding
if (symbol.expression === null) {
// the template binder already filtered out non-bindables, so we know we need a setProperty here
return new runtime_1.SetPropertyInstruction(symbol.rawValue, symbol.bindable.propName);
}
else {
// either an element binding interpolation or a dynamic options attribute binding interpolation
return new runtime_1.InterpolationInstruction(symbol.expression, symbol.bindable.propName);
}
}
else {
// either an element binding command, dynamic options attribute binding command,
// or custom attribute / template controller (single value) binding command
return symbol.command.compile(symbol);
}
}
compileAttributes(symbol, offset) {
let attributeInstructions;
if ((symbol.flags & 2048 /* hasAttributes */) > 0) {
// any attributes on a custom element (which are not bindables) or a plain element
const customAttributes = symbol.customAttributes;
const plainAttributes = symbol.plainAttributes;
const customAttributeLength = customAttributes.length;
const plainAttributesLength = plainAttributes.length;
attributeInstructions = Array(offset + customAttributeLength + plainAttributesLength);
for (let i = 0; customAttributeLength > i; ++i) {
attributeInstructions[offset] = this.compileCustomAttribute(customAttributes[i]);
offset++;
}
for (let i = 0; plainAttributesLength > i; ++i) {
attributeInstructions[offset] = this.compilePlainAttribute(plainAttributes[i], false);
offset++;
}
}
else if (offset > 0) {
attributeInstructions = Array(offset);
}
else {
attributeInstructions = kernel_1.PLATFORM.emptyArray;
}
return attributeInstructions;
}
compileCustomAttribute(symbol) {
// a normal custom attribute (not template controller)
const bindings = this.compileBindings(symbol);
return new runtime_1.HydrateAttributeInstruction(symbol.res, bindings);
}
compilePlainAttribute(symbol, isOnSurrogate) {
if (symbol.command === null) {
const syntax = symbol.syntax;
if (symbol.expression === null) {
const attrRawValue = syntax.rawValue;
if (isOnSurrogate) {
switch (syntax.target) {
case 'class':
return new runtime_html_1.SetClassAttributeInstruction(attrRawValue);
case 'style':
return new runtime_html_1.SetStyleAttributeInstruction(attrRawValue);
// todo: define how to merge other attribute peacefully
// this is an existing feature request
}
}
// a plain attribute on a surrogate
return new runtime_html_1.SetAttributeInstruction(attrRawValue, syntax.target);
}
else {
// a plain attribute with an interpolation
return new runtime_1.InterpolationInstruction(symbol.expression, syntax.target);
}
}
else {
// a plain attribute with a binding command
return symbol.command.compile(symbol);
}
}
// private compileAttribute(symbol: IAttributeSymbol): HTMLAttributeInstruction {
// // any attribute on a custom element (which is not a bindable) or a plain element
// if (symbol.flags & SymbolFlags.isCustomAttribute) {
// return this.compileCustomAttribute(symbol as CustomAttributeSymbol);
// } else {
// return this.compilePlainAttribute(symbol as PlainAttributeSymbol);
// }
// }
compileParts(symbol, scopeParts) {
const parts = {};
if ((symbol.flags & 16384 /* hasParts */) > 0) {
const replaceParts = symbol.parts;
const len = replaceParts.length;
let s = scopeParts.length;
for (let i = 0; i < len; ++i) {
const replacePart = replaceParts[i];
if (!scopeParts.includes(replacePart.name)) {
scopeParts[s++] = replacePart.name;
}
const partScopeParts = [];
const partInstructionRows = [];
this.compileParentNode(replacePart.template, partInstructionRows, partScopeParts);
// TODO: the assignment to `this.compilation.parts[replacePart.name]` might be the cause of replaceable bug reported by rluba
// need to verify this
this.compilation.parts[replacePart.name] = parts[replacePart.name] = runtime_1.CustomElementDefinition.create({
name: replacePart.name,
scopeParts: partScopeParts,
template: replacePart.physicalNode,
instructions: partInstructionRows,
needsCompile: false,
});
}
}
return parts;
}
};
TemplateCompiler = tslib_1.__decorate([
tslib_1.__param(0, template_element_factory_1.ITemplateElementFactory),
tslib_1.__param(1, jit_1.IAttributeParser),
tslib_1.__param(2, runtime_1.IExpressionParser),
tslib_1.__param(3, attribute_syntax_transformer_1.IAttrSyntaxTransformer),
tslib_1.__metadata("design:paramtypes", [Object, Object, Object, Object])
], TemplateCompiler);
exports.TemplateCompiler = TemplateCompiler;
});
//# sourceMappingURL=template-compiler.js.map