malinajs 0.7.0-a5 → 0.7.0-a6

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 (3) hide show
  1. package/malina.js +43 -17
  2. package/package.json +1 -1
  3. package/runtime.js +13 -16
package/malina.js CHANGED
@@ -1277,7 +1277,6 @@
1277
1277
  let source = this.scriptNodes.length ? this.scriptNodes[0].content : null;
1278
1278
  this.script = {
1279
1279
  source,
1280
- watchers: [],
1281
1280
  imports: [],
1282
1281
  importedNames: [],
1283
1282
  autosubscribeNames: [],
@@ -1429,7 +1428,7 @@
1429
1428
  function walk(node, parent, fn) {
1430
1429
  if(typeof node !== 'object') return;
1431
1430
 
1432
- if(node._apply) return;
1431
+ if(node._apply && node.type == 'ExpressionStatement') return;
1433
1432
  node._parent = parent;
1434
1433
  let forParent = parent;
1435
1434
  if(node.type) {
@@ -1467,6 +1466,8 @@
1467
1466
  };
1468
1467
  }
1469
1468
 
1469
+ let watchers = xNode('block');
1470
+
1470
1471
  const makeWatch = (n) => {
1471
1472
  function assertExpression(n) {
1472
1473
  if(['Identifier', 'TemplateLiteral', 'Literal'].includes(n.type)) return;
@@ -1483,15 +1484,22 @@
1483
1484
  target = ex.left.name;
1484
1485
  if(!(target in rootVariables)) resultBody.push(makeVariable(target));
1485
1486
  } else if(ex.left.type == 'MemberExpression') {
1486
- target = source.substring(ex.left.start, ex.left.end);
1487
+ target = astring.generate(ex.left);
1487
1488
  } else throw 'Error';
1488
1489
  assertExpression(ex.right);
1489
- const exp = source.substring(ex.right.start, ex.right.end);
1490
- result.watchers.push(`$runtime.prefixPush(() => {${target} = ${exp};});`);
1490
+ const exp = astring.generate(ex.right);
1491
+ watchers.push(xNode('watch-assign', {
1492
+ $wait: ['apply'],
1493
+ target,
1494
+ exp
1495
+ }, (ctx, n) => {
1496
+ if(this.inuse.apply) ctx.write(true, `$runtime.prefixPush(() => {${n.target} = ${n.exp};});`);
1497
+ else ctx.write(true, `${n.target} = ${n.exp};`);
1498
+ }));
1491
1499
  } else if(n.body.expression.type == 'SequenceExpression') {
1492
1500
  const ex = n.body.expression.expressions;
1493
- const handler = ex[ex.length - 1];
1494
- let callback = source.substring(handler.start, handler.end);
1501
+ const handler = last(ex);
1502
+ let callback = astring.generate(handler);
1495
1503
  if(handler.type == 'ArrowFunctionExpression' || handler.type == 'FunctionExpression') ; else if(detectExpressionType(callback) == 'identifier') {
1496
1504
  callback = `(v) => { ${callback}(v); }`;
1497
1505
  } else {
@@ -1500,13 +1508,33 @@
1500
1508
 
1501
1509
  if(ex.length == 2) {
1502
1510
  assertExpression(ex[0]);
1503
- let exp = source.substring(ex[0].start, ex[0].end);
1504
- if(this.config.immutable) result.watchers.push(`$watch(() => (${exp}), ${callback}, {ro: false});`);
1505
- else result.watchers.push(`$watch(() => (${exp}), ${callback}, {ro: false, cmp: $runtime.$$deepComparator(0)});`);
1511
+ watchers.push(xNode('watch-expression', {
1512
+ $wait: ['apply'],
1513
+ exp: astring.generate(ex[0]),
1514
+ callback
1515
+ }, (ctx, n) => {
1516
+ if(this.inuse.apply) {
1517
+ if(this.config.immutable) ctx.write(true, `$watch(() => (${n.exp}), ${n.callback});`);
1518
+ else ctx.write(true, `$watch(() => (${n.exp}), ${n.callback}, {cmp: $runtime.$$deepComparator(0)});`);
1519
+ } else {
1520
+ ctx.write(true, `(${n.callback})(${n.exp});`);
1521
+ }
1522
+ }));
1506
1523
  } else if(ex.length > 2) {
1507
1524
  for(let i = 0; i < ex.length - 1; i++) assertExpression(ex[i]);
1508
- let exp = source.substring(ex[0].start, ex[ex.length - 2].end);
1509
- result.watchers.push(`$watch(() => [${exp}], ($args) => { (${callback}).apply(null, $args); }, {ro: false, cmp: $runtime.$$deepComparator(1)});`);
1525
+ let exp = {
1526
+ type: 'ArrayExpression',
1527
+ elements: ex.slice(0, ex.length - 1)
1528
+ };
1529
+
1530
+ watchers.push(xNode('watch-expression', {
1531
+ $wait: ['apply'],
1532
+ exp: astring.generate(exp),
1533
+ callback
1534
+ }, (ctx, n) => {
1535
+ if(this.inuse.apply) ctx.write(true, `$watch(() => ${n.exp}, ($args) => { (${n.callback}).apply(null, $args); }, {cmp: $runtime.$$deepComparator(1)});`);
1536
+ else ctx.write(true, `(${n.callback}).apply(null, ${n.exp})`);
1537
+ }));
1510
1538
  } else throw 'Error';
1511
1539
  } else throw 'Error';
1512
1540
  };
@@ -1634,6 +1662,7 @@
1634
1662
  }));
1635
1663
 
1636
1664
  this.module.top.push(xNode('ast', { body: imports }));
1665
+ this.module.code.push(watchers);
1637
1666
 
1638
1667
  if(this.scriptNodes[0] && this.scriptNodes[0].attributes.some(a => a.name == 'property') && this.script.props.length && !this.script.readOnly) {
1639
1668
  this.require('apply');
@@ -1770,9 +1799,6 @@
1770
1799
 
1771
1800
  if(this.script.onMount) runtime.push('$runtime.$onMount(onMount);');
1772
1801
  if(this.script.onDestroy) runtime.push('$runtime.$onDestroy(onDestroy);');
1773
- if(this.script.watchers.length) {
1774
- this.script.watchers.forEach(n => runtime.push(n));
1775
- }
1776
1802
 
1777
1803
  runtime.push(xNode('addStyle', ctx => {
1778
1804
  if(!this.css.active()) return;
@@ -6270,7 +6296,7 @@
6270
6296
  return { event, fn, rootModifier };
6271
6297
  }
6272
6298
 
6273
- const version = '0.7.0-a5';
6299
+ const version = '0.7.0-a6';
6274
6300
 
6275
6301
 
6276
6302
  async function compile(source, config = {}) {
@@ -6395,7 +6421,7 @@
6395
6421
  await hook(ctx, 'js:before');
6396
6422
  ctx.js_parse();
6397
6423
  await hook(ctx, 'js');
6398
- ctx.js_transform();
6424
+ use_context(ctx, () => ctx.js_transform());
6399
6425
  await hook(ctx, 'js:after');
6400
6426
 
6401
6427
  await hook(ctx, 'css:before');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.7.0-a5",
3
+ "version": "0.7.0-a6",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "prepare": "npm run build",
package/runtime.js CHANGED
@@ -30,7 +30,6 @@ const $onDestroy = fn => fn && current_destroyList.push(fn);
30
30
  function WatchObject(fn, cb) {
31
31
  this.fn = fn;
32
32
  this.cb = cb;
33
- this.ro = true;
34
33
  this.value = NaN;
35
34
  this.cmp = null;
36
35
  }
@@ -101,7 +100,6 @@ function $$compareArray(w, value) {
101
100
  if(isArray(value)) w.value = value.slice();
102
101
  else w.value = value;
103
102
  w.cb(w.value);
104
- return w.ro ? 0 : 1;
105
103
  }
106
104
 
107
105
 
@@ -159,7 +157,6 @@ function $$deepComparator(depth) {
159
157
  let diff = compareDeep(w.value, value, depth);
160
158
  diff && (w.value = cloneDeep(value, depth), !w.idle && w.cb(value));
161
159
  w.idle = false;
162
- return !w.ro && diff ? 1 : 0;
163
160
  };
164
161
  }
165
162
 
@@ -174,7 +171,6 @@ const keyComparator = (w, value) => {
174
171
  }
175
172
  diff && !w.idle && w.cb(value);
176
173
  w.idle = false;
177
- return !w.ro && diff ? 1 : 0;
178
174
  };
179
175
 
180
176
 
@@ -186,27 +182,26 @@ const fire = w => {
186
182
  }
187
183
  };
188
184
 
189
- function $digest($cd) {
185
+ function $digest($cd, flag) {
190
186
  let loop = 10;
191
187
  let w;
192
188
  while(loop >= 0) {
193
- let changes = 0;
194
189
  let index = 0;
195
190
  let queue = [];
196
- let i, value, cd = $cd;
191
+ let i, value, cd = $cd, changes = 0;
197
192
  while(cd) {
198
193
  for(i = 0; i < cd.prefix.length; i++) cd.prefix[i]();
199
194
  for(i = 0; i < cd.watchers.length; i++) {
200
195
  w = cd.watchers[i];
201
196
  value = w.fn();
202
197
  if(w.value !== value) {
198
+ flag[0] = 0;
203
199
  if(w.cmp) {
204
- changes += w.cmp(w, value);
200
+ w.cmp(w, value);
205
201
  } else {
206
- w.value = value;
207
- if(!w.ro) changes++;
208
- w.cb(w.value);
202
+ w.cb(w.value = value);
209
203
  }
204
+ changes += flag[0];
210
205
  }
211
206
  }
212
207
  if(cd.children.length) queue.push.apply(queue, cd.children);
@@ -356,13 +351,14 @@ const makeApply = () => {
356
351
  let $cd = current_component.$cd = current_cd = cd_new();
357
352
  $cd.component = current_component;
358
353
 
359
- let planned;
354
+ let planned, flag = [0];
360
355
  let apply = r => {
356
+ flag[0]++;
361
357
  if(planned) return r;
362
358
  planned = true;
363
359
  $tick(() => {
364
360
  try {
365
- $digest($cd);
361
+ $digest($cd, flag);
366
362
  } finally {
367
363
  planned = false;
368
364
  }
@@ -550,7 +546,7 @@ const bindAction = (element, action, fn, subscribe) => {
550
546
  } else handler = action(element);
551
547
  $onDestroy(handler?.destroy);
552
548
  subscribe?.(fn, handler, value);
553
- handler.init && $tick(handler.init);
549
+ handler?.init && $tick(handler.init);
554
550
  };
555
551
 
556
552
 
@@ -558,7 +554,7 @@ const __bindActionSubscribe = (fn, handler, value) => {
558
554
  if(handler?.update && fn) {
559
555
  $watch(fn, args => {
560
556
  handler.update.apply(handler, args);
561
- }, { ro: false, cmp: $$deepComparator(1), value: cloneDeep(value, 1) });
557
+ }, { cmp: $$deepComparator(1), value: cloneDeep(value, 1) });
562
558
  }
563
559
  };
564
560
 
@@ -1127,7 +1123,7 @@ function $$eachBlock(label, onlyChild, fn, getKey, bind) {
1127
1123
 
1128
1124
  const invokeSlotBase = ($component, slotName, $context, props, placeholder) => {
1129
1125
  let $slot = $component.$option.slots?.[slotName || 'default'];
1130
- return $slot ? $slot($component, $context, props) : placeholder?.();
1126
+ return $slot ? $slot($component, $context, props)[0] : placeholder?.();
1131
1127
  };
1132
1128
 
1133
1129
  const invokeSlot = ($component, slotName, $context, propsFn, placeholder, cmp) => {
@@ -1150,6 +1146,7 @@ const makeSlot = (fr, fn) => {
1150
1146
  let $dom = fr.cloneNode(true), prev = current_cd, $cd = current_cd = cd_new();
1151
1147
  cd_attach2(parentCD, $cd);
1152
1148
  $onDestroy(() => cd_detach($cd));
1149
+ parentCD.component.apply();
1153
1150
  try {
1154
1151
  return [$dom, fn($dom, $context, callerComponent, props)];
1155
1152
  } finally {