sprae 2.5.3 → 2.5.5

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/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "2.5.3",
4
+ "version": "2.5.5",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
7
7
  "type": "module",
8
8
  "dependencies": {
9
9
  "@preact/signals-core": "^1.2.2",
10
10
  "primitive-pool": "^2.0.0",
11
- "signal-struct": "^1.8.0",
11
+ "signal-struct": "^1.9.0",
12
12
  "swapdom": "^1.1.1"
13
13
  },
14
14
  "devDependencies": {
package/r&d.md CHANGED
@@ -324,18 +324,20 @@
324
324
  - need to match many syntax quirks, can be tedious
325
325
  ~ can be fine to limit expressions to meaningful default: why Proxy, generators, awaits, global access etc.
326
326
  - Somewhat heavy to bundle
327
- ~ 1-2kb is not super-heavy, besides signal-struct kicks out
327
+ ~ 1-2kb is not super-heavy, besides kicks out signal-struct (with preact signals?)
328
328
  + Scope is easier to provide: no need for signal proxy
329
329
  + Can detect access errors in advance
330
330
  + Syntax-level access to signals can be inavoidable: external signals still "leak in" (via arrays or etc.).
331
331
  + Updating simple objects should also rerender the template parts, not just signals.
332
332
  + Deps can be analyzed / implemented without signals
333
- - Screwed up debugging / stacktrace (unless errored)
333
+ - Screwed up debugging / stacktrace (unless errored properly)
334
+ ~+ can actually provide better trace since no internal framework stuff is shown
334
335
  + that "unlimits" returned struct, so that any property can be added/deleted.
335
336
  - doesn't really save from `new (()=>{}).constructor` hack: we gotta substitute objects too.
336
337
  + allows easier handle of `:with="a=1,b=2,c=3"` - we just naturally get local variables without messup with global
337
338
  + we can even define locals without `let`...
338
339
  - not having "comfy" compatible JS at hand: cognitive load of whole language "layer" in-between
340
+ + allows `let a = 1; a;` case instead of `let a = 1; return a;`
339
341
 
340
342
  2. Use sandboxed proxy
341
343
  - tough evaluation
@@ -391,4 +393,30 @@
391
393
  .equal Equal, =
392
394
  .period Period, .
393
395
  .slash Foward Slash, /
394
- - conflict with dot-separated events
396
+ - conflict with dot-separated events
397
+
398
+ ## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
399
+
400
+ 1. `:x="abc"` creates property + attribute
401
+ - can be excessive pollution
402
+
403
+ 2. `.x="abc"`
404
+ ~ `:x.x=""` writes both property and attribute...
405
+ - conflicts with class selector
406
+ - blocks dot-separated values
407
+ - breaks convention of reserved namespace via `:`
408
+
409
+ 2.1 `_x="abc"`
410
+ - conflicts with `_target="blank"`
411
+
412
+ 3. `:.x="abc"`
413
+ + keeps convention
414
+ + compatible with `:on*`
415
+ - can be a bit too noisy syntax
416
+
417
+ 4. `:_x`
418
+ + reference to "private"
419
+ - conflicts with `:_target="blank"`
420
+
421
+ 5. `:x="this.x=value"`
422
+ + yepyepyep
package/readme.md CHANGED
@@ -126,7 +126,7 @@ Set value of an input, textarea or select. Takes handle of `checked` and `select
126
126
 
127
127
  #### `:<prop>="value?"`, `:="props?"`
128
128
 
129
- Set any prop value or run effect.
129
+ Set any attribute value or run effect.
130
130
 
131
131
  ```html
132
132
  <!-- Single property -->
package/sprae.js CHANGED
@@ -367,38 +367,58 @@ signalStruct.isStruct = isStruct;
367
367
  function signalStruct(values, proto) {
368
368
  if (isStruct(values) && !proto)
369
369
  return values;
370
- let state, signals;
371
370
  if (isObject(values)) {
372
- state = Object.create(proto || Object.getPrototypeOf(values)), signals = {};
373
- let desc = Object.getOwnPropertyDescriptors(values);
374
- if (isStruct(values))
375
- for (let key in desc)
376
- Object.defineProperty(state, key, desc[key]);
377
- else
378
- for (let key in desc)
379
- signals[key] = defineSignal(state, key, desc[key].get ? w(desc[key].get.bind(state)) : desc[key].value);
371
+ const state = Object.create(proto || Object.getPrototypeOf(values)), signals = {}, descs = Object.getOwnPropertyDescriptors(values);
372
+ for (let key in descs) {
373
+ let desc = descs[key];
374
+ if (desc.get) {
375
+ let s2 = signals[key] = w(desc.get.bind(state));
376
+ Object.defineProperty(state, key, {
377
+ get() {
378
+ return s2.value;
379
+ },
380
+ set: desc.set?.bind(state),
381
+ configurable: false,
382
+ enumerable: true
383
+ });
384
+ } else {
385
+ let value = desc.value;
386
+ let isObservable = observable(value), s2 = signals[key] = isSignal(value) ? value : u(
387
+ isObservable ? void 0 : isObject(value) ? Object.seal(signalStruct(value)) : Array.isArray(value) ? signalStruct(value) : value
388
+ );
389
+ if (isObservable)
390
+ sube_default(value, (v2) => s2.value = v2);
391
+ Object.defineProperty(state, key, {
392
+ get() {
393
+ return s2.value;
394
+ },
395
+ set(v2) {
396
+ if (isObject(v2)) {
397
+ if (isObject(s2.value))
398
+ try {
399
+ Object.assign(s2.value, v2);
400
+ return;
401
+ } catch (e2) {
402
+ }
403
+ s2.value = Object.seal(signalStruct(v2));
404
+ } else if (Array.isArray(v2))
405
+ s2.value = signalStruct(v2);
406
+ else
407
+ s2.value = v2;
408
+ },
409
+ enumerable: true,
410
+ configurable: false
411
+ });
412
+ }
413
+ }
380
414
  Object.defineProperty(state, _struct, { configurable: false, enumerable: false, value: true });
381
415
  return state;
382
416
  }
383
- if (Array.isArray(values)) {
417
+ if (Array.isArray(values) && !isStruct(values[0])) {
384
418
  return values.map((v2) => signalStruct(v2));
385
419
  }
386
420
  return values;
387
421
  }
388
- function defineSignal(state, key, value) {
389
- let isObservable, s2 = isSignal(value) ? value : isObject(value) || Array.isArray(value) ? u(signalStruct(value)) : u((isObservable = observable(value)) ? void 0 : value);
390
- if (isObservable)
391
- sube_default(value, (v2) => s2.value = v2);
392
- Object.defineProperty(state, key, {
393
- get() {
394
- return s2.value;
395
- },
396
- set: !isSignal(value) && isObject(value) ? (v2) => v2 ? Object.assign(s2.value, v2) : s2.value = signalStruct(v2) : (v2) => s2.value = signalStruct(v2),
397
- enumerable: true,
398
- configurable: false
399
- });
400
- return s2;
401
- }
402
422
  function isObject(v2) {
403
423
  return v2 && v2.constructor === Object;
404
424
  }
@@ -690,19 +710,19 @@ directives["aria"] = (el, expr) => {
690
710
  };
691
711
  var evaluatorMemo = {};
692
712
  function parseExpr(el, expression, dir) {
693
- if (evaluatorMemo[expression])
694
- return evaluatorMemo[expression];
695
- let rightSideSafeExpression = /^[\n\s]*if.*\(.*\)/.test(expression) || /^(let|const)\s/.test(expression) ? `(() => { ${expression} })()` : expression;
696
- let evaluate;
697
- try {
698
- evaluate = new Function(`__scope`, `with (__scope) { return ${rightSideSafeExpression} };`).bind(el);
699
- } catch (e2) {
700
- return exprError(e2, el, expression, dir);
713
+ let evaluate = evaluatorMemo[expression];
714
+ if (!evaluate) {
715
+ let rightSideSafeExpression = /^[\n\s]*if.*\(.*\)/.test(expression) || /^(let|const)\s/.test(expression) ? `(() => { ${expression} })()` : expression;
716
+ try {
717
+ evaluate = evaluatorMemo[expression] = new Function(`__scope`, `with (__scope) { return ${rightSideSafeExpression} };`);
718
+ } catch (e2) {
719
+ return exprError(e2, el, expression, dir);
720
+ }
701
721
  }
702
- return evaluatorMemo[expression] = (state) => {
722
+ return (state) => {
703
723
  let result;
704
724
  try {
705
- result = evaluate(state);
725
+ result = evaluate.call(el, state);
706
726
  } catch (e2) {
707
727
  return exprError(e2, el, expression, dir);
708
728
  }
package/sprae.min.js CHANGED
@@ -1 +1 @@
1
- function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&u(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function f(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function l(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function a(t){return new l(t)}function u(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function h(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function c(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function v(t){l.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function p(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,d(t),e}finally{i=o,e()}}}function d(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,p(t)}function y(t){if(i!==this)throw new Error("Out-of-order effect");c(this),i=t,this.f&=-2,8&this.f&&d(this),e()}function b(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function m(t){var e=new b(t);return e.c(),e.d.bind(e)}l.prototype.h=function(){return!0},l.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},l.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},l.prototype.subscribe=function(t){var e=this;return m((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},l.prototype.valueOf=function(){return this.value},l.prototype.toString=function(){return this.value+""},l.prototype.peek=function(){return this.v},Object.defineProperty(l.prototype,"value",{get:function(){var t=f(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(v.prototype=new l).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!u(this))return this.f&=-2,!0;var t=i;try{h(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,c(this),this.f&=-2,!0},v.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}l.prototype.S.call(this,t)},v.prototype.U=function(t){if(l.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},v.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},v.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(v.prototype,"value",{get:function(){1&this.f&&t();var e=f(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),b.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},b.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,p(this),h(this),n++;var e=i;return i=this,y.bind(this,e)},b.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},b.prototype.d=function(){this.f|=8,1&this.f||d(this)},Symbol.observable||=Symbol("observable");var g=new FinalizationRegistry((t=>t.call?.())),S=t=>t&&t.peek,x=t=>t&&t[w],w=Symbol("signal-struct");function A(t,e){if(x(t)&&!e)return t;let i,r;if(j(t)){i=Object.create(e||Object.getPrototypeOf(t)),r={};let n=Object.getOwnPropertyDescriptors(t);if(x(t))for(let t in n)Object.defineProperty(i,t,n[t]);else for(let t in n)r[t]=O(i,t,n[t].get?new v(n[t].get.bind(i)):n[t].value);return Object.defineProperty(i,w,{configurable:!1,enumerable:!1,value:!0}),i}return Array.isArray(t)?t.map((t=>A(t))):t}function O(t,e,i){let r,n=S(i)?i:j(i)||Array.isArray(i)?a(A(i)):a((r=(o=i)&&!!(o[Symbol.observable]||o[Symbol.asyncIterator]||o.call&&o.set||o.subscribe||o.then))?void 0:i);var o,s,f,l,u,h,c;return r&&(f=t=>n.value=t,(s=i)&&(c=(s[Symbol.observable]?.()||s).subscribe?.(f,l,undefined),h=c&&(()=>c.unsubscribe?.())||s.set&&s.call?.(u,f)||(s.then?.((t=>{!u&&f(t)}),l)||(async t=>{try{for await(t of s){if(u)return;f(t)}}catch(t){}})())&&(t=>u=1),g.register(s,h))),Object.defineProperty(t,e,{get:()=>n.value,set:!S(i)&&j(i)?t=>t?Object.assign(n.value,t):n.value=A(t):t=>n.value=A(t),enumerable:!0,configurable:!1}),n}function j(t){return t&&t.constructor===Object}A.isStruct=x;var N=(t,e,i,r=null)=>{let n,o,s,f=0,l=i.length,a=e.length,{remove:u,same:h,insert:c,replace:v}=N;for(;f<l&&f<a&&h(e[f],i[f]);)f++;for(;f<l&&f<a&&h(i[l-1],e[a-1]);)r=i[(--a,--l)];if(f==a)for(;f<l;)c(r,i[f++],t);else{for(n=e[f];f<l;)s=i[f++],o=n?n.nextSibling:r,h(n,s)?n=o:f<l&&h(i[f],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,u(n,t),n=o}return i};N.same=(t,e)=>t==e,N.replace=(t,e,i)=>i.replaceChild(e,t),N.insert=(t,e,i)=>i.insertBefore(e,t),N.remove=(t,e)=>e.removeChild(t);var E=N,W={},k={},$={},P={},C=(t,e,i,r)=>{let n,o=r.startsWith("on")&&r.slice(2),s=R(t,e,":"+r);if(s)return o?e=>{n&&_(t,o,n),n=s(e),n&&D(t,o,n)}:e=>U(t,r,s(e))},U=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};P[""]=(t,e)=>{let i=R(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)U(t,I(e),r[e])}};var B=Symbol(":each"),L=Symbol(":ref");P.ref=(t,e,i)=>{t.hasAttribute(":each")?t[L]=e:i[e]=t},P.with=(t,e,i)=>{X(t,A(R(t,e,"with")(i),i))},P.if=(t,e)=>{let i=document.createTextNode(""),r=[R(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(R(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[B]||o).replaceWith(o=n[e]||i),X(o,t))}},P.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!i)return F(new Error,t,e);const r=t[B]=document.createTextNode("");t.replaceWith(r);const n=R(t,i.items,":each"),o=new WeakMap,s=new WeakMap;let f=[];return l=>{let a=n(l);a?"number"==typeof a?a=Array.from({length:a},((t,e)=>[e,e+1])):Array.isArray(a)?a=a.map(((t,e)=>[e+1,t])):"object"==typeof a?a=Object.entries(a):F(Error("Bad list value"),t,e,":each"):a=[];let u=[],h=[];for(let[e,r]of a){let n=null===(c=r)?k:void 0===c?$:"number"==typeof c||c instanceof Number?W[c]||(W[c]=new Number(c)):"string"==typeof c||c instanceof String?W[c]||(W[c]=new String(c)):"boolean"==typeof c||c instanceof Boolean?W[c]||(W[c]=new Boolean(c)):c,f=s.get(n);if(f||(f=t.cloneNode(!0),s.set(n,f)),u.push(f),!o.has(n)){let s=Object.create(l);s[i.item]=r,i.index&&(s[i.index]=e),t[L]&&(s[t[L]]=f),o.set(n,s)}h.push(o.get(n))}var c;E(r.parentNode,f,u,r),f=u;for(let t=0;t<u.length;t++)X(u[t],h[t])}},P.id=(t,e)=>{let i=R(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},P.class=(t,e)=>{let i=R(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},P.style=(t,e)=>{let i=R(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},P.text=(t,e)=>{let i=R(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},P.value=(t,e)=>{let i,r,n=R(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",U(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))};var T=Symbol("stop");P.on=(t,e)=>{let i=R(t,e,":on"),r={};return e=>{for(let e in r)_(t,e,r[e]);r=i(e);for(let e in r)D(t,e,r[e])}};var D=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=f=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,f))&&(e=()=>{}),++o<r.length?n(e,o):i[T]||n(i)};t.addEventListener(r[o],s)};n(i)}},_=(t,e,i)=>{e.indexOf("..")>=0&&(i[T]=!0),t.removeEventListener(e,i)};P.data=(t,e)=>{let i=R(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},P.aria=(t,e)=>{let i=R(t,e,":aria");return e=>(e=>{for(let i in e)U(t,"aria-"+I(i),null==e[i]?null:e[i]+"")})(i(e))};var M={};function R(t,e,i){if(M[e])return M[e];let r,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=new Function("__scope",`with (__scope) { return ${n} };`).bind(t)}catch(r){return F(r,t,e,i)}return M[e]=n=>{let o;try{o=r(n)}catch(r){return F(r,t,e,i)}return o}}function F(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function I(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var z=new WeakMap;function X(t,e){if(!t.children)return;if(z.has(t))return z.get(t);const i=A(e||{}),r=[],n=(t,e=t.parentNode)=>{if(t.attributes)for(let n=0;n<t.attributes.length;){let o=t.attributes[n];if(":"!==o.name[0]){n++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let f=o.name.slice(1).split(":");for(let n of f){let o=P[n]||C;if(r.push(o(t,s,i,n)||(()=>{})),z.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===n(e,t)&&i--};n(t);for(let t of r)m((()=>t(i)));return Object.seal(i),z.set(t,i),i}var Z=X;export{Z as default};
1
+ function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&f(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function a(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function f(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function u(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){a.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}a.prototype.h=function(){return!0},a.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},a.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},a.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},a.prototype.valueOf=function(){return this.value},a.prototype.toString=function(){return this.value+""},a.prototype.peek=function(){return this.v},Object.defineProperty(a.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new a).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!f(this))return this.f&=-2,!0;var t=i;try{u(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}a.prototype.S.call(this,t)},c.prototype.U=function(t){if(a.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),u(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[x],x=Symbol("signal-struct");function w(t,e){if(S(t)&&!e)return t;if(A(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),f=o[t]=(i=s)&&i.peek?s:new a(l?void 0:A(s)?Object.seal(w(s)):Array.isArray(s)?w(s):s);l&&g(s,(t=>f.value=t)),Object.defineProperty(n,t,{get:()=>f.value,set(t){if(A(t)){if(A(f.value))try{return void Object.assign(f.value,t)}catch(t){}f.value=Object.seal(w(t))}else Array.isArray(t)?f.value=w(t):f.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,x,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>w(t))):t}function A(t){return t&&t.constructor===Object}w.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,a=i.length,f=e.length,{remove:u,same:h,insert:c,replace:v}=O;for(;l<a&&l<f&&h(e[l],i[l]);)l++;for(;l<a&&l<f&&h(i[a-1],e[f-1]);)r=i[(--f,--a)];if(l==f)for(;l<a;)c(r,i[l++],t);else{for(n=e[l];l<a;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<a&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,u(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},W={},k={},$=(t,e,i,r)=>{let n,o=r.startsWith("on")&&r.slice(2),s=_(t,e,":"+r);if(s)return o?e=>{n&&T(t,o,n),n=s(e),n&&L(t,o,n)}:e=>P(t,r,s(e))},P=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")};k[""]=(t,e)=>{let i=_(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)P(t,R(e),r[e])}};var C=Symbol(":each"),U=Symbol(":ref");k.ref=(t,e,i)=>{t.hasAttribute(":each")?t[U]=e:i[e]=t},k.with=(t,e,i)=>{I(t,w(_(t,e,"with")(i),i))},k.if=(t,e)=>{let i=document.createTextNode(""),r=[_(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(_(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[C]||o).replaceWith(o=n[e]||i),I(o,t))}},k.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r={};r.items=i[2].trim();let n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?(r.item=n.replace(e,"").trim(),r.index=o[1].trim()):r.item=n,r}(e);if(!i)return M(new Error,t,e);const r=t[C]=document.createTextNode("");t.replaceWith(r);const n=_(t,i.items,":each"),o=new WeakMap,s=new WeakMap;let l=[];return a=>{let f=n(a);f?"number"==typeof f?f=Array.from({length:f},((t,e)=>[e,e+1])):Array.isArray(f)?f=f.map(((t,e)=>[e+1,t])):"object"==typeof f?f=Object.entries(f):M(Error("Bad list value"),t,e,":each"):f=[];let u=[],h=[];for(let[e,r]of f){let n=null===(c=r)?E:void 0===c?W:"number"==typeof c||c instanceof Number?N[c]||(N[c]=new Number(c)):"string"==typeof c||c instanceof String?N[c]||(N[c]=new String(c)):"boolean"==typeof c||c instanceof Boolean?N[c]||(N[c]=new Boolean(c)):c,l=s.get(n);if(l||(l=t.cloneNode(!0),s.set(n,l)),u.push(l),!o.has(n)){let s=Object.create(a);s[i.item]=r,i.index&&(s[i.index]=e),t[U]&&(s[t[U]]=l),o.set(n,s)}h.push(o.get(n))}var c;j(r.parentNode,l,u,r),l=u;for(let t=0;t<u.length;t++)I(u[t],h[t])}},k.id=(t,e)=>{let i=_(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},k.class=(t,e)=>{let i=_(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},k.style=(t,e)=>{let i=_(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},k.text=(t,e)=>{let i=_(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},k.value=(t,e)=>{let i,r,n=_(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",P(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))};var B=Symbol("stop");k.on=(t,e)=>{let i=_(t,e,":on"),r={};return e=>{for(let e in r)T(t,e,r[e]);r=i(e);for(let e in r)L(t,e,r[e])}};var L=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[B]||n(i)};t.addEventListener(r[o],s)};n(i)}},T=(t,e,i)=>{e.indexOf("..")>=0&&(i[B]=!0),t.removeEventListener(e,i)};k.data=(t,e)=>{let i=_(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},k.aria=(t,e)=>{let i=_(t,e,":aria");return e=>(e=>{for(let i in e)P(t,"aria-"+R(i),null==e[i]?null:e[i]+"")})(i(e))};var D={};function _(t,e,i){let r=D[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=D[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return M(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return M(r,t,e,i)}return o}}function M(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function R(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var F=new WeakMap;function I(t,e){if(!t.children)return;if(F.has(t))return F.get(t);const i=w(e||{}),r=[],n=(t,e=t.parentNode)=>{if(t.attributes)for(let n=0;n<t.attributes.length;){let o=t.attributes[n];if(":"!==o.name[0]){n++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let l=o.name.slice(1).split(":");for(let n of l){let o=k[n]||$;if(r.push(o(t,s,i,n)||(()=>{})),F.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===n(e,t)&&i--};n(t);for(let t of r)b((()=>t(i)));return Object.seal(i),F.set(t,i),i}var z=I;export{z as default};
package/src/directives.js CHANGED
@@ -11,7 +11,6 @@ export const directives = {}
11
11
  export default (el, expr, values, name) => {
12
12
  let evt = name.startsWith('on') && name.slice(2)
13
13
  let evaluate = parseExpr(el, expr, ':'+name)
14
-
15
14
  let value
16
15
  if (evaluate) return evt ? state => {
17
16
  value && removeListener(el, evt, value)
@@ -285,31 +284,32 @@ let evaluatorMemo = {}
285
284
  // borrowed from alpine: https://github.com/alpinejs/alpine/blob/main/packages/alpinejs/src/evaluator.js#L61
286
285
  // it seems to be more robust than subscript
287
286
  function parseExpr(el, expression, dir) {
288
- if (evaluatorMemo[expression]) return evaluatorMemo[expression]
289
-
290
- // Some expressions that are useful in Alpine are not valid as the right side of an expression.
291
- // Here we'll detect if the expression isn't valid for an assignement and wrap it in a self-
292
- // calling function so that we don't throw an error AND a "return" statement can b e used.
293
- let rightSideSafeExpression = 0
294
- // Support expressions starting with "if" statements like: "if (...) doSomething()"
295
- || /^[\n\s]*if.*\(.*\)/.test(expression)
296
- // Support expressions starting with "let/const" like: "let foo = 'bar'"
297
- || /^(let|const)\s/.test(expression)
298
- ? `(() => { ${expression} })()`
299
- : expression;
300
-
301
287
  // guard static-time eval errors
302
- let evaluate
303
- try {
304
- evaluate = new Function(`__scope`,`with (__scope) { return ${rightSideSafeExpression} };`).bind(el)
305
- } catch ( e ) {
306
- return exprError(e, el, expression, dir)
288
+ let evaluate = evaluatorMemo[expression]
289
+
290
+ if (!evaluate) {
291
+ // Some expressions that are useful in Alpine are not valid as the right side of an expression.
292
+ // Here we'll detect if the expression isn't valid for an assignement and wrap it in a self-
293
+ // calling function so that we don't throw an error AND a "return" statement can b e used.
294
+ let rightSideSafeExpression = 0
295
+ // Support expressions starting with "if" statements like: "if (...) doSomething()"
296
+ || /^[\n\s]*if.*\(.*\)/.test(expression)
297
+ // Support expressions starting with "let/const" like: "let foo = 'bar'"
298
+ || /^(let|const)\s/.test(expression)
299
+ ? `(() => { ${expression} })()`
300
+ : expression;
301
+
302
+ try {
303
+ evaluate = evaluatorMemo[expression] = new Function(`__scope`,`with (__scope) { return ${rightSideSafeExpression} };`)
304
+ } catch ( e ) {
305
+ return exprError(e, el, expression, dir)
306
+ }
307
307
  }
308
308
 
309
309
  // guard runtime eval errors
310
- return evaluatorMemo[expression] = (state) => {
310
+ return (state) => {
311
311
  let result
312
- try { result = evaluate(state) }
312
+ try { result = evaluate.call(el, state) }
313
313
  catch (e) { return exprError(e, el, expression, dir) }
314
314
  return result
315
315
  }
package/test/test.js CHANGED
@@ -81,12 +81,26 @@ test('props: base', async () => {
81
81
  is(el.outerHTML, `<input id="0" for="1" title="2" help="3" type="4" placeholder="5" value="7" a-b="8">`)
82
82
  })
83
83
 
84
+ test('props: sets prop', async () => {
85
+ let el = h`<x :x="this.x=1" :y="this.y='abc'"></x>`
86
+ sprae(el)
87
+ is(el.x, 1)
88
+ is(el.y, 'abc')
89
+ })
90
+
84
91
  test('props: multiprop', async () => {
85
92
  let el = h`<input :id:name:for="0" />`
86
93
  let params = sprae(el)
87
94
  is(el.outerHTML, `<input id="0" name="0" for="0">`)
88
95
  })
89
96
 
97
+ // FIXME: this must work without return
98
+ test.todo('props: calculation', async () => {
99
+ let el = h`<x :x="let a = 5; return Array.from({length:a}, (_,i)=>i).join(' ')"></x>`
100
+ sprae(el);
101
+ is(el.outerHTML, `<x x="01234"></x>`)
102
+ })
103
+
90
104
  test('data: base', async () => {
91
105
  let el = h`<input :data="{a:1, fooBar:2}"/>`
92
106
  let params = sprae(el)
@@ -352,6 +366,14 @@ test('each: condition within loop', async () => {
352
366
  is(el.innerHTML, '')
353
367
  })
354
368
 
369
+ test('each: next items have own "this", not single one', async () => {
370
+ // FIXME: let el = h`<x :each="x in 3"></x>`
371
+ let el = h`<div><x :each="x in 3" :data="{x}" :x="log.push(x, this.dataset.x)"></x></div>`
372
+ let log = []
373
+ let state = sprae(el, {log})
374
+ is(state.log, [1,'1',2,'2',3,'3'])
375
+ })
376
+
355
377
  test('on: base', () => {
356
378
  let el = h`<div :on="{click(e){log.push('click')},x}"></div>`
357
379
  let log = signal([])