vsn 0.1.43 → 0.1.46
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/demo/demo.html +7 -2
- package/demo/markup.html +2 -0
- package/demo/vsn.js +1 -1
- package/demo/xhr.vsn +4 -0
- package/dist/AST/ArithmeticAssignmentNode.js +8 -1
- package/dist/AST/ArithmeticAssignmentNode.js.map +1 -1
- package/dist/AST/FunctionNode.d.ts +0 -0
- package/dist/AST/FunctionNode.js +1 -0
- package/dist/AST/FunctionNode.js.map +1 -0
- package/dist/AST/StringFormatNode.d.ts +18 -0
- package/dist/{attributes/ClickToggleClass.js → AST/StringFormatNode.js} +49 -49
- package/dist/AST/StringFormatNode.js.map +1 -0
- package/dist/AST/WASM/Context.d.ts +4 -0
- package/dist/AST/WASM/Context.js +18 -0
- package/dist/AST/WASM/Context.js.map +1 -0
- package/dist/AST/WASM/Function.d.ts +22 -0
- package/dist/AST/WASM/Function.js +110 -0
- package/dist/AST/WASM/Function.js.map +1 -0
- package/dist/AST/WASM/Memory.d.ts +12 -0
- package/dist/AST/WASM/Memory.js +22 -0
- package/dist/AST/WASM/Memory.js.map +1 -0
- package/dist/AST/WASM/Section.d.ts +5 -0
- package/dist/AST/WASM/Section.js +11 -0
- package/dist/AST/WASM/Section.js.map +1 -0
- package/dist/AST/WASM.d.ts +58 -0
- package/dist/AST/WASM.js +277 -0
- package/dist/AST/WASM.js.map +1 -0
- package/dist/AST/XHRNode.d.ts +15 -0
- package/dist/AST/XHRNode.js +146 -0
- package/dist/AST/XHRNode.js.map +1 -0
- package/dist/AST.d.ts +62 -55
- package/dist/AST.js +123 -83
- package/dist/AST.js.map +1 -1
- package/dist/DOM/DOMObject.d.ts +1 -0
- package/dist/DOM/DOMObject.js +6 -0
- package/dist/DOM/DOMObject.js.map +1 -1
- package/dist/DOM.js +61 -90
- package/dist/DOM.js.map +1 -1
- package/dist/Registry.d.ts +2 -0
- package/dist/Registry.js +13 -9
- package/dist/Registry.js.map +1 -1
- package/dist/Scope/ScopeDataAbstract.js +2 -2
- package/dist/Scope/ScopeDataAbstract.js.map +1 -1
- package/dist/Scope/properties/Property.d.ts +5 -6
- package/dist/Scope/properties/Property.js +17 -25
- package/dist/Scope/properties/Property.js.map +1 -1
- package/dist/Scope/properties/_imports.d.ts +1 -1
- package/dist/Scope/properties/_imports.js.map +1 -1
- package/dist/Tag.d.ts +1 -0
- package/dist/Tag.js +9 -11
- package/dist/Tag.js.map +1 -1
- package/dist/attributes/StandardAttribute.js +4 -1
- package/dist/attributes/StandardAttribute.js.map +1 -1
- package/dist/attributes/_imports.d.ts +0 -2
- package/dist/attributes/_imports.js +1 -5
- package/dist/attributes/_imports.js.map +1 -1
- package/dist/helpers/VisionHelper.d.ts +1 -0
- package/dist/helpers/VisionHelper.js +17 -0
- package/dist/helpers/VisionHelper.js.map +1 -1
- package/dist/vsn.d.ts +3 -2
- package/dist/vsn.js +7 -3
- package/dist/vsn.js.map +1 -1
- package/package.json +1 -1
- package/src/AST/ArithmeticAssignmentNode.ts +9 -2
- package/src/AST/FunctionNode.ts +0 -0
- package/src/AST/StringFormatNode.ts +43 -0
- package/src/AST/WASM/Context.ts +12 -0
- package/src/AST/WASM/Function.ts +67 -0
- package/src/AST/WASM/Memory.ts +21 -0
- package/src/AST/WASM/Section.ts +6 -0
- package/src/AST/WASM.ts +244 -0
- package/src/AST/XHRNode.ts +81 -0
- package/src/AST.ts +66 -31
- package/src/DOM/DOMObject.ts +6 -0
- package/src/DOM.ts +11 -25
- package/src/Registry.ts +12 -9
- package/src/Scope/ScopeDataAbstract.ts +2 -2
- package/src/Scope/properties/Property.ts +17 -28
- package/src/Scope/properties/_imports.ts +1 -1
- package/src/Tag.ts +10 -9
- package/src/attributes/AddClassIf.ts +1 -1
- package/src/attributes/StandardAttribute.ts +4 -2
- package/src/attributes/_imports.ts +0 -2
- package/src/helpers/VisionHelper.ts +13 -0
- package/src/vsn.ts +3 -2
- package/test/AST/ArithmeticAssignmentNode.spec.ts +0 -2
- package/test/AST/StringFormatNode.spec.ts +12 -0
- package/test/AST/WASM.spec.ts +63 -0
- package/test/AST/XHRNode.spec.ts +10 -0
- package/test/Scope/ScopeData.spec.ts +5 -5
- package/types/vsn-component.d.ts +5 -0
- package/dist/attributes/ClickRemoveClass.d.ts +0 -8
- package/dist/attributes/ClickRemoveClass.js +0 -114
- package/dist/attributes/ClickRemoveClass.js.map +0 -1
- package/dist/attributes/ClickToggleClass.d.ts +0 -8
- package/dist/attributes/ClickToggleClass.js.map +0 -1
- package/src/attributes/ClickRemoveClass.ts +0 -30
- package/src/attributes/ClickToggleClass.ts +0 -30
package/src/AST/WASM.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import {VisionHelper} from "../helpers/VisionHelper";
|
|
2
|
+
import {FunctionSection} from "./WASM/Function";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const dummyFunc = (...args: any[]): any => null;
|
|
6
|
+
const dummyVal = null;
|
|
7
|
+
|
|
8
|
+
let _ieee754 = dummyFunc;
|
|
9
|
+
let _encodeString = dummyFunc;
|
|
10
|
+
let _signedLEB128 = dummyFunc;
|
|
11
|
+
let _unsignedLEB128 = dummyFunc;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_ieee754 = (n: number) => {
|
|
15
|
+
const buf = Buffer.allocUnsafe(4);
|
|
16
|
+
buf.writeFloatLE(n, 0);
|
|
17
|
+
return Uint8Array.from(buf);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
_encodeString = (str: string) => [
|
|
21
|
+
str.length,
|
|
22
|
+
...str.split("").map(s => s.charCodeAt(0))
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
_signedLEB128 = (n: number) => {
|
|
26
|
+
const buffer = [];
|
|
27
|
+
let more = true;
|
|
28
|
+
const isNegative = n < 0;
|
|
29
|
+
const bitCount = Math.ceil(Math.log2(Math.abs(n))) + 1;
|
|
30
|
+
while (more) {
|
|
31
|
+
let byte = n & 0x7f;
|
|
32
|
+
n >>= 7;
|
|
33
|
+
if (isNegative) {
|
|
34
|
+
n = n | -(1 << (bitCount - 8));
|
|
35
|
+
}
|
|
36
|
+
if ((n === 0 && (byte & 0x40) === 0) || (n === -1 && (byte & 0x40) !== 0x40)) {
|
|
37
|
+
more = false;
|
|
38
|
+
} else {
|
|
39
|
+
byte |= 0x80;
|
|
40
|
+
}
|
|
41
|
+
buffer.push(byte);
|
|
42
|
+
}
|
|
43
|
+
return buffer;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
_unsignedLEB128 = (n: number) => {
|
|
47
|
+
const buffer = [];
|
|
48
|
+
do {
|
|
49
|
+
let byte = n & 0x7f;
|
|
50
|
+
n >>>= 7;
|
|
51
|
+
if (n !== 0) {
|
|
52
|
+
byte |= 0x80;
|
|
53
|
+
}
|
|
54
|
+
buffer.push(byte);
|
|
55
|
+
} while (n !== 0);
|
|
56
|
+
return buffer;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export const ieee754 = _ieee754;
|
|
61
|
+
export const encodeString = _encodeString;
|
|
62
|
+
export const signedLEB128 = _signedLEB128;
|
|
63
|
+
export const unsignedLEB128 = _unsignedLEB128;
|
|
64
|
+
|
|
65
|
+
export const flatten = (arr: any[]) => {
|
|
66
|
+
return [].concat.apply([], arr);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
enum ESectionType {
|
|
70
|
+
custom = 0,
|
|
71
|
+
type = 1,
|
|
72
|
+
import = 2,
|
|
73
|
+
func = 3,
|
|
74
|
+
table = 4,
|
|
75
|
+
memory = 5,
|
|
76
|
+
global = 6,
|
|
77
|
+
export = 7,
|
|
78
|
+
start = 8,
|
|
79
|
+
element = 9,
|
|
80
|
+
code = 10,
|
|
81
|
+
data = 11
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// https://webassembly.github.io/spec/core/binary/types.html
|
|
85
|
+
export enum EValueType {
|
|
86
|
+
i32 = 0x7f,
|
|
87
|
+
f32 = 0x7d
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// https://webassembly.github.io/spec/core/binary/types.html#binary-blocktype
|
|
91
|
+
export enum EBlockType {
|
|
92
|
+
void = 0x40
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// https://webassembly.github.io/spec/core/binary/instructions.html
|
|
96
|
+
export enum EOpCode {
|
|
97
|
+
block = 0x02,
|
|
98
|
+
loop = 0x03,
|
|
99
|
+
br = 0x0c,
|
|
100
|
+
br_if = 0x0d,
|
|
101
|
+
end = 0x0b,
|
|
102
|
+
call = 0x10,
|
|
103
|
+
get_local = 0x20,
|
|
104
|
+
set_local = 0x21,
|
|
105
|
+
i32_store_8 = 0x3a,
|
|
106
|
+
i32_const = 0x41,
|
|
107
|
+
f32_const = 0x43,
|
|
108
|
+
i32_add = 0x6a,
|
|
109
|
+
i32_sub = 0x6B,
|
|
110
|
+
i32_mul = 0x6C,
|
|
111
|
+
i32_div = 0x6D,
|
|
112
|
+
i32_eqz = 0x45,
|
|
113
|
+
i32_eq = 0x46,
|
|
114
|
+
f32_eq = 0x5b,
|
|
115
|
+
f32_lt = 0x5d,
|
|
116
|
+
f32_gt = 0x5e,
|
|
117
|
+
i32_and = 0x71,
|
|
118
|
+
f32_add = 0x92,
|
|
119
|
+
f32_sub = 0x93,
|
|
120
|
+
f32_mul = 0x94,
|
|
121
|
+
f32_div = 0x95,
|
|
122
|
+
i32_trunc_f32_s = 0xa8,
|
|
123
|
+
memory_size = 0x3f,
|
|
124
|
+
memory_grow = 0x40,
|
|
125
|
+
|
|
126
|
+
// Vision op codes
|
|
127
|
+
scope_get = 0x400,
|
|
128
|
+
scope_set = 0x401
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const binaryOpcode = {
|
|
132
|
+
"+": EOpCode.f32_add,
|
|
133
|
+
"-": EOpCode.f32_sub,
|
|
134
|
+
"*": EOpCode.f32_mul,
|
|
135
|
+
"/": EOpCode.f32_div,
|
|
136
|
+
"==": EOpCode.f32_eq,
|
|
137
|
+
">": EOpCode.f32_gt,
|
|
138
|
+
"<": EOpCode.f32_lt,
|
|
139
|
+
"&&": EOpCode.i32_and
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// http://webassembly.github.io/spec/core/binary/modules.html#export-section
|
|
143
|
+
export enum EExportType {
|
|
144
|
+
func = 0x00,
|
|
145
|
+
table = 0x01,
|
|
146
|
+
mem = 0x02,
|
|
147
|
+
global = 0x03
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// http://webassembly.github.io/spec/core/binary/types.html#function-types
|
|
151
|
+
export const functionType = 0x60;
|
|
152
|
+
|
|
153
|
+
export const emptyArray = 0x0;
|
|
154
|
+
|
|
155
|
+
// https://webassembly.github.io/spec/core/binary/modules.html#binary-module
|
|
156
|
+
const magicModuleHeader = [0x00, 0x61, 0x73, 0x6d];
|
|
157
|
+
const moduleVersion = [0x01, 0x00, 0x00, 0x00];
|
|
158
|
+
|
|
159
|
+
// https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec
|
|
160
|
+
// Vectors are encoded with their length followed by their element sequence
|
|
161
|
+
export const encodeVector = (data: any[]) => [
|
|
162
|
+
...unsignedLEB128(data.length),
|
|
163
|
+
...flatten(data)
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
// https://webassembly.github.io/spec/core/binary/modules.html#code-section
|
|
167
|
+
export const encodeLocal = (count: number, type: EValueType) => [
|
|
168
|
+
...unsignedLEB128(count),
|
|
169
|
+
type
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
// https://webassembly.github.io/spec/core/binary/modules.html#sections
|
|
173
|
+
// sections are encoded by their type followed by their vector contents
|
|
174
|
+
const createSection = (sectionType: ESectionType, data: any[]) => [
|
|
175
|
+
sectionType,
|
|
176
|
+
...encodeVector(data)
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
Building a WASM program...
|
|
181
|
+
Based off of Chasm:
|
|
182
|
+
https://github.com/ColinEberhardt/chasm/blob/master/src/emitter.ts
|
|
183
|
+
https://webassembly.github.io/wabt/demo/wat2wasm/
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
export const emitter = (functions: FunctionSection[]) => {
|
|
187
|
+
// Types section
|
|
188
|
+
const typesSection = createSection(ESectionType.type, [
|
|
189
|
+
functions.length, // Number of types
|
|
190
|
+
...flatten(functions.map((func) => func.sectionTypes))
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
// Functions section
|
|
194
|
+
const functionsSection = createSection(ESectionType.func, [
|
|
195
|
+
functions.length, // number of functions
|
|
196
|
+
...functions.map((func, i) => i)
|
|
197
|
+
]);
|
|
198
|
+
|
|
199
|
+
// Export section
|
|
200
|
+
const exportSection = createSection(
|
|
201
|
+
ESectionType.export,
|
|
202
|
+
encodeVector(functions.map((func,i) => [...func.sectionExport, i]))
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const codeSection = createSection(ESectionType.code, [
|
|
206
|
+
functions.length, // Number of functions
|
|
207
|
+
...flatten(functions.map((func) => func.sectionCode))
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
return Uint8Array.from([
|
|
211
|
+
...magicModuleHeader,
|
|
212
|
+
...moduleVersion,
|
|
213
|
+
...typesSection,
|
|
214
|
+
...functionsSection,
|
|
215
|
+
...exportSection,
|
|
216
|
+
...codeSection
|
|
217
|
+
]);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const defaultMemory: WebAssembly.Memory = new WebAssembly.Memory({initial: 10, maximum: 100, shared: true} as WebAssembly.MemoryDescriptor);
|
|
221
|
+
|
|
222
|
+
export async function compile(functions: FunctionSection[], memory?: WebAssembly.Memory) {
|
|
223
|
+
memory = memory || defaultMemory;
|
|
224
|
+
const wasm = emitter(functions);
|
|
225
|
+
return await WebAssembly.instantiate(wasm, {
|
|
226
|
+
js: {
|
|
227
|
+
memory: memory
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export async function run(functions: FunctionSection | FunctionSection[], ...args) {
|
|
233
|
+
const memory = args[0] instanceof WebAssembly.Memory && args[0] || defaultMemory;
|
|
234
|
+
if (functions instanceof FunctionSection)
|
|
235
|
+
functions = [functions];
|
|
236
|
+
|
|
237
|
+
const wasm = await compile(functions, memory);
|
|
238
|
+
return 'main' in wasm.instance.exports ? (wasm.instance.exports.main as any)(...args) : wasm;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (VisionHelper.window)
|
|
242
|
+
window['wasm'] = {
|
|
243
|
+
compile: compile
|
|
244
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {Node} from "./Node";
|
|
2
|
+
import {Token, TokenType, Tree, TreeNode} from "../AST";
|
|
3
|
+
import {Scope} from "../Scope";
|
|
4
|
+
import {DOM} from "../DOM";
|
|
5
|
+
import {Tag} from "../Tag";
|
|
6
|
+
import {ScopeDataAbstract} from "../Scope/ScopeDataAbstract";
|
|
7
|
+
|
|
8
|
+
export class XHRNode extends Node implements TreeNode {
|
|
9
|
+
constructor(
|
|
10
|
+
public readonly left: Node | null,
|
|
11
|
+
public readonly requestType: TokenType,
|
|
12
|
+
public readonly url: Node
|
|
13
|
+
) {
|
|
14
|
+
super();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public getChildNodes(): Node[] {
|
|
18
|
+
const nodes = [this.url];
|
|
19
|
+
if (this.left)
|
|
20
|
+
nodes.push(this.left);
|
|
21
|
+
return nodes;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async evaluate(scope: Scope, dom: DOM, tag?: Tag) {
|
|
25
|
+
const url = await this.url.evaluate(scope, dom, tag);
|
|
26
|
+
let method: string;
|
|
27
|
+
let data = this.left ? await this.left.evaluate(scope, dom, tag) : {};
|
|
28
|
+
|
|
29
|
+
if (data instanceof Scope)
|
|
30
|
+
data = data.data;
|
|
31
|
+
|
|
32
|
+
if (data instanceof ScopeDataAbstract)
|
|
33
|
+
data = data.getData();
|
|
34
|
+
|
|
35
|
+
switch (this.requestType) {
|
|
36
|
+
case TokenType.XHR_POST:
|
|
37
|
+
method = "POST";
|
|
38
|
+
break;
|
|
39
|
+
case TokenType.XHR_PUT:
|
|
40
|
+
method = "PUT";
|
|
41
|
+
break;
|
|
42
|
+
case TokenType.XHR_DELETE:
|
|
43
|
+
method = "DELETE";
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
method = "GET";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let request = {
|
|
50
|
+
method: method
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (request.method === 'GET') {
|
|
54
|
+
|
|
55
|
+
} else {
|
|
56
|
+
request['body'] = (typeof data === "string") ? data : JSON.stringify(data);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const response = await fetch(url, request);
|
|
60
|
+
const contentType = response.headers.get('content-type');
|
|
61
|
+
if (contentType && contentType.includes('application/json')) {
|
|
62
|
+
return await response.json();
|
|
63
|
+
}
|
|
64
|
+
return await response.text();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public static parse(node: Node, token: Token, tokens: Token[]): XHRNode {
|
|
68
|
+
tokens.splice(0, 1); // Consume request type
|
|
69
|
+
const url = Tree.processTokens(Tree.getNextStatementTokens(tokens, false, false, false));
|
|
70
|
+
return new XHRNode(node, token.type, url);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public static match(tokens: Token[]) {
|
|
74
|
+
return [
|
|
75
|
+
TokenType.XHR_POST,
|
|
76
|
+
TokenType.XHR_PUT,
|
|
77
|
+
TokenType.XHR_GET,
|
|
78
|
+
TokenType.XHR_DELETE,
|
|
79
|
+
].indexOf(tokens[0].type) > -1;
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/AST.ts
CHANGED
|
@@ -24,6 +24,8 @@ import {ArithmeticAssignmentNode} from "./AST/ArithmeticAssignmentNode";
|
|
|
24
24
|
import {UnitLiteralNode} from "./AST/UnitLiteralNode";
|
|
25
25
|
import {BooleanLiteralNode} from "./AST/BooleanLiteralNode";
|
|
26
26
|
import {NotNode} from "./AST/NotNode";
|
|
27
|
+
import {XHRNode} from "./AST/XHRNode";
|
|
28
|
+
import {StringFormatNode} from "./AST/StringFormatNode";
|
|
27
29
|
|
|
28
30
|
function lower(str: string): string {
|
|
29
31
|
return str ? str.toLowerCase() : null;
|
|
@@ -47,6 +49,7 @@ export enum BlockType {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export enum TokenType {
|
|
52
|
+
NULL,
|
|
50
53
|
WHITESPACE,
|
|
51
54
|
TYPE_INT,
|
|
52
55
|
TYPE_UINT,
|
|
@@ -71,7 +74,8 @@ export enum TokenType {
|
|
|
71
74
|
PERIOD,
|
|
72
75
|
COMMA,
|
|
73
76
|
COLON,
|
|
74
|
-
|
|
77
|
+
SEMICOLON,
|
|
78
|
+
STRING_FORMAT,
|
|
75
79
|
STRING_LITERAL,
|
|
76
80
|
NUMBER_LITERAL,
|
|
77
81
|
BOOLEAN_LITERAL,
|
|
@@ -101,6 +105,10 @@ export enum TokenType {
|
|
|
101
105
|
ELEMENT_STYLE,
|
|
102
106
|
ELEMENT_QUERY,
|
|
103
107
|
UNIT,
|
|
108
|
+
XHR_GET,
|
|
109
|
+
XHR_POST,
|
|
110
|
+
XHR_PUT,
|
|
111
|
+
XHR_DELETE,
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
const TOKEN_PATTERNS: TokenPattern[] = [
|
|
@@ -108,6 +116,22 @@ const TOKEN_PATTERNS: TokenPattern[] = [
|
|
|
108
116
|
type: TokenType.WHITESPACE,
|
|
109
117
|
pattern: /^[\s\n\r]+/
|
|
110
118
|
},
|
|
119
|
+
{
|
|
120
|
+
type: TokenType.XHR_POST,
|
|
121
|
+
pattern: /^>>/
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: TokenType.XHR_PUT,
|
|
125
|
+
pattern: /^<>/
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: TokenType.XHR_GET,
|
|
129
|
+
pattern: /^<</
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
type: TokenType.XHR_DELETE,
|
|
133
|
+
pattern: /^></
|
|
134
|
+
},
|
|
111
135
|
{
|
|
112
136
|
type: TokenType.TYPE_INT,
|
|
113
137
|
pattern: /^int+/
|
|
@@ -257,9 +281,13 @@ const TOKEN_PATTERNS: TokenPattern[] = [
|
|
|
257
281
|
pattern: /^:/
|
|
258
282
|
},
|
|
259
283
|
{
|
|
260
|
-
type: TokenType.
|
|
284
|
+
type: TokenType.SEMICOLON,
|
|
261
285
|
pattern: /^;/
|
|
262
286
|
},
|
|
287
|
+
{
|
|
288
|
+
type: TokenType.STRING_FORMAT,
|
|
289
|
+
pattern: /^`([^`]*)`/
|
|
290
|
+
},
|
|
263
291
|
{
|
|
264
292
|
type: TokenType.STRING_LITERAL,
|
|
265
293
|
pattern: /^"([^"]*)"/
|
|
@@ -341,36 +369,38 @@ export const AttributableNodes = [
|
|
|
341
369
|
|
|
342
370
|
export class Tree {
|
|
343
371
|
protected static cache: { [key: string]: Node } = {};
|
|
344
|
-
protected
|
|
372
|
+
protected _root: Node;
|
|
345
373
|
|
|
346
374
|
constructor(
|
|
347
375
|
public readonly code: string
|
|
348
376
|
) {
|
|
349
377
|
if (Tree.cache[code]) {
|
|
350
|
-
this.
|
|
378
|
+
this._root = Tree.cache[code];
|
|
351
379
|
} else {
|
|
352
380
|
this.parse();
|
|
353
|
-
Tree.cache[code] = this.
|
|
381
|
+
Tree.cache[code] = this._root;
|
|
354
382
|
}
|
|
355
383
|
}
|
|
356
384
|
|
|
385
|
+
public get root(): Node { return this._root; }
|
|
386
|
+
|
|
357
387
|
public parse() {
|
|
358
388
|
const tokens = Tree.tokenize(this.code);
|
|
359
|
-
this.
|
|
389
|
+
this._root = Tree.processTokens(tokens);
|
|
360
390
|
}
|
|
361
391
|
|
|
362
392
|
async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
|
|
363
|
-
return await this.
|
|
393
|
+
return await this._root.evaluate(scope, dom, tag);
|
|
364
394
|
}
|
|
365
395
|
|
|
366
396
|
async prepare(scope: Scope, dom: DOM, tag: Tag = null) {
|
|
367
|
-
if (!this.
|
|
397
|
+
if (!this._root.isPreparationRequired())
|
|
368
398
|
return;
|
|
369
|
-
return await this.
|
|
399
|
+
return await this._root.prepare(scope, dom, tag);
|
|
370
400
|
}
|
|
371
401
|
|
|
372
402
|
async bindToScopeChanges(scope, fnc, dom: DOM, tag: Tag = null) {
|
|
373
|
-
for (const node of this.
|
|
403
|
+
for (const node of this._root.findChildrenByTypes<ScopeMemberNode | ElementAttributeNode>([RootScopeMemberNode, ScopeMemberNode, ElementAttributeNode], 'ScopeMemberNodes')) {
|
|
374
404
|
let _scope: Scope = scope;
|
|
375
405
|
if (node instanceof ScopeMemberNode)
|
|
376
406
|
_scope = await node.scope.evaluate(scope, dom);
|
|
@@ -431,14 +461,16 @@ export class Tree {
|
|
|
431
461
|
if (count > 1000) break; // Limit to 1000 iterations while in development
|
|
432
462
|
|
|
433
463
|
if (tokens[0].type === TokenType.RETURN)
|
|
434
|
-
tokens.
|
|
464
|
+
tokens.shift()
|
|
435
465
|
|
|
436
466
|
const token: Token = tokens[0];
|
|
437
467
|
if (token.type === TokenType.NAME) {
|
|
438
468
|
node = new RootScopeMemberNode<string>(
|
|
439
469
|
new LiteralNode<string>(token.value)
|
|
440
470
|
);
|
|
441
|
-
tokens.
|
|
471
|
+
tokens.shift()
|
|
472
|
+
} else if (XHRNode.match(tokens)) {
|
|
473
|
+
node = XHRNode.parse(node, tokens[0], tokens);
|
|
442
474
|
} else if (token.type === TokenType.IF) {
|
|
443
475
|
node = IfStatementNode.parse(node, token, tokens);
|
|
444
476
|
blockNodes.push(node);
|
|
@@ -447,18 +479,20 @@ export class Tree {
|
|
|
447
479
|
node = ForStatementNode.parse(node, token, tokens);
|
|
448
480
|
blockNodes.push(node);
|
|
449
481
|
node = null;
|
|
482
|
+
} else if (StringFormatNode.match(tokens)) {
|
|
483
|
+
node = StringFormatNode.parse(node, tokens[0], tokens);
|
|
450
484
|
} else if (token.type === TokenType.STRING_LITERAL) {
|
|
451
485
|
node = new LiteralNode(token.value);
|
|
452
|
-
tokens.
|
|
486
|
+
tokens.shift()
|
|
453
487
|
} else if (token.type === TokenType.NUMBER_LITERAL) {
|
|
454
488
|
node = new NumberLiteralNode(token.value);
|
|
455
|
-
tokens.
|
|
489
|
+
tokens.shift()
|
|
456
490
|
} else if (tokens[0].type === TokenType.ELEMENT_REFERENCE) {
|
|
457
491
|
node = new ElementQueryNode(tokens[0].value, true);
|
|
458
|
-
tokens.
|
|
492
|
+
tokens.shift()
|
|
459
493
|
} else if (tokens[0].type === TokenType.ELEMENT_QUERY) {
|
|
460
494
|
node = new ElementQueryNode(tokens[0].value);
|
|
461
|
-
tokens.
|
|
495
|
+
tokens.shift()
|
|
462
496
|
} else if (tokens[0].type === TokenType.L_BRACKET) {
|
|
463
497
|
if (node) {
|
|
464
498
|
node = IndexNode.parse(node, token, tokens);
|
|
@@ -469,10 +503,10 @@ export class Tree {
|
|
|
469
503
|
node = ObjectNode.parse(node, token, tokens);
|
|
470
504
|
} else if (tokens[0].type === TokenType.ELEMENT_ATTRIBUTE) {
|
|
471
505
|
node = new ElementAttributeNode(node as any, tokens[0].value);
|
|
472
|
-
tokens.
|
|
506
|
+
tokens.shift()
|
|
473
507
|
} else if (tokens[0].type === TokenType.ELEMENT_STYLE) {
|
|
474
508
|
node = new ElementStyleNode(node as any, tokens[0].value);
|
|
475
|
-
tokens.
|
|
509
|
+
tokens.shift()
|
|
476
510
|
} else if (node !== null && token.type === TokenType.PERIOD && tokens[1].type === TokenType.NAME) {
|
|
477
511
|
node = new ScopeMemberNode(
|
|
478
512
|
node,
|
|
@@ -493,12 +527,12 @@ export class Tree {
|
|
|
493
527
|
} else {
|
|
494
528
|
node = new BlockNode(nodes);
|
|
495
529
|
}
|
|
496
|
-
} else if (tokens[0].type === TokenType.
|
|
530
|
+
} else if (tokens[0].type === TokenType.SEMICOLON) {
|
|
497
531
|
if (node) {
|
|
498
532
|
blockNodes.push(node);
|
|
499
533
|
}
|
|
500
534
|
node = null;
|
|
501
|
-
tokens.
|
|
535
|
+
tokens.shift()
|
|
502
536
|
} else if (InNode.match(tokens)) {
|
|
503
537
|
node = InNode.parse(node, token, tokens);
|
|
504
538
|
} else if (ComparisonNode.match(tokens)) {
|
|
@@ -508,16 +542,16 @@ export class Tree {
|
|
|
508
542
|
} else if (ArithmeticAssignmentNode.match(tokens)) {
|
|
509
543
|
node = ArithmeticAssignmentNode.parse(node, token, tokens);
|
|
510
544
|
} else if (tokens[0].type === TokenType.WHITESPACE) {
|
|
511
|
-
tokens.
|
|
545
|
+
tokens.shift()
|
|
512
546
|
} else if (tokens[0].type === TokenType.UNIT) {
|
|
513
547
|
node = new UnitLiteralNode(tokens[0].value);
|
|
514
|
-
tokens.
|
|
548
|
+
tokens.shift()
|
|
515
549
|
} else if (tokens[0].type === TokenType.BOOLEAN_LITERAL) {
|
|
516
550
|
node = new BooleanLiteralNode(tokens[0].value);
|
|
517
|
-
tokens.
|
|
551
|
+
tokens.shift()
|
|
518
552
|
} else if (tokens[0].type === TokenType.NULL_LITERAL) {
|
|
519
553
|
node = new LiteralNode(null);
|
|
520
|
-
tokens.
|
|
554
|
+
tokens.shift()
|
|
521
555
|
} else if (tokens[0].type === TokenType.EXCLAMATION_POINT) {
|
|
522
556
|
node = NotNode.parse(node, tokens[0], tokens);
|
|
523
557
|
} else {
|
|
@@ -583,7 +617,7 @@ export class Tree {
|
|
|
583
617
|
break;
|
|
584
618
|
default:
|
|
585
619
|
open = null;
|
|
586
|
-
close = TokenType.
|
|
620
|
+
close = TokenType.SEMICOLON;
|
|
587
621
|
openCharacter = null;
|
|
588
622
|
closeCharacter = ';';
|
|
589
623
|
break;
|
|
@@ -603,7 +637,7 @@ export class Tree {
|
|
|
603
637
|
|
|
604
638
|
// Consume opening block token
|
|
605
639
|
if (consumeOpeningToken && tokens[0].type === blockInfo.open) {
|
|
606
|
-
tokens.
|
|
640
|
+
tokens.shift()
|
|
607
641
|
}
|
|
608
642
|
|
|
609
643
|
return Tree.getTokensUntil(tokens, blockInfo.close, consumeClosingToken, includeClosingToken);
|
|
@@ -632,7 +666,7 @@ export class Tree {
|
|
|
632
666
|
}
|
|
633
667
|
|
|
634
668
|
// Consume token
|
|
635
|
-
tokens.
|
|
669
|
+
tokens.shift()
|
|
636
670
|
i--;
|
|
637
671
|
if (openBlocks === 0) {
|
|
638
672
|
if (arg.length > 0)
|
|
@@ -644,7 +678,7 @@ export class Tree {
|
|
|
644
678
|
throw Error(`Invalid Syntax, missing ${blockInfo.closeCharacter}`);
|
|
645
679
|
}
|
|
646
680
|
|
|
647
|
-
public static getTokensUntil(tokens: Token[], terminator: TokenType = TokenType.
|
|
681
|
+
public static getTokensUntil(tokens: Token[], terminator: TokenType = TokenType.SEMICOLON, consumeTerminator: boolean = true, includeTerminator: boolean = false, validIfTerminatorNotFound: boolean = false, blockInfo: IBlockInfo = null): Token[] {
|
|
648
682
|
const statementTokens: Token[] = [];
|
|
649
683
|
blockInfo = blockInfo || Tree.getBlockInfo(tokens);
|
|
650
684
|
|
|
@@ -681,8 +715,9 @@ export class Tree {
|
|
|
681
715
|
if (includeTerminator)
|
|
682
716
|
statementTokens.push(token);
|
|
683
717
|
|
|
684
|
-
if (
|
|
685
|
-
|
|
718
|
+
//if (consumeTerminator && token.type !== TokenType.SEMICOLON)
|
|
719
|
+
if ((includeTerminator || consumeTerminator) && token.type !== TokenType.SEMICOLON)
|
|
720
|
+
tokens.shift() // Consume end of block
|
|
686
721
|
break;
|
|
687
722
|
} else if (token.type === terminator && (openParens > 0 || openBraces > 0 || openBrackets > 0)) {
|
|
688
723
|
} else {
|
|
@@ -693,7 +728,7 @@ export class Tree {
|
|
|
693
728
|
}
|
|
694
729
|
|
|
695
730
|
statementTokens.push(token);
|
|
696
|
-
tokens.
|
|
731
|
+
tokens.shift() // Consume part of statement
|
|
697
732
|
i--;
|
|
698
733
|
}
|
|
699
734
|
return statementTokens;
|
package/src/DOM/DOMObject.ts
CHANGED