vsn 0.1.42 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/demo/demo.html +6 -2
  2. package/demo/markup.html +2 -0
  3. package/demo/vsn.js +1 -1
  4. package/demo/xhr.vsn +4 -0
  5. package/dist/AST/ArithmeticAssignmentNode.js +8 -1
  6. package/dist/AST/ArithmeticAssignmentNode.js.map +1 -1
  7. package/dist/AST/FunctionNode.d.ts +0 -0
  8. package/dist/AST/FunctionNode.js +1 -0
  9. package/dist/AST/FunctionNode.js.map +1 -0
  10. package/dist/AST/StringFormatNode.d.ts +18 -0
  11. package/dist/{attributes/ClickToggleClass.js → AST/StringFormatNode.js} +49 -49
  12. package/dist/AST/StringFormatNode.js.map +1 -0
  13. package/dist/AST/WASM/Context.d.ts +4 -0
  14. package/dist/AST/WASM/Context.js +18 -0
  15. package/dist/AST/WASM/Context.js.map +1 -0
  16. package/dist/AST/WASM/Function.d.ts +22 -0
  17. package/dist/AST/WASM/Function.js +110 -0
  18. package/dist/AST/WASM/Function.js.map +1 -0
  19. package/dist/AST/WASM/Memory.d.ts +12 -0
  20. package/dist/AST/WASM/Memory.js +22 -0
  21. package/dist/AST/WASM/Memory.js.map +1 -0
  22. package/dist/AST/WASM/Section.d.ts +5 -0
  23. package/dist/AST/WASM/Section.js +11 -0
  24. package/dist/AST/WASM/Section.js.map +1 -0
  25. package/dist/AST/WASM.d.ts +58 -0
  26. package/dist/AST/WASM.js +277 -0
  27. package/dist/AST/WASM.js.map +1 -0
  28. package/dist/AST/XHRNode.d.ts +15 -0
  29. package/dist/AST/XHRNode.js +146 -0
  30. package/dist/AST/XHRNode.js.map +1 -0
  31. package/dist/AST.d.ts +62 -55
  32. package/dist/AST.js +123 -83
  33. package/dist/AST.js.map +1 -1
  34. package/dist/DOM.js +39 -82
  35. package/dist/DOM.js.map +1 -1
  36. package/dist/Registry.d.ts +2 -0
  37. package/dist/Registry.js +13 -9
  38. package/dist/Registry.js.map +1 -1
  39. package/dist/Scope/ScopeDataAbstract.js +2 -2
  40. package/dist/Scope/ScopeDataAbstract.js.map +1 -1
  41. package/dist/Scope/properties/Property.d.ts +6 -6
  42. package/dist/Scope/properties/Property.js +26 -30
  43. package/dist/Scope/properties/Property.js.map +1 -1
  44. package/dist/Scope/properties/_imports.d.ts +1 -1
  45. package/dist/Scope/properties/_imports.js.map +1 -1
  46. package/dist/Tag.js +2 -11
  47. package/dist/Tag.js.map +1 -1
  48. package/dist/attributes/_imports.d.ts +0 -2
  49. package/dist/attributes/_imports.js +1 -5
  50. package/dist/attributes/_imports.js.map +1 -1
  51. package/dist/helpers/VisionHelper.d.ts +1 -0
  52. package/dist/helpers/VisionHelper.js +17 -0
  53. package/dist/helpers/VisionHelper.js.map +1 -1
  54. package/dist/vsn.d.ts +3 -2
  55. package/dist/vsn.js +7 -3
  56. package/dist/vsn.js.map +1 -1
  57. package/package.json +1 -1
  58. package/src/AST/ArithmeticAssignmentNode.ts +9 -2
  59. package/src/AST/FunctionNode.ts +0 -0
  60. package/src/AST/StringFormatNode.ts +43 -0
  61. package/src/AST/WASM/Context.ts +12 -0
  62. package/src/AST/WASM/Function.ts +67 -0
  63. package/src/AST/WASM/Memory.ts +21 -0
  64. package/src/AST/WASM/Section.ts +6 -0
  65. package/src/AST/WASM.ts +244 -0
  66. package/src/AST/XHRNode.ts +81 -0
  67. package/src/AST.ts +66 -31
  68. package/src/DOM.ts +4 -25
  69. package/src/Registry.ts +12 -9
  70. package/src/Scope/ScopeDataAbstract.ts +2 -2
  71. package/src/Scope/properties/Property.ts +27 -34
  72. package/src/Scope/properties/_imports.ts +1 -1
  73. package/src/Tag.ts +2 -9
  74. package/src/attributes/AddClassIf.ts +1 -1
  75. package/src/attributes/_imports.ts +0 -2
  76. package/src/helpers/VisionHelper.ts +13 -0
  77. package/src/vsn.ts +3 -2
  78. package/test/AST/ArithmeticAssignmentNode.spec.ts +0 -2
  79. package/test/AST/StringFormatNode.spec.ts +12 -0
  80. package/test/AST/WASM.spec.ts +63 -0
  81. package/test/AST/XHRNode.spec.ts +10 -0
  82. package/test/Scope/ScopeData.spec.ts +5 -5
  83. package/dist/attributes/ClickRemoveClass.d.ts +0 -8
  84. package/dist/attributes/ClickRemoveClass.js +0 -114
  85. package/dist/attributes/ClickRemoveClass.js.map +0 -1
  86. package/dist/attributes/ClickToggleClass.d.ts +0 -8
  87. package/dist/attributes/ClickToggleClass.js.map +0 -1
  88. package/src/attributes/ClickRemoveClass.ts +0 -30
  89. package/src/attributes/ClickToggleClass.ts +0 -30
@@ -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
- SEMI_COLON,
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.SEMI_COLON,
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 rootNode: Node;
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.rootNode = Tree.cache[code];
378
+ this._root = Tree.cache[code];
351
379
  } else {
352
380
  this.parse();
353
- Tree.cache[code] = this.rootNode;
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.rootNode = Tree.processTokens(tokens);
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.rootNode.evaluate(scope, dom, tag);
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.rootNode.isPreparationRequired())
397
+ if (!this._root.isPreparationRequired())
368
398
  return;
369
- return await this.rootNode.prepare(scope, dom, tag);
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.rootNode.findChildrenByTypes<ScopeMemberNode | ElementAttributeNode>([RootScopeMemberNode, ScopeMemberNode, ElementAttributeNode], 'ScopeMemberNodes')) {
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.splice(0, 1);
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.splice(0, 1);
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.splice(0, 1);
486
+ tokens.shift()
453
487
  } else if (token.type === TokenType.NUMBER_LITERAL) {
454
488
  node = new NumberLiteralNode(token.value);
455
- tokens.splice(0, 1);
489
+ tokens.shift()
456
490
  } else if (tokens[0].type === TokenType.ELEMENT_REFERENCE) {
457
491
  node = new ElementQueryNode(tokens[0].value, true);
458
- tokens.splice(0, 1);
492
+ tokens.shift()
459
493
  } else if (tokens[0].type === TokenType.ELEMENT_QUERY) {
460
494
  node = new ElementQueryNode(tokens[0].value);
461
- tokens.splice(0, 1);
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.splice(0, 1);
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.splice(0, 1);
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.SEMI_COLON) {
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.splice(0, 1);
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.splice(0, 1);
545
+ tokens.shift()
512
546
  } else if (tokens[0].type === TokenType.UNIT) {
513
547
  node = new UnitLiteralNode(tokens[0].value);
514
- tokens.splice(0, 1);
548
+ tokens.shift()
515
549
  } else if (tokens[0].type === TokenType.BOOLEAN_LITERAL) {
516
550
  node = new BooleanLiteralNode(tokens[0].value);
517
- tokens.splice(0, 1);
551
+ tokens.shift()
518
552
  } else if (tokens[0].type === TokenType.NULL_LITERAL) {
519
553
  node = new LiteralNode(null);
520
- tokens.splice(0, 1);
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.SEMI_COLON;
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.splice(0, 1);
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.splice(0, 1);
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.SEMI_COLON, consumeTerminator: boolean = true, includeTerminator: boolean = false, validIfTerminatorNotFound: boolean = false, blockInfo: IBlockInfo = null): Token[] {
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 ((includeTerminator || consumeTerminator) && token.type !== TokenType.SEMI_COLON)
685
- tokens.splice(0, 1); // Consume end of block
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.splice(0, 1); // Consume part of statement
731
+ tokens.shift() // Consume part of statement
697
732
  i--;
698
733
  }
699
734
  return statementTokens;
package/src/DOM.ts CHANGED
@@ -3,8 +3,6 @@ import {ElementHelper} from "./helpers/ElementHelper";
3
3
  import {Configuration} from "./Configuration";
4
4
  import {Tree} from "./AST";
5
5
  import {TagList} from "./Tag/List";
6
- import {benchmarkEnd, benchmarkStart} from "./Bencmark";
7
- import {VisionHelper} from "./helpers/VisionHelper";
8
6
  import {WrappedWindow} from "./DOM/WrappedWindow";
9
7
  import {WrappedDocument} from "./DOM/WrappedDocument";
10
8
  import {Scope} from "./Scope";
@@ -50,6 +48,8 @@ export class DOM extends EventDispatcher {
50
48
  return new TagList(this.window);
51
49
  case 'document':
52
50
  return new TagList(this.document);
51
+ case 'body':
52
+ return new TagList(this.root);
53
53
  default:
54
54
  const nodes = this.querySelectorAll(selector, tag);
55
55
  return await this.getTagsForElements(Array.from(nodes) as Element[], create);
@@ -139,7 +139,6 @@ export class DOM extends EventDispatcher {
139
139
  const toBuild: HTMLElement[] = [];
140
140
  const toSkip: HTMLElement[] = [];
141
141
 
142
- if (VisionHelper.doBenchmark) benchmarkStart('DOM','findElements');
143
142
  if (ele && ele.querySelectorAll) {
144
143
  for (const element of (Array.from(ele.querySelectorAll(`*`)) as HTMLElement[])) { // Don't build items more than once
145
144
  if (!ElementHelper.hasVisionAttribute(element)) continue;
@@ -152,9 +151,7 @@ export class DOM extends EventDispatcher {
152
151
  toBuild.push(element);
153
152
  }
154
153
  }
155
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'findElements');
156
154
 
157
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'buildTags');
158
155
  for (const element of toBuild) {
159
156
  if (allElements.indexOf(element) > -1) continue;
160
157
  const tag: Tag = new Tag(element, this);
@@ -162,23 +159,17 @@ export class DOM extends EventDispatcher {
162
159
  newTags.push(tag);
163
160
  allElements.push(element as HTMLElement);
164
161
  }
165
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'buildTags');
166
162
 
167
163
  if (isRoot)
168
164
  this._root = await this.getTagForElement(document.body);
169
165
 
170
166
  // Configure, setup & execute attributes
171
- if (VisionHelper.doBenchmark) benchmarkStart('DOM','buildTagAttributes');
172
167
  for (const tag of newTags)
173
168
  await tag.buildAttributes();
174
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM','buildTagAttributes');
175
169
 
176
- if (VisionHelper.inDevelopment) benchmarkStart('DOM', 'compileAttributes');
177
170
  for (const tag of newTags)
178
171
  await tag.compileAttributes();
179
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM','compileAttributes');
180
172
 
181
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'buildTree');
182
173
  for (const tag of newTags) {
183
174
  if (tag === this.root)
184
175
  continue;
@@ -198,39 +189,27 @@ export class DOM extends EventDispatcher {
198
189
  if (!foundParent)
199
190
  console.error('Could not find parent for ', tag);
200
191
  }
201
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'buildTree');
202
192
 
203
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'setupAttributes');
204
193
  for (const tag of newTags)
205
194
  await tag.setupAttributes();
206
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'setupAttributes');
207
195
 
208
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'extractAttributes');
209
196
  for (const tag of newTags)
210
197
  await tag.extractAttributes();
211
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'extractAttributes');
212
198
 
213
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'connectAttributes');
214
199
  for (const tag of newTags)
215
200
  await tag.connectAttributes();
216
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'connectAttributes');
217
201
 
218
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'finalizeTags');
219
202
  for (const tag of newTags) {
220
203
  await tag.finalize();
221
204
  this.queued.splice(this.queued.indexOf(tag.element), 1);
222
205
  }
223
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'finalizeTags');
224
206
 
225
- if (VisionHelper.doBenchmark) benchmarkStart('DOM', 'observeTags');
226
- for (const tag of newTags)
227
- this.observer.observe(tag.element, {
207
+ newTags.forEach(tag => this.observer.observe(tag.element, {
228
208
  attributes: true,
229
209
  characterData: true,
230
210
  childList: true,
231
211
  subtree: true
232
- });
233
- if (VisionHelper.doBenchmark) benchmarkEnd('DOM', 'observeTags');
212
+ }));
234
213
 
235
214
  this.dispatch('built');
236
215
  }
package/src/Registry.ts CHANGED
@@ -1,4 +1,3 @@
1
- import {VisionHelper} from "./helpers/VisionHelper";
2
1
  import {EventDispatcher} from "./EventDispatcher";
3
2
  import {IDeferred, IPromise, SimplePromise} from "./SimplePromise";
4
3
 
@@ -53,6 +52,7 @@ export class RegistryStore extends EventDispatcher {
53
52
 
54
53
  export class Registry extends EventDispatcher {
55
54
  protected static _instance: Registry;
55
+ public readonly components: RegistryStore;
56
56
  public readonly classes: RegistryStore;
57
57
  public readonly models: RegistryStore;
58
58
  public readonly templates: RegistryStore;
@@ -63,15 +63,18 @@ export class Registry extends EventDispatcher {
63
63
 
64
64
  constructor() {
65
65
  super();
66
+ this.components = new RegistryStore();
67
+ this.classes = new RegistryStore();
68
+ this.models = new RegistryStore();
69
+ this.templates = new RegistryStore();
70
+ this.types = new RegistryStore();
71
+ this.validators = new RegistryStore();
72
+ this.formats = new RegistryStore();
73
+ this.attributes = new RegistryStore();
74
+ }
66
75
 
67
- const w = VisionHelper.window || {};
68
- this.classes = new RegistryStore(w['$classes'] || {});
69
- this.models = new RegistryStore(w['$models'] || {});
70
- this.templates = new RegistryStore(w['$templates'] || {});
71
- this.types = new RegistryStore(w['$types'] || {});
72
- this.validators = new RegistryStore(w['$validators'] || {});
73
- this.formats = new RegistryStore(w['$formats'] || {});
74
- this.attributes = new RegistryStore(w['$attributes'] || {});
76
+ public static component(key: string = null, setup = null) {
77
+ return register('components', key, setup);
75
78
  }
76
79
 
77
80
  public static class(key: string = null, setup = null) {
@@ -65,7 +65,7 @@ export class ScopeDataAbstract extends EventDispatcher {
65
65
  const keys = [];
66
66
  for (const key of this.keys) {
67
67
  const property = this.getProperty(key);
68
- if (property.hasTags(tags)) {
68
+ if (property.hasLabels(tags)) {
69
69
  keys.push(key);
70
70
  }
71
71
  }
@@ -86,7 +86,7 @@ export class ScopeDataAbstract extends EventDispatcher {
86
86
  propLoop: for (const key of this.getProperties()) {
87
87
  const property = this['__'+key];
88
88
  for (const tag of tags) {
89
- if (!property.hasTag(tag))
89
+ if (!property.hasLabel(tag))
90
90
  continue propLoop;
91
91
  }
92
92
 
@@ -30,7 +30,7 @@ export interface IPropertyConfig {
30
30
  type?: string;
31
31
  default?: any;
32
32
  validators?: TValidator[];
33
- tags?: string[];
33
+ labels?: string[];
34
34
  }
35
35
 
36
36
  export class Property<T = any> extends EventDispatcher {
@@ -41,8 +41,8 @@ export class Property<T = any> extends EventDispatcher {
41
41
  constructor(value?: T, config?: IPropertyConfig) {
42
42
  super();
43
43
  this.config = config;
44
- if (!this.config.tags)
45
- this.config.tags = [];
44
+ if (!this.config.labels)
45
+ this.config.labels = [];
46
46
  if (!this.config.validators)
47
47
  this.config.validators = [];
48
48
  this.type = config.type || 'any';
@@ -93,55 +93,48 @@ export class Property<T = any> extends EventDispatcher {
93
93
  return errors;
94
94
  }
95
95
 
96
- addValidator(validator: TValidator | string) {
97
- if (typeof validator == 'string')
98
- validator = Registry.instance.validators.getSynchronous(validator) as TValidator;
99
-
96
+ getValidator(id: string) {
97
+ const validator = Registry.instance.validators.getSynchronous(id) as TValidator;
100
98
  if (!validator)
101
- throw new Error('Invalid validator');
102
-
103
- if (this.config.validators.indexOf(validator) == -1)
104
- this.config.validators.push(validator);
99
+ throw new Error(`Invalid validator ${id}`);
100
+ return validator;
105
101
  }
106
102
 
107
- removeValidator(validator: TValidator | string) {
108
- if (typeof validator == 'string')
109
- validator = Registry.instance.validators.getSynchronous(validator) as TValidator;
110
-
111
- if (!validator)
112
- throw new Error('Invalid validator');
103
+ addValidator(validator: TValidator | string) {
104
+ if (typeof validator == 'string') {
105
+ validator = this.getValidator(validator);
106
+ }
113
107
 
114
- const index = this.config.validators.indexOf(validator);
115
- if (index != -1)
116
- this.config.validators.splice(index, 1);
108
+ if (this.config.validators.indexOf(validator) == -1)
109
+ this.config.validators.push(validator);
117
110
  }
118
111
 
119
- addTag(tag: string) {
120
- if(this.config.tags == undefined) {
121
- this.config.tags = [];
112
+ addLabel(label: string) {
113
+ if(this.config.labels == undefined) {
114
+ this.config.labels = [];
122
115
  }
123
- if(this.config.tags.indexOf(tag) == -1) {
124
- this.config.tags.push(tag);
116
+ if(this.config.labels.indexOf(label) == -1) {
117
+ this.config.labels.push(label);
125
118
  }
126
119
  }
127
120
 
128
- removeTag(tag: string) {
129
- if(this.config.tags == undefined) {
121
+ removeLabel(label: string) {
122
+ if(this.config.labels == undefined) {
130
123
  return;
131
124
  }
132
- const index = this.config.tags.indexOf(tag);
125
+ const index = this.config.labels.indexOf(label);
133
126
  if(index != -1) {
134
- this.config.tags.splice(index, 1);
127
+ this.config.labels.splice(index, 1);
135
128
  }
136
129
  }
137
130
 
138
- hasTag(tag: string) {
139
- return this.config.tags.indexOf(tag) !== -1;
131
+ hasLabel(label: string) {
132
+ return this.config.labels.indexOf(label) !== -1;
140
133
  }
141
134
 
142
- hasTags(tags: string[]) {
143
- for(const tag of tags) {
144
- if(!this.hasTag(tag)) {
135
+ hasLabels(labels: string[]) {
136
+ for(const label of labels) {
137
+ if(!this.hasLabel(label)) {
145
138
  return false;
146
139
  }
147
140
  }
@@ -1,2 +1,2 @@
1
- export {Property, property} from './Property';
1
+ export {Property, property, IPropertyConfig} from './Property';
2
2
  export {ArrayProperty} from './ArrayProperty';
package/src/Tag.ts CHANGED
@@ -72,12 +72,7 @@ export class Tag extends DOMObject {
72
72
  if (this._nonDeferredAttributes.length > 0)
73
73
  return this._nonDeferredAttributes;
74
74
 
75
- const attrs: Attribute[] = [];
76
- for (const attribute of this.attributes) {
77
- if (attribute.state === AttributeState.Deferred)
78
- continue;
79
- attrs.push(attribute);
80
- }
75
+ const attrs: Attribute[] = this.attributes.filter(attr => attr.state !== AttributeState.Deferred);
81
76
  this._nonDeferredAttributes = attrs;
82
77
  return attrs;
83
78
  }
@@ -119,9 +114,7 @@ export class Tag extends DOMObject {
119
114
  }
120
115
 
121
116
  mutate(mutation: MutationRecord): void {
122
- for (const attr of this.attributes) {
123
- attr.mutate(mutation);
124
- }
117
+ this.attributes.map(attr => attr.mutate(mutation));
125
118
  this.dispatch('mutate', mutation);
126
119
  }
127
120
 
@@ -11,4 +11,4 @@ export class AddClassIf extends If {
11
11
  this.tag.element.classList.remove(this.getAttributeBinding());
12
12
  }
13
13
  }
14
- }
14
+ }
@@ -1,7 +1,5 @@
1
1
  export {AddClassIf} from "./AddClassIf";
2
2
  export {Bind} from "./Bind";
3
- export {ClickRemoveClass} from "./ClickRemoveClass";
4
- export {ClickToggleClass} from "./ClickToggleClass";
5
3
  export {ControllerAttribute} from "./ControllerAttribute";
6
4
  export {DisableIf} from "./DisableIf";
7
5
  export {Exec} from "./Exec";
@@ -47,4 +47,17 @@ export class VisionHelper {
47
47
  setTimeout(callback, timeout);
48
48
  }
49
49
  }
50
+
51
+ public static get wasmSupport(): boolean {
52
+ try {
53
+ if (typeof WebAssembly === "object"
54
+ && typeof WebAssembly.instantiate === "function") {
55
+ const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
56
+ if (module instanceof WebAssembly.Module)
57
+ return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
58
+ }
59
+ } catch (e) {
60
+ }
61
+ return false;
62
+ }
50
63
  }