solarite 0.2.4 → 0.3.1

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 (38) hide show
  1. package/dist/Solarite-debug.js +1457 -1402
  2. package/dist/Solarite.js +1425 -1272
  3. package/dist/Solarite.min.js +2 -2
  4. package/package.json +5 -6
  5. package/readme.md +2 -4
  6. package/src/{solarite/ExprPath.js → ExprPath.js} +421 -231
  7. package/src/Globals.js +79 -0
  8. package/src/HtmlParser.js +91 -0
  9. package/src/{util/MultiValueMap.js → MultiValueMap.js} +22 -26
  10. package/src/{solarite/NodeGroup.js → NodeGroup.js} +286 -226
  11. package/src/{solarite/Shell.js → Shell.js} +119 -92
  12. package/src/Solarite.d.ts +62 -0
  13. package/src/{solarite/Solarite.js → Solarite.js} +15 -13
  14. package/src/{solarite/Template.js → Template.js} +22 -19
  15. package/src/Util.js +330 -0
  16. package/src/{util/Errors.js → assert.js} +1 -0
  17. package/src/createSolarite.js +154 -0
  18. package/src/{util/delve.js → delve.js} +5 -4
  19. package/src/{solarite/getArg.js → getArg.js} +41 -15
  20. package/src/{solarite/r.js → h.js} +59 -29
  21. package/src/{solarite/hash.js → hash.js} +12 -9
  22. package/src/unused/FastLookupArray.js +54 -0
  23. package/src/unused/Hashes.js +339 -0
  24. package/src/unused/InUse.test.js +92 -0
  25. package/src/unused/InUseMap.js +98 -0
  26. package/src/unused/LinkedList.js +117 -0
  27. package/src/unused/LinkedList.test.js +115 -0
  28. package/src/unused/Misc.js +13 -0
  29. package/src/unused/Perf.js +47 -0
  30. package/src/unused/TrackedArray.js +54 -0
  31. package/src/watch.js +546 -0
  32. package/src/solarite/Globals.js +0 -54
  33. package/src/solarite/Util.js +0 -388
  34. package/src/solarite/createSolarite.js +0 -274
  35. package/src/solarite/watch3.js +0 -189
  36. package/src/util/Util.js +0 -113
  37. /package/src/{solarite/udomdiff.js → udomdiff.js} +0 -0
  38. /package/src/{util → unused}/WeakArray.js +0 -0
package/src/Globals.js ADDED
@@ -0,0 +1,79 @@
1
+ var Globals;
2
+
3
+ /**
4
+ * Created with a reset() function because it's useful for testing. */
5
+ function reset() {
6
+ Globals = {
7
+
8
+ /**
9
+ * Used by NodeGroup.applyComponentExprs() */
10
+ componentArgsHash: new WeakMap(),
11
+
12
+ /**
13
+ * Store which instances of Solarite have already been added to the DOM.
14
+ * @type {WeakSet<HTMLElement>} */
15
+ connected: new WeakSet(),
16
+
17
+ /**
18
+ * ExprPath.applyExactNodes() sets this property when an expression is being accessed.
19
+ * watch() then adds the ExprPath to the list of ExprPaths that should be re-rendered when the value changes.
20
+ * @type {ExprPath}*/
21
+ currentExprPath: null,
22
+
23
+ div: document.createElement("div"),
24
+
25
+ /**
26
+ * @type {Record<string, Class<Node>>} A map from built-in tag names to the constructors that create them. */
27
+ elementClasses: {},
28
+
29
+ /** @type {Record<string, boolean>} Key is tag-name.propName. Value is whether it's an attribute.*/
30
+ htmlProps: {},
31
+
32
+ /**
33
+ * Used by ExprPath.applyEventAttrib()
34
+ * @type {WeakMap<Node, Record<eventName:string, [original:function, bound:function, args:*[]]>>} */
35
+ nodeEvents: new WeakMap(),
36
+
37
+ /**
38
+ * Get the RootNodeGroup for an element.
39
+ * @type {WeakMap<HTMLElement, RootNodeGroup>} */
40
+ nodeGroups: new WeakMap(),
41
+
42
+ /**
43
+ * Used by r() path 9. */
44
+ objToEl: new WeakMap(),
45
+
46
+ //pendingChildren: [],
47
+
48
+
49
+ /**
50
+ * Elements that have been rendered to by r() at least once.
51
+ * This is used by the Solarite class to know when to call onFirstConnect()
52
+ * @type {WeakSet<HTMLElement>} */
53
+ rendered: new WeakSet(),
54
+
55
+ /**
56
+ * Elements that are currently rendering via the r() function.
57
+ * @type {WeakSet<HTMLElement>} */
58
+ rendering: new WeakSet(),
59
+
60
+ /**
61
+ * Map from array of Html strings to a Shell created from them.
62
+ * @type {WeakMap<string[], Shell>} */
63
+ shells: new WeakMap(),
64
+
65
+ /**
66
+ * A map of individual untagged strings to their Templates.
67
+ * This way we don't keep creating new Templates for the same string when re-rendering.
68
+ * This is used by ExprPath.applyExactNodes()
69
+ * @type {Record<string, Template>} */
70
+ //stringTemplates: {},
71
+
72
+ reset,
73
+
74
+ count: 0
75
+ };
76
+ }
77
+ reset();
78
+
79
+ export default Globals;
@@ -0,0 +1,91 @@
1
+
2
+ export default class HtmlParser {
3
+ constructor() {
4
+ this.defaultState = {
5
+ context: HtmlParser.Text, // possible values: 'TEXT', 'TAG', 'ATTRIBUTE'
6
+ quote: null, // possible values: null, '"', "'"
7
+ buffer: '',
8
+ lastChar: null
9
+ };
10
+ this.state = {...this.defaultState};
11
+ }
12
+
13
+ reset() {
14
+ this.state = {...this.defaultState};
15
+ return this.state.context;
16
+ }
17
+
18
+ /**
19
+ * Parse the next chunk of html, starting with the same context we left off with from the previous chunk.
20
+ * @param html {string}
21
+ * @param onContextChange {?function(html:string, index:int, oldContext:string, newContext:string)}
22
+ * Called every time the context changes, and again at the last context.
23
+ * @return {('Attribute','Text','Tag')} The context at the end of html. */
24
+ parse(html, onContextChange=null) {
25
+ if (html === null)
26
+ return this.reset();
27
+
28
+ for (let i = 0; i < html.length; i++) {
29
+ const char = html[i];
30
+ switch (this.state.context) {
31
+ case HtmlParser.Text:
32
+ if (char === '<' && html[i + 1].match(/[/a-z!]/i)) { // Start of a tag or comment.
33
+ onContextChange?.(html, i, this.state.context, HtmlParser.Tag);
34
+ this.state.context = HtmlParser.Tag;
35
+ this.state.buffer = '';
36
+ }
37
+ break;
38
+ case HtmlParser.Tag:
39
+ if (char === '>') {
40
+ onContextChange?.(html, i+1, this.state.context, HtmlParser.Text);
41
+ this.state.context = HtmlParser.Text;
42
+ this.state.quote = null;
43
+ this.state.buffer = '';
44
+ }
45
+ else if (char === ' ' && !this.state.buffer) {
46
+ // No attribute name is present. Skipping the space.
47
+ continue;
48
+ }
49
+ else if (char === ' ' || char === '/' || char === '?') {
50
+ this.state.buffer = ''; // Reset the buffer when a delimiter or potential self-closing sign is found.
51
+ }
52
+ else if (char === '"' || char === "'" || char === '=') {
53
+ onContextChange?.(html, i, this.state.context, HtmlParser.Attribute);
54
+ this.state.context = HtmlParser.Attribute;
55
+ this.state.quote = char === '=' ? null : char;
56
+ this.state.buffer = '';
57
+ }
58
+ else
59
+ this.state.buffer += char;
60
+ break;
61
+ case HtmlParser.Attribute:
62
+ // Start an attribute quote.
63
+ if (!this.state.quote && !this.state.buffer.length && (char === '"' || char === "'")) {
64
+ this.state.quote = char;
65
+ }
66
+ else if (char === this.state.quote || (!this.state.quote && this.state.buffer.length)) {
67
+ onContextChange?.(html, i, this.state.context, HtmlParser.Tag);
68
+ this.state.context = HtmlParser.Tag;
69
+ this.state.quote = null;
70
+ this.state.buffer = '';
71
+ }
72
+ else if (!this.state.quote && char === '>') {
73
+ onContextChange?.(html, i+1, this.state.context, HtmlParser.Text);
74
+ this.state.context = HtmlParser.Text;
75
+ this.state.quote = null;
76
+ this.state.buffer = '';
77
+ }
78
+ else if (char !== ' ')
79
+ this.state.buffer += char;
80
+
81
+ break;
82
+ }
83
+ }
84
+ onContextChange?.(html, html.length, this.state.context, null);
85
+ return this.state.context;
86
+ }
87
+ }
88
+
89
+ HtmlParser.Attribute = 'Attribute';
90
+ HtmlParser.Text = 'Text';
91
+ HtmlParser.Tag = 'Tag';
@@ -1,6 +1,6 @@
1
1
  export default class MultiValueMap {
2
2
 
3
- /** @type {Object<string, Set>} */
3
+ /** @type {Record<string, Set>} */
4
4
  data = {};
5
5
 
6
6
  // Set a new value for a key
@@ -34,23 +34,14 @@ export default class MultiValueMap {
34
34
  * @param val If specified, make sure we delete this specific value, if a key exists more than once.
35
35
  * @returns {*|undefined} The deleted item. */
36
36
  delete(key, val=undefined) {
37
- // if (key === '["Html2",[[["Html3",["F1","A"]],["Html3",["F1","B"]]]]]')
38
- // debugger;
39
-
40
37
  let data = this.data;
41
-
42
- // if (!data.hasOwnProperty(key))
43
- // return undefined;
44
-
45
- // Delete a specific value.
46
38
  let result;
47
39
  let set = data[key];
48
- if (!set) // slower than pre-check.
40
+ if (!set)
49
41
  return undefined;
50
42
 
51
43
  // Delete any value.
52
44
  if (val === undefined) {
53
- //result = set.values().next().value; // get first item from set.
54
45
  [result] = set; // Does the same as above and seems to be about the same speed.
55
46
  set.delete(result);
56
47
  }
@@ -61,7 +52,6 @@ export default class MultiValueMap {
61
52
  result = val;
62
53
  }
63
54
 
64
- // TODO: Will this make it slower?
65
55
  if (set.size === 0)
66
56
  delete data[key];
67
57
 
@@ -69,28 +59,34 @@ export default class MultiValueMap {
69
59
  }
70
60
 
71
61
  /**
72
- * Try to delete an item that matches the key and the isPreferred function.
73
- * if not the latter, just delete any item that matches the key.
62
+ * Remove one value from a key, and return it.
74
63
  * @param key {string}
75
- * @param isPreferred {function}
76
64
  * @returns {*|undefined} The deleted item. */
77
- deletePreferred(key, isPreferred) {
65
+ deleteAny(key) {
66
+ let data = this.data;
78
67
  let result;
68
+ let set = data[key];
69
+ if (!set) // slower than pre-check.
70
+ return undefined;
71
+
72
+ [result] = set; // Does the same as above and seems to be about the same speed.
73
+ set.delete(result);
74
+
75
+ if (set.size === 0)
76
+ delete data[key];
77
+
78
+ return result;
79
+ }
80
+
81
+ deleteSpecific(key, val) {
79
82
  let data = this.data;
83
+ let result;
80
84
  let set = data[key];
81
85
  if (!set)
82
86
  return undefined;
83
87
 
84
- for (let val of set)
85
- if (isPreferred(val)) {
86
- set.delete(val);
87
- result = val;
88
- break;
89
- }
90
- if (!result) {
91
- [result] = set;
92
- set.delete(result);
93
- }
88
+ set.delete(val);
89
+ result = val;
94
90
 
95
91
  if (set.size === 0)
96
92
  delete data[key];