solarite 0.3.2 → 0.5.0

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/src/watch.js CHANGED
@@ -28,11 +28,11 @@ class WatchExample extends Solarite {
28
28
  }
29
29
 
30
30
  render() {
31
- r(this)`
31
+ h(this)`
32
32
  <watch-example>
33
33
  ${() => this.name + '!'}
34
34
 
35
- ${this.items.map(item => r`
35
+ ${this.items.map(item => h`
36
36
  <div>${item.name}</div>
37
37
  `)}
38
38
  ${() => this.items.length}
@@ -44,7 +44,7 @@ customElements.define('watch-example', WatchExample);
44
44
  let a = new WatchExample();
45
45
 
46
46
  // Items is a Proxy.
47
- // Calling push() will trigger the map'd ExprPaths to add another at the end.
47
+ // Calling push() will trigger the map'd Paths to add another at the end.
48
48
  // And the .length expression to update.
49
49
  // Because accessing .items returns a proxy.
50
50
  a.items.push({name: 'Fred'});
@@ -52,7 +52,7 @@ a.items.push({name: 'Fred'});
52
52
 
53
53
  import Globals from "./Globals.js";
54
54
  import Util from "./Util.js";
55
- import {assert} from "./assert.js";
55
+ import assert from "./assert.js";
56
56
 
57
57
  let unusedArg = Symbol('unusedArg');
58
58
 
@@ -65,12 +65,12 @@ function removeProxy(obj) {
65
65
  }
66
66
 
67
67
  /**
68
- * Render the ExprPaths that were added to rootNg.exprsToRender.
68
+ * Render the Paths that were added to rootNg.exprsToRender.
69
69
  * @param root {HTMLElement}
70
70
  * @param trackModified {boolean}
71
71
  * @returns {Node[]} Modified elements. */
72
72
  export function renderWatched(root, trackModified=false) {
73
- let rootNg = Globals.nodeGroups.get(root);
73
+ let rootNg = Globals.rootNodeGroups.get(root);
74
74
  let modified;
75
75
 
76
76
  if (trackModified)
@@ -78,27 +78,27 @@ export function renderWatched(root, trackModified=false) {
78
78
 
79
79
 
80
80
  // Mark NodeGroups of expressionpaths as freed.
81
- // for (let [exprPath, ops] of rootNg.exprsToRender) {
81
+ // for (let [Path, ops] of rootNg.exprsToRender) {
82
82
  // if (ops instanceof WholeArrayOp) {}
83
83
  // else if (ops instanceof ValueOp) {}
84
84
  // else {} // Array Slice Op
85
85
  // }
86
86
 
87
- for (let [exprPath, ops] of rootNg.exprsToRender) {
87
+ for (let [Path, ops] of rootNg.exprsToRender) {
88
88
 
89
89
  // Reapply the whole expression.
90
90
  if (ops instanceof WholeArrayOp) {
91
91
 
92
92
  // So it doesn't use the old value inside the map callback in the get handler above.
93
93
  // TODO: Find a more sensible way to pass newValue.
94
- ops.markNodeGroupsAvailable(exprPath);
95
- exprPath.watchFunction.newValue = ops.array;
96
- exprPath.apply([exprPath.watchFunction], false);
94
+ ops.markNodeGroupsAvailable(Path);
95
+ Path.watchFunction.newValue = ops.array;
96
+ Path.apply([Path.watchFunction], false);
97
97
 
98
- //exprPath.freeNodeGroups();
98
+ //Path.freeNodeGroups();
99
99
 
100
100
  if (trackModified)
101
- modified.add(...exprPath.getNodes());
101
+ modified.add(Path.nodeMarker);
102
102
  }
103
103
 
104
104
  // Update a single value in a map callback
@@ -106,13 +106,13 @@ export function renderWatched(root, trackModified=false) {
106
106
  else if (ops instanceof ValueOp) {
107
107
 
108
108
  // TODO: I need to only free node groups of watched expressions.
109
- exprPath.watchFunction.newValue = ops.value;
110
- exprPath.apply([exprPath.watchFunction], false); // False to not free nodeGroups.
109
+ Path.watchFunction.newValue = ops.value;
110
+ Path.apply([Path.watchFunction], false); // False to not free nodeGroups.
111
111
 
112
- //exprPath.freeNodeGroups();
112
+ //Path.freeNodeGroups();
113
113
 
114
114
  if (trackModified)
115
- modified.add(...exprPath.getNodes());
115
+ modified.add(...Path.getNodes());
116
116
  }
117
117
 
118
118
  // Selectively update NodeGroups created by array.map()
@@ -130,8 +130,8 @@ export function renderWatched(root, trackModified=false) {
130
130
  && op.array[op.index] === nextOp.firstDeleted
131
131
  ) {
132
132
 
133
- let nga = exprPath.nodeGroups[op.index];
134
- let ngb = exprPath.nodeGroups[nextOp.index];
133
+ let nga = Path.nodeGroups[op.index];
134
+ let ngb = Path.nodeGroups[nextOp.index];
135
135
 
136
136
  // Swap the nodegroup nga and ngb node positions
137
137
  let nextA = nga.endNode.nextSibling;
@@ -156,8 +156,8 @@ export function renderWatched(root, trackModified=false) {
156
156
  nextB.parentNode.insertBefore(node, nextB);
157
157
  */
158
158
 
159
- exprPath.nodeGroups[op.index] = ngb;
160
- exprPath.nodeGroups[nextOp.index] = nga;
159
+ Path.nodeGroups[op.index] = ngb;
160
+ Path.nodeGroups[nextOp.index] = nga;
161
161
 
162
162
  if (trackModified) {
163
163
  nga.getNodes().map(n => modified.add(n));
@@ -171,14 +171,14 @@ export function renderWatched(root, trackModified=false) {
171
171
 
172
172
  if (trackModified && op.deleteCount)
173
173
  modified.add(
174
- ...exprPath.nodeGroups.slice(op.index, op.index + op.deleteCount).map(ng => ng.getNodes()).flat()
174
+ ...Path.nodeGroups.slice(op.index, op.index + op.deleteCount).map(ng => ng.getNodes()).flat()
175
175
  );
176
176
 
177
- op.markNodeGroupsAvailable(exprPath);
178
- exprPath.applyArrayOp(op);
177
+ op.markNodeGroupsAvailable(Path);
178
+ Path.applyWatchArrayOp(op);
179
179
 
180
180
  if (trackModified && op.items.length) {
181
- exprPath.nodeGroups.slice(op.index, op.index + op.items.length)
181
+ Path.nodeGroups.slice(op.index, op.index + op.items.length)
182
182
  .map(ng => ng.getNodes())
183
183
  .flat()
184
184
  .map(n => modified.add(n));
@@ -213,14 +213,14 @@ class ProxyHandler {
213
213
  /** @type {Record<string, [Proxy, ProxyHandler]>} Proxies for child properties. */
214
214
  proxies = {}
215
215
 
216
- /** @type Set<ExprPath> ExprPaths that will need to be re-rendered when this variable is modified. */
217
- exprPaths = new Set();
216
+ /** @type Set<Path> Paths that will need to be re-rendered when this variable is modified. */
217
+ paths = new Set();
218
218
 
219
219
  /**
220
- * ExprPaths that will need to be re-rendered when one of this variable's primitive properties is modified,
220
+ * Paths that will need to be re-rendered when one of this variable's primitive properties is modified,
221
221
  * since primitives can't have their own ProxyHandler.
222
- * @type {Record<prop:string, affected:Set<ExprPath>>} */
223
- childExprPaths = {};
222
+ * @type {Record<prop:string, affected:Set<Path>>} */
223
+ childPaths = {};
224
224
 
225
225
 
226
226
  constructor(root, value) {
@@ -250,8 +250,8 @@ class ProxyHandler {
250
250
  }
251
251
 
252
252
  /**
253
- * We override get() so we can mark which ExprPaths read from each variable in the hierarchy.
254
- * Then later when we call set on a variable, we can see which ExprPaths use it, and can mark them to be re-rendered.
253
+ * We override get() so we can mark which Paths read from each variable in the hierarchy.
254
+ * Then later when we call set on a variable, we can see which Paths use it, and can mark them to be re-rendered.
255
255
  * @param obj
256
256
  * @param prop {string}
257
257
  * @param receiver
@@ -261,9 +261,6 @@ class ProxyHandler {
261
261
  if (prop === '$removeProxy')
262
262
  return obj;
263
263
 
264
- // if (prop === 'items')
265
- // debugger;
266
-
267
264
  const result = (obj === receiver)
268
265
  ? this.value // top-level value.
269
266
  : Reflect.get(obj, prop, receiver); // avoid infinite recursion.
@@ -276,22 +273,22 @@ class ProxyHandler {
276
273
 
277
274
  const self = this;
278
275
 
279
- // This outer function is so the ExprPath calls it as a function,
276
+ // This outer function is so the Path calls it as a function,
280
277
  // instead of it being evaluated immediately when the Template is created.
281
- // This allows ExprPath.apply() to set the Globals.currentExprPath before evaluating further.
278
+ // This allows Path.apply() to set the Globals.currentPath before evaluating further.
282
279
  return (callback) =>
283
280
 
284
281
  // This is the new map function.
285
282
  function mapFunction() {
286
283
 
287
- // Save the ExprPaths that called the array used by .map()
288
- const currExprPath = Globals.currentExprPath;
289
- if (currExprPath)
290
- self.exprPaths.add(currExprPath);
284
+ // Save the Paths that called the array used by .map()
285
+ const currPath = Globals.currentPath;
286
+ if (currPath)
287
+ self.paths.add(currPath);
291
288
 
292
289
  // Apply the map function.
293
290
  const newObj = mapFunction.newValue || obj;
294
- Globals.currentExprPath.mapCallback = callback;
291
+ Globals.currentPath.mapCallback = callback;
295
292
  // If new Proxy fails b/c newObj isn't an object, make sure the expression is a function.
296
293
  // TODO: Find a way to warn about this automatically.
297
294
  let p = new Proxy(newObj, self);
@@ -300,75 +297,75 @@ class ProxyHandler {
300
297
  }
301
298
 
302
299
  else if (prop === 'push' || prop==='pop' || prop === 'splice') {
303
- const rootNg = Globals.nodeGroups.get(this.root);
304
- return new WatchedArray(rootNg, obj, this.exprPaths)[prop];
300
+ const rootNg = Globals.rootNodeGroups.get(this.root);
301
+ return new WatchedArray(rootNg, obj, this.paths)[prop];
305
302
  }
306
303
  }
307
304
 
308
305
 
309
- // Save the ExprPath that's currently accessing this variable.
310
- const currExprPath = Globals.currentExprPath;
306
+ // Save the Path that's currently accessing this variable.
307
+ const currPath = Globals.currentPath;
311
308
 
312
309
  // Accessing a sub-property
313
310
  if (result && typeof result === 'object') {
314
311
  let [proxiedResult, handler] = this.getProxyandHandler(prop, result); // Clone this handler and append prop to the path.
315
312
 
316
- if (currExprPath && prop !== 'constructor')
317
- handler.exprPaths.add(currExprPath);
313
+ if (currPath && prop !== 'constructor')
314
+ handler.paths.add(currPath);
318
315
 
319
316
  return proxiedResult;
320
317
  }
321
318
  else {
322
- if (currExprPath && prop !== 'constructor') {
319
+ if (currPath && prop !== 'constructor') {
323
320
 
324
321
  // We can't have Proxies on primitive types,
325
322
  // So we store the affected expressions in the parent Proxy.
326
- if (!this.childExprPaths[prop])
327
- this.childExprPaths[prop] = new Set([currExprPath]);
323
+ if (!this.childPaths[prop])
324
+ this.childPaths[prop] = new Set([currPath]);
328
325
  else
329
- this.childExprPaths[prop].add(currExprPath);
326
+ this.childPaths[prop].add(currPath);
330
327
  }
331
328
 
332
329
  return result;
333
330
  }
334
331
  }
335
332
 
336
- // TODO: Will fail for attribute w/ a value having multiple ExprPaths.
333
+ // TODO: Will fail for attribute w/ a value having multiple Paths.
337
334
  // TODO: This won't update a component's expressions.
338
335
  set(obj, prop, val, receiver) {
339
336
 
340
337
  val = removeProxy(val);
341
338
 
342
- // 1. Add to the list of ExprPaths to re-render.
339
+ // 1. Add to the list of Paths to re-render.
343
340
  if (!this.rootNodeGroup)
344
- this.rootNodeGroup = Globals.nodeGroups.get(this.root);
341
+ this.rootNodeGroup = Globals.rootNodeGroups.get(this.root);
345
342
  const rootNg = this.rootNodeGroup
346
343
 
347
344
  // New: // TODO: Should I instead be checking if the old value of val is a primitive?
348
345
  let isPrimitive = !val || typeof val !== 'object';
349
- let exprPaths = isPrimitive
350
- ? this.childExprPaths[prop] || []
351
- : this.getProxyandHandler(prop, val)[1].exprPaths;
346
+ let paths = isPrimitive
347
+ ? this.childPaths[prop] || []
348
+ : this.getProxyandHandler(prop, val)[1].paths;
352
349
 
353
350
  const isArray = Array.isArray(obj);
354
- for (let exprPath of exprPaths) {
351
+ for (let Path of paths) {
355
352
 
356
353
  if (isArray) {
357
354
  if (Number.isInteger(+prop)) {
358
- const exprsToRender = rootNg.exprsToRender.get(exprPath);
355
+ const exprsToRender = rootNg.exprsToRender.get(Path);
359
356
 
360
357
  // If we're not re-rendering the whole thing.
361
358
  if (!(exprsToRender instanceof WholeArrayOp))
362
359
  // TODO: Inline this for performance
363
- Util.mapArrayAdd(rootNg.exprsToRender, exprPath, new ArraySpliceOp(obj, prop, 1, [val]));
360
+ Util.mapArrayAdd(rootNg.exprsToRender, Path, new ArraySpliceOp(obj, prop, 1, [val]));
364
361
  }
365
362
 
366
363
  // Reapply the whole expression.
367
364
  else
368
- rootNg.exprsToRender.set(exprPath, new WholeArrayOp(val));
365
+ rootNg.exprsToRender.set(Path, new WholeArrayOp(val));
369
366
  }
370
367
  else
371
- rootNg.exprsToRender.set(exprPath, new ValueOp(val));
368
+ rootNg.exprsToRender.set(Path, new ValueOp(val));
372
369
  }
373
370
 
374
371
  // 2. Set the value.
@@ -397,7 +394,7 @@ class ProxyHandler {
397
394
  * TODO
398
395
  *
399
396
  *
400
- * @param root {HTMLElement} An instance of a Web Component that uses r() to render its content.
397
+ * @param root {HTMLElement} An instance of a Web Component that uses h() to render its content.
401
398
  * @param field {string} The name of a top-level property of root.
402
399
  * @param value {string|Symbol} The default value. */
403
400
  export default function watch(root, field, value=unusedArg) {
@@ -418,21 +415,21 @@ export {watch};
418
415
 
419
416
  /**
420
417
  * Wrap an array so that functions that modify the array are intercepted.
421
- * We then add ArraySpliceOp's to the list of ops to run for each affected ExprPath.
418
+ * We then add ArraySpliceOp's to the list of ops to run for each affected Path.
422
419
  * When renderWatched() is called it then applies those ops to the NodeGroups created by the map() function. */
423
420
  class WatchedArray {
424
421
 
425
422
  /**
426
423
  * @param array {Array}
427
424
  * @param rootNg {RootNodeGroup}
428
- * @param exprPaths {ExprPath[]|Set<ExprPath>} Expression paths that use this array. */
429
- constructor(rootNg, array, exprPaths) {
425
+ * @param paths {Path[]|Set<Path>} Expression paths that use this array. */
426
+ constructor(rootNg, array, paths) {
430
427
  this.rootNg = rootNg;
431
428
  //#IFDEV
432
429
  assert(Array.isArray(array));
433
430
  //#ENDIF
434
431
  this.array = array;
435
- this.exprPaths = exprPaths;
432
+ this.paths = paths;
436
433
  this.push = this.push.bind(this);
437
434
  this.pop = this.pop.bind(this);
438
435
  this.splice = this.splice.bind(this);
@@ -453,10 +450,10 @@ class WatchedArray {
453
450
 
454
451
  internalSplice(func, args, spliceArgs) {
455
452
  // Mark all expressions affected by the array function to be re-rendered
456
- for (let exprPath of this.exprPaths) {
457
- let exprsToRender = this.rootNg.exprsToRender.get(exprPath);
453
+ for (let Path of this.paths) {
454
+ let exprsToRender = this.rootNg.exprsToRender.get(Path);
458
455
  if (!(exprsToRender instanceof WholeArrayOp)) // If we're not already going to re-render the whole array.
459
- Util.mapArrayAdd(this.rootNg.exprsToRender, exprPath, new ArraySpliceOp(...spliceArgs));
456
+ Util.mapArrayAdd(this.rootNg.exprsToRender, Path, new ArraySpliceOp(...spliceArgs));
460
457
  }
461
458
 
462
459
  // Call original array function
@@ -492,13 +489,13 @@ export class ArraySpliceOp extends WatchOp {
492
489
  this.firstDeleted = deleteCount===1 ? array[index] : undefined;
493
490
  }
494
491
 
495
- markNodeGroupsAvailable(exprPath) {
492
+ markNodeGroupsAvailable(Path) {
496
493
  if (this.deleteCount > 0) {
497
494
  let count = this.index+this.deleteCount;
498
495
  for (let i=this.index; i<count; i++) {
499
- let oldNg = exprPath.nodeGroups[i];
500
- exprPath.nodeGroupsAttachedAvailable.add(oldNg.exactKey, oldNg);
501
- exprPath.nodeGroupsAttachedAvailable.add(oldNg.closeKey, oldNg);
496
+ let oldNg = Path.nodeGroups[i];
497
+ Path.nodeGroupsAttachedAvailable.add(oldNg.exactKey, oldNg);
498
+ Path.nodeGroupsAttachedAvailable.add(oldNg.closeKey, oldNg);
502
499
  }
503
500
  }
504
501
  }
@@ -510,7 +507,7 @@ class ValueOp extends WatchOp {
510
507
  this.value = value;
511
508
  }
512
509
 
513
- markNodeGroupsAvailable(exprPath) {}
510
+ markNodeGroupsAvailable(Path) {}
514
511
  }
515
512
 
516
513
  // We detect such ops but we never need to instantiate this class.
@@ -536,11 +533,11 @@ class WholeArrayOp extends WatchOp {
536
533
  this.value = value;
537
534
  }
538
535
 
539
- markNodeGroupsAvailable(exprPath) {
540
- for (let i=0; i<exprPath.nodeGroups.length; i++) {
541
- let oldNg = exprPath.nodeGroups[i];
542
- exprPath.nodeGroupsAttachedAvailable.add(oldNg.exactKey, oldNg);
543
- exprPath.nodeGroupsAttachedAvailable.add(oldNg.closeKey, oldNg);
536
+ markNodeGroupsAvailable(Path) {
537
+ for (let i=0; i<Path.nodeGroups.length; i++) {
538
+ let oldNg = Path.nodeGroups[i];
539
+ Path.nodeGroupsAttachedAvailable.add(oldNg.exactKey, oldNg);
540
+ Path.nodeGroupsAttachedAvailable.add(oldNg.closeKey, oldNg);
544
541
  }
545
542
  }
546
543
  }