From b8c5501338cc5fc250426e87b8b9ba7aeafc4085 Mon Sep 17 00:00:00 2001 From: X-Ryl669 Date: Mon, 2 Sep 2024 10:04:53 +0200 Subject: [PATCH] Reduce the vanjs file size even more (by 32 bytes, minimized). --- package.json | 2 +- public/van-1.5.2.debug.js | 2 +- public/van-latest.debug.js | 2 +- public/van-latest.js | 36 +++++++------- public/van-latest.min.js | 2 +- public/van-latest.nomodule.debug.js | 73 +++++++++++++++-------------- public/van-latest.nomodule.js | 55 ++++++++++++---------- public/van-latest.nomodule.min.js | 2 +- public/van.version | 2 +- src/van.js | 36 +++++++------- 10 files changed, 111 insertions(+), 101 deletions(-) diff --git a/package.json b/package.json index 3b9e089f..3e24bc04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vanjs-core", - "version": "1.5.2", + "version": "1.5.3", "description": "VanJS. A minimalist React-like UI library based on vanilla JavaScript and DOM.", "files": [ "src/van.js", diff --git a/public/van-1.5.2.debug.js b/public/van-1.5.2.debug.js index 45a2ec51..e6ddf5ec 100644 --- a/public/van-1.5.2.debug.js +++ b/public/van-1.5.2.debug.js @@ -1,4 +1,4 @@ -import van from "./van-1.5.2.js" +import van from "./van.js" // If this variable is set to an Array, we will push the error message into the array instead of // throwing an error. This is useful in testing, to capture the error occurred asynchronous to the initiating diff --git a/public/van-latest.debug.js b/public/van-latest.debug.js index 74b2ecda..e6ddf5ec 100644 --- a/public/van-latest.debug.js +++ b/public/van-latest.debug.js @@ -1,4 +1,4 @@ -import van from "./van-latest.js" +import van from "./van.js" // If this variable is set to an Array, we will push the error message into the array instead of // throwing an error. This is useful in testing, to capture the error occurred asynchronous to the initiating diff --git a/public/van-latest.js b/public/van-latest.js index 568ec787..0f0715fb 100644 --- a/public/van-latest.js +++ b/public/van-latest.js @@ -1,13 +1,13 @@ // This file consistently uses `let` keyword instead of `const` for reducing the bundle size. // Global variables - aliasing some builtin symbols to reduce the bundle size. -let protoOf = Object.getPrototypeOf +let object = Object, protoOf = object.getPrototypeOf let changedStates, derivedStates, curDeps, curNewDerives, alwaysConnectedDom = {isConnected: 1} let gcCycleInMs = 1000, statesToGc, propSetterCache = {} -let objProto = protoOf(alwaysConnectedDom), funcProto = protoOf(protoOf), _undefined +let objProto = protoOf(alwaysConnectedDom), funcProto = protoOf(protoOf), _undefined, remove = 'remove', evl = 'eventListener', st = Set, dc=document let addAndScheduleOnFirst = (set, s, f, waitMs) => - (set ?? (setTimeout(f, waitMs), new Set)).add(s) + (set ?? (setTimeout(f, waitMs), new st)).add(s) let runAndCaptureDeps = (f, deps, arg) => { let prevDeps = curDeps @@ -62,10 +62,10 @@ let state = initVal => ({ }) let bind = (f, dom) => { - let deps = {_getters: new Set, _setters: new Set}, binding = {f}, prevNewDerives = curNewDerives + let deps = {_getters: new st, _setters: new st}, binding = {f}, prevNewDerives = curNewDerives curNewDerives = [] let newDom = runAndCaptureDeps(f, deps, dom) - newDom = (newDom ?? document).nodeType ? newDom : new Text(newDom) + newDom = (newDom ?? dc).nodeType ? newDom : new Text(newDom) for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._bindings.push(binding)) for (let l of curNewDerives) l._dom = newDom @@ -74,7 +74,7 @@ let bind = (f, dom) => { } let derive = (f, s = state(), dom) => { - let deps = {_getters: new Set, _setters: new Set}, listener = {f, s} + let deps = {_getters: new st, _setters: new st}, listener = {f, s} listener._dom = dom ?? curNewDerives?.push(listener) ?? alwaysConnectedDom s.val = runAndCaptureDeps(f, deps, s.rawVal) for (let d of deps._getters) @@ -83,7 +83,7 @@ let derive = (f, s = state(), dom) => { } let add = (dom, ...children) => { - for (let c of children.flat(Infinity)) { + for (let c of children.flat(1/0)) { let protoOfC = protoOf(c ?? 0) let child = protoOfC === stateProto ? bind(() => c.val) : protoOfC === funcProto ? bind(c) : c @@ -94,22 +94,22 @@ let add = (dom, ...children) => { let tag = (ns, name, ...args) => { let [props, ...children] = protoOf(args[0] ?? 0) === objProto ? args : [{}, ...args] - let dom = ns ? document.createElementNS(ns, name) : document.createElement(name) - for (let [k, v] of Object.entries(props)) { + let n = ns&&'NS', doc = dc['createElement'+n](ns||name,name) + for (let [k, v] of object.entries(props)) { let getPropDescriptor = proto => proto ? - Object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : + object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined let cacheKey = name + "," + k let propSetter = propSetterCache[cacheKey] ??= getPropDescriptor(protoOf(dom))?.set ?? 0 - let setter = k.startsWith("on") ? + let on = k.startsWith("on"), setter = on ? (v, oldV) => { let event = k.slice(2) - dom.removeEventListener(event, oldV) - dom.addEventListener(event, v) + dom[remove+evl](event, oldV) + dom['add'+evl](event, v) } : propSetter ? propSetter.bind(dom) : dom.setAttribute.bind(dom, k) let protoOfV = protoOf(v ?? 0) - k.startsWith("on") || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto) + on || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto) protoOfV === stateProto ? bind(() => (setter(v.val, v._oldVal), dom)) : setter(v) } return add(dom, children) @@ -117,18 +117,18 @@ let tag = (ns, name, ...args) => { let handler = ns => ({get: (_, name) => tag.bind(_undefined, ns, name)}) -let update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove() +let update = (dom, newDom) => newDom === dom || dom[newDom?'replaceWith':remove](newDom) let updateDoms = () => { let iter = 0, derivedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) do { - derivedStates = new Set - for (let l of new Set(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) + derivedStates = new st + for (let l of new st(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) derive(l.f, l.s, l._dom), l._dom = _undefined } while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length) let changedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) changedStates = _undefined - for (let b of new Set(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) + for (let b of new st(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) update(b._dom, bind(b.f, b._dom)), b._dom = _undefined for (let s of changedStatesArray) s._oldVal = s.rawVal } diff --git a/public/van-latest.min.js b/public/van-latest.min.js index 9780bbf3..c465047e 100644 --- a/public/van-latest.min.js +++ b/public/van-latest.min.js @@ -1 +1 @@ -let e,t,r,o,l,n,s=Object.getPrototypeOf,f={isConnected:1},i={},h=s(f),a=s(s),d=(e,t,r,o)=>(e??(setTimeout(r,o),new Set)).add(t),u=(e,t,o)=>{let l=r;r=t;try{return e(o)}catch(e){return console.error(e),o}finally{r=l}},w=e=>e.filter(e=>e.t?.isConnected),_=e=>l=d(l,e,()=>{for(let e of l)e.o=w(e.o),e.l=w(e.l);l=n},1e3),c={get val(){return r?.i?.add(this),this.rawVal},get oldVal(){return r?.i?.add(this),this.h},set val(o){r?.u?.add(this),o!==this.rawVal&&(this.rawVal=o,this.o.length+this.l.length?(t?.add(this),e=d(e,this,v)):this.h=o)}},S=e=>({__proto__:c,rawVal:e,h:e,o:[],l:[]}),g=(e,t)=>{let r={i:new Set,u:new Set},l={f:e},n=o;o=[];let s=u(e,r,t);s=(s??document).nodeType?s:new Text(s);for(let e of r.i)r.u.has(e)||(_(e),e.o.push(l));for(let e of o)e.t=s;return o=n,l.t=s},y=(e,t=S(),r)=>{let l={i:new Set,u:new Set},n={f:e,s:t};n.t=r??o?.push(n)??f,t.val=u(e,l,t.rawVal);for(let e of l.i)l.u.has(e)||(_(e),e.l.push(n));return t},b=(e,...t)=>{for(let r of t.flat(1/0)){let t=s(r??0),o=t===c?g(()=>r.val):t===a?g(r):r;o!=n&&e.append(o)}return e},m=(e,t,...r)=>{let[o,...l]=s(r[0]??0)===h?r:[{},...r],f=e?document.createElementNS(e,t):document.createElement(t);for(let[e,r]of Object.entries(o)){let o=t=>t?Object.getOwnPropertyDescriptor(t,e)??o(s(t)):n,l=t+","+e,h=i[l]??=o(s(f))?.set??0,d=e.startsWith("on")?(t,r)=>{let o=e.slice(2);f.removeEventListener(o,r),f.addEventListener(o,t)}:h?h.bind(f):f.setAttribute.bind(f,e),u=s(r??0);e.startsWith("on")||u===a&&(r=y(r),u=c),u===c?g(()=>(d(r.val,r.h),f)):d(r)}return b(f,l)},x=e=>({get:(t,r)=>m.bind(n,e,r)}),j=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),v=()=>{let r=0,o=[...e].filter(e=>e.rawVal!==e.h);do{t=new Set;for(let e of new Set(o.flatMap(e=>e.l=w(e.l))))y(e.f,e.s,e.t),e.t=n}while(++r<100&&(o=[...t]).length);let l=[...e].filter(e=>e.rawVal!==e.h);e=n;for(let e of new Set(l.flatMap(e=>e.o=w(e.o))))j(e.t,g(e.f,e.t)),e.t=n;for(let e of l)e.h=e.rawVal};export default{tags:new Proxy(e=>new Proxy(m,x(e)),x()),hydrate:(e,t)=>j(e,g(t,e)),add:b,state:S,derive:y}; \ No newline at end of file +let e,t,o,r,l,n,s=Object,f=s.getPrototypeOf,d={isConnected:1},i={},a=f(d),h=f(f),w="remove",m="eventListener",u=Set,_=document,c=(e,t,o,r)=>(e??(setTimeout(o,r),new u)).add(t),g=(e,t,r)=>{let l=o;o=t;try{return e(r)}catch(e){return console.error(e),r}finally{o=l}},v=e=>e.filter(e=>e.t?.isConnected),y=e=>l=c(l,e,()=>{for(let e of l)e.o=v(e.o),e.l=v(e.l);l=n},1e3),x={get val(){return o?.i?.add(this),this.rawVal},get oldVal(){return o?.i?.add(this),this.h},set val(r){o?.m?.add(this),r!==this.rawVal&&(this.rawVal=r,this.o.length+this.l.length?(t?.add(this),e=c(e,this,C)):this.h=r)}},V=e=>({__proto__:x,rawVal:e,h:e,o:[],l:[]}),b=(e,t)=>{let o={i:new u,m:new u},l={f:e},n=r;r=[];let s=g(e,o,t);s=(s??_).nodeType?s:new Text(s);for(let e of o.i)o.m.has(e)||(y(e),e.o.push(l));for(let e of r)e.t=s;return r=n,l.t=s},p=(e,t=V(),o)=>{let l={i:new u,m:new u},n={f:e,s:t};n.t=o??r?.push(n)??d,t.val=g(e,l,t.rawVal);for(let e of l.i)l.m.has(e)||(y(e),e.l.push(n));return t},P=(e,...t)=>{for(let o of t.flat(1/0)){let t=f(o??0),r=t===x?b(()=>o.val):t===h?b(o):o;r!=n&&e.append(r)}return e},S=(e,t,...o)=>{let[r,...l]=f(o[0]??0)===a?o:[{},...o];_["createElement"+(e&&"NS")](e||t,t);for(let[e,o]of s.entries(r)){let r=t=>t?s.getOwnPropertyDescriptor(t,e)??r(f(t)):n,l=t+","+e,d=i[l]??=r(f(dom))?.set??0,a=e.startsWith("on"),u=a?(t,o)=>{let r=e.slice(2);dom[w+m](r,o),dom["add"+m](r,t)}:d?d.bind(dom):dom.setAttribute.bind(dom,e),_=f(o??0);a||_===h&&(o=p(o),_=x),_===x?b(()=>(u(o.val,o.h),dom)):u(o)}return P(dom,l)},T=e=>({get:(t,o)=>S.bind(n,e,o)}),j=(e,t)=>t===e||e[t?"replaceWith":w](t),C=()=>{let o=0,r=[...e].filter(e=>e.rawVal!==e.h);do{t=new u;for(let e of new u(r.flatMap(e=>e.l=v(e.l))))p(e.f,e.s,e.t),e.t=n}while(++o<100&&(r=[...t]).length);let l=[...e].filter(e=>e.rawVal!==e.h);e=n;for(let e of new u(l.flatMap(e=>e.o=v(e.o))))j(e.t,b(e.f,e.t)),e.t=n;for(let e of l)e.h=e.rawVal};export default{tags:new Proxy(e=>new Proxy(S,T(e)),T()),hydrate:(e,t)=>j(e,b(t,e)),add:P,state:V,derive:p}; \ No newline at end of file diff --git a/public/van-latest.nomodule.debug.js b/public/van-latest.nomodule.debug.js index 701b0225..92020c96 100644 --- a/public/van-latest.nomodule.debug.js +++ b/public/van-latest.nomodule.debug.js @@ -1,6 +1,7 @@ (() => { // van.js - var protoOf = Object.getPrototypeOf; + var object = Object; + var protoOf = object.getPrototypeOf; var changedStates; var derivedStates; var curDeps; @@ -12,7 +13,11 @@ var objProto = protoOf(alwaysConnectedDom); var funcProto = protoOf(protoOf); var _undefined; - var addAndScheduleOnFirst = (set, s, f, waitMs) => (set ?? (setTimeout(f, waitMs), /* @__PURE__ */ new Set())).add(s); + var remove = "remove"; + var evl = "eventListener"; + var st = Set; + var dc = document; + var addAndScheduleOnFirst = (set, s, f, waitMs) => (set ?? (setTimeout(f, waitMs), new st())).add(s); var runAndCaptureDeps = (f, deps, arg) => { let prevDeps = curDeps; curDeps = deps; @@ -55,11 +60,11 @@ _bindings: [], _listeners: [] }); - var bind = (f, dom) => { - let deps = { _getters: /* @__PURE__ */ new Set(), _setters: /* @__PURE__ */ new Set() }, binding = { f }, prevNewDerives = curNewDerives; + var bind = (f, dom2) => { + let deps = { _getters: new st(), _setters: new st() }, binding = { f }, prevNewDerives = curNewDerives; curNewDerives = []; - let newDom = runAndCaptureDeps(f, deps, dom); - newDom = (newDom ?? document).nodeType ? newDom : new Text(newDom); + let newDom = runAndCaptureDeps(f, deps, dom2); + newDom = (newDom ?? dc).nodeType ? newDom : new Text(newDom); for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._bindings.push(binding)); for (let l of curNewDerives) @@ -67,59 +72,59 @@ curNewDerives = prevNewDerives; return binding._dom = newDom; }; - var derive = (f, s = state(), dom) => { - let deps = { _getters: /* @__PURE__ */ new Set(), _setters: /* @__PURE__ */ new Set() }, listener = { f, s }; - listener._dom = dom ?? curNewDerives?.push(listener) ?? alwaysConnectedDom; + var derive = (f, s = state(), dom2) => { + let deps = { _getters: new st(), _setters: new st() }, listener = { f, s }; + listener._dom = dom2 ?? curNewDerives?.push(listener) ?? alwaysConnectedDom; s.val = runAndCaptureDeps(f, deps, s.rawVal); for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._listeners.push(listener)); return s; }; - var add = (dom, ...children) => { - for (let c of children.flat(Infinity)) { + var add = (dom2, ...children) => { + for (let c of children.flat(1 / 0)) { let protoOfC = protoOf(c ?? 0); let child = protoOfC === stateProto ? bind(() => c.val) : protoOfC === funcProto ? bind(c) : c; - child != _undefined && dom.append(child); + child != _undefined && dom2.append(child); } - return dom; + return dom2; }; var tag = (ns, name, ...args) => { let [props, ...children] = protoOf(args[0] ?? 0) === objProto ? args : [{}, ...args]; - let dom = ns ? document.createElementNS(ns, name) : document.createElement(name); - for (let [k, v] of Object.entries(props)) { - let getPropDescriptor = (proto) => proto ? Object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined; + let n = ns && "NS", doc = dc["createElement" + n](ns || name, name); + for (let [k, v] of object.entries(props)) { + let getPropDescriptor = (proto) => proto ? object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined; let cacheKey = name + "," + k; let propSetter = propSetterCache[cacheKey] ??= getPropDescriptor(protoOf(dom))?.set ?? 0; - let setter = k.startsWith("on") ? (v2, oldV) => { + let on = k.startsWith("on"), setter = on ? (v2, oldV) => { let event = k.slice(2); - dom.removeEventListener(event, oldV); - dom.addEventListener(event, v2); + dom[remove + evl](event, oldV); + dom["add" + evl](event, v2); } : propSetter ? propSetter.bind(dom) : dom.setAttribute.bind(dom, k); let protoOfV = protoOf(v ?? 0); - k.startsWith("on") || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto); + on || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto); protoOfV === stateProto ? bind(() => (setter(v.val, v._oldVal), dom)) : setter(v); } return add(dom, children); }; var handler = (ns) => ({ get: (_, name) => tag.bind(_undefined, ns, name) }); - var update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove(); + var update = (dom2, newDom) => newDom === dom2 || dom2[newDom ? "replaceWith" : remove](newDom); var updateDoms = () => { let iter = 0, derivedStatesArray = [...changedStates].filter((s) => s.rawVal !== s._oldVal); do { - derivedStates = /* @__PURE__ */ new Set(); - for (let l of new Set(derivedStatesArray.flatMap((s) => s._listeners = keepConnected(s._listeners)))) + derivedStates = new st(); + for (let l of new st(derivedStatesArray.flatMap((s) => s._listeners = keepConnected(s._listeners)))) derive(l.f, l.s, l._dom), l._dom = _undefined; } while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length); let changedStatesArray = [...changedStates].filter((s) => s.rawVal !== s._oldVal); changedStates = _undefined; - for (let b of new Set(changedStatesArray.flatMap((s) => s._bindings = keepConnected(s._bindings)))) + for (let b of new st(changedStatesArray.flatMap((s) => s._bindings = keepConnected(s._bindings)))) update(b._dom, bind(b.f, b._dom)), b._dom = _undefined; for (let s of changedStatesArray) s._oldVal = s.rawVal; }; var van_default = { tags: new Proxy((ns) => new Proxy(tag, handler(ns)), handler()), - hydrate: (dom, f) => update(dom, bind(f, dom)), + hydrate: (dom2, f) => update(dom2, bind(f, dom2)), add, state, derive @@ -169,9 +174,9 @@ ); return child; }; - var withResultValidation = (f) => (dom) => { - const r = validateChild(f(dom)); - if (r !== dom && r instanceof Node) + var withResultValidation = (f) => (dom2) => { + const r = validateChild(f(dom2)); + if (r !== dom2 && r instanceof Node) expect( !r.isConnected, "If the result of complex binding function is not the same as previous one, it shouldn't be already connected to document" @@ -186,9 +191,9 @@ expect(!c?.isConnected, "You can't add a DOM Node that is already connected to document"); return validateChild(c); }); - var add2 = (dom, ...children) => { - expect(dom instanceof Element, "1st argument of `van.add` function must be a DOM Element object"); - return van_default.add(dom, ...checkChildren(children)); + var add2 = (dom2, ...children) => { + expect(dom2 instanceof Element, "1st argument of `van.add` function must be a DOM Element object"); + return van_default.add(dom2, ...checkChildren(children)); }; var debugHandler = { get: (vanTags, name) => { @@ -225,10 +230,10 @@ }; var _tags = _tagsNS(""); var tags = new Proxy(tagsNS, { get: (_, name) => _tags[name] }); - var hydrate = (dom, f) => { - expect(dom instanceof Node, "1st argument of `van.hydrate` function must be a DOM Node object"); + var hydrate = (dom2, f) => { + expect(dom2 instanceof Node, "1st argument of `van.hydrate` function must be a DOM Node object"); expect(typeof f === "function", "2nd argument of `van.hydrate` function must be a function"); - return van_default.hydrate(dom, withResultValidation(f)); + return van_default.hydrate(dom2, withResultValidation(f)); }; var van_debug_default = { add: add2, tags, state: state2, derive: derive2, hydrate, startCapturingErrors, stopCapturingErrors, get capturedErrors() { return capturedErrors; diff --git a/public/van-latest.nomodule.js b/public/van-latest.nomodule.js index 64b8ceeb..13320b30 100644 --- a/public/van-latest.nomodule.js +++ b/public/van-latest.nomodule.js @@ -1,6 +1,7 @@ (() => { // van.js - var protoOf = Object.getPrototypeOf; + var object = Object; + var protoOf = object.getPrototypeOf; var changedStates; var derivedStates; var curDeps; @@ -12,7 +13,11 @@ var objProto = protoOf(alwaysConnectedDom); var funcProto = protoOf(protoOf); var _undefined; - var addAndScheduleOnFirst = (set, s, f, waitMs) => (set ?? (setTimeout(f, waitMs), /* @__PURE__ */ new Set())).add(s); + var remove = "remove"; + var evl = "eventListener"; + var st = Set; + var dc = document; + var addAndScheduleOnFirst = (set, s, f, waitMs) => (set ?? (setTimeout(f, waitMs), new st())).add(s); var runAndCaptureDeps = (f, deps, arg) => { let prevDeps = curDeps; curDeps = deps; @@ -55,11 +60,11 @@ _bindings: [], _listeners: [] }); - var bind = (f, dom) => { - let deps = { _getters: /* @__PURE__ */ new Set(), _setters: /* @__PURE__ */ new Set() }, binding = { f }, prevNewDerives = curNewDerives; + var bind = (f, dom2) => { + let deps = { _getters: new st(), _setters: new st() }, binding = { f }, prevNewDerives = curNewDerives; curNewDerives = []; - let newDom = runAndCaptureDeps(f, deps, dom); - newDom = (newDom ?? document).nodeType ? newDom : new Text(newDom); + let newDom = runAndCaptureDeps(f, deps, dom2); + newDom = (newDom ?? dc).nodeType ? newDom : new Text(newDom); for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._bindings.push(binding)); for (let l of curNewDerives) @@ -67,59 +72,59 @@ curNewDerives = prevNewDerives; return binding._dom = newDom; }; - var derive = (f, s = state(), dom) => { - let deps = { _getters: /* @__PURE__ */ new Set(), _setters: /* @__PURE__ */ new Set() }, listener = { f, s }; - listener._dom = dom ?? curNewDerives?.push(listener) ?? alwaysConnectedDom; + var derive = (f, s = state(), dom2) => { + let deps = { _getters: new st(), _setters: new st() }, listener = { f, s }; + listener._dom = dom2 ?? curNewDerives?.push(listener) ?? alwaysConnectedDom; s.val = runAndCaptureDeps(f, deps, s.rawVal); for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._listeners.push(listener)); return s; }; - var add = (dom, ...children) => { - for (let c of children.flat(Infinity)) { + var add = (dom2, ...children) => { + for (let c of children.flat(1 / 0)) { let protoOfC = protoOf(c ?? 0); let child = protoOfC === stateProto ? bind(() => c.val) : protoOfC === funcProto ? bind(c) : c; - child != _undefined && dom.append(child); + child != _undefined && dom2.append(child); } - return dom; + return dom2; }; var tag = (ns, name, ...args) => { let [props, ...children] = protoOf(args[0] ?? 0) === objProto ? args : [{}, ...args]; - let dom = ns ? document.createElementNS(ns, name) : document.createElement(name); - for (let [k, v] of Object.entries(props)) { - let getPropDescriptor = (proto) => proto ? Object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined; + let n = ns && "NS", doc = dc["createElement" + n](ns || name, name); + for (let [k, v] of object.entries(props)) { + let getPropDescriptor = (proto) => proto ? object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined; let cacheKey = name + "," + k; let propSetter = propSetterCache[cacheKey] ??= getPropDescriptor(protoOf(dom))?.set ?? 0; - let setter = k.startsWith("on") ? (v2, oldV) => { + let on = k.startsWith("on"), setter = on ? (v2, oldV) => { let event = k.slice(2); - dom.removeEventListener(event, oldV); - dom.addEventListener(event, v2); + dom[remove + evl](event, oldV); + dom["add" + evl](event, v2); } : propSetter ? propSetter.bind(dom) : dom.setAttribute.bind(dom, k); let protoOfV = protoOf(v ?? 0); - k.startsWith("on") || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto); + on || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto); protoOfV === stateProto ? bind(() => (setter(v.val, v._oldVal), dom)) : setter(v); } return add(dom, children); }; var handler = (ns) => ({ get: (_, name) => tag.bind(_undefined, ns, name) }); - var update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove(); + var update = (dom2, newDom) => newDom === dom2 || dom2[newDom ? "replaceWith" : remove](newDom); var updateDoms = () => { let iter = 0, derivedStatesArray = [...changedStates].filter((s) => s.rawVal !== s._oldVal); do { - derivedStates = /* @__PURE__ */ new Set(); - for (let l of new Set(derivedStatesArray.flatMap((s) => s._listeners = keepConnected(s._listeners)))) + derivedStates = new st(); + for (let l of new st(derivedStatesArray.flatMap((s) => s._listeners = keepConnected(s._listeners)))) derive(l.f, l.s, l._dom), l._dom = _undefined; } while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length); let changedStatesArray = [...changedStates].filter((s) => s.rawVal !== s._oldVal); changedStates = _undefined; - for (let b of new Set(changedStatesArray.flatMap((s) => s._bindings = keepConnected(s._bindings)))) + for (let b of new st(changedStatesArray.flatMap((s) => s._bindings = keepConnected(s._bindings)))) update(b._dom, bind(b.f, b._dom)), b._dom = _undefined; for (let s of changedStatesArray) s._oldVal = s.rawVal; }; var van_default = { tags: new Proxy((ns) => new Proxy(tag, handler(ns)), handler()), - hydrate: (dom, f) => update(dom, bind(f, dom)), + hydrate: (dom2, f) => update(dom2, bind(f, dom2)), add, state, derive diff --git a/public/van-latest.nomodule.min.js b/public/van-latest.nomodule.min.js index 3352f11c..649f5e36 100644 --- a/public/van-latest.nomodule.min.js +++ b/public/van-latest.nomodule.min.js @@ -1 +1 @@ -{let e,t,r,o,n,l,s,f,i,h,w,a,d,u,_,c,S,g,y,b,m,v,j,x,O;s=Object.getPrototypeOf,i={},h=s(f={isConnected:1}),w=s(s),a=(e,t,r,o)=>(e??(setTimeout(r,o),new Set)).add(t),d=(e,t,o)=>{let n=r;r=t;try{return e(o)}catch(e){return console.error(e),o}finally{r=n}},u=e=>e.filter(e=>e.t?.isConnected),_=e=>n=a(n,e,()=>{for(let e of n)e.o=u(e.o),e.l=u(e.l);n=l},1e3),c={get val(){return r?.i?.add(this),this.rawVal},get oldVal(){return r?.i?.add(this),this.h},set val(o){r?.u?.add(this),o!==this.rawVal&&(this.rawVal=o,this.o.length+this.l.length?(t?.add(this),e=a(e,this,x)):this.h=o)}},S=e=>({__proto__:c,rawVal:e,h:e,o:[],l:[]}),g=(e,t)=>{let r={i:new Set,u:new Set},n={f:e},l=o;o=[];let s=d(e,r,t);s=(s??document).nodeType?s:new Text(s);for(let e of r.i)r.u.has(e)||(_(e),e.o.push(n));for(let e of o)e.t=s;return o=l,n.t=s},y=(e,t=S(),r)=>{let n={i:new Set,u:new Set},l={f:e,s:t};l.t=r??o?.push(l)??f,t.val=d(e,n,t.rawVal);for(let e of n.i)n.u.has(e)||(_(e),e.l.push(l));return t},b=(e,...t)=>{for(let r of t.flat(1/0)){let t=s(r??0),o=t===c?g(()=>r.val):t===w?g(r):r;o!=l&&e.append(o)}return e},m=(e,t,...r)=>{let[o,...n]=s(r[0]??0)===h?r:[{},...r],f=e?document.createElementNS(e,t):document.createElement(t);for(let[e,r]of Object.entries(o)){let o=t=>t?Object.getOwnPropertyDescriptor(t,e)??o(s(t)):l,n=t+","+e,h=i[n]??=o(s(f))?.set??0,a=e.startsWith("on")?(t,r)=>{let o=e.slice(2);f.removeEventListener(o,r),f.addEventListener(o,t)}:h?h.bind(f):f.setAttribute.bind(f,e),d=s(r??0);e.startsWith("on")||d===w&&(r=y(r),d=c),d===c?g(()=>(a(r.val,r.h),f)):a(r)}return b(f,n)},v=e=>({get:(t,r)=>m.bind(l,e,r)}),j=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),x=()=>{let r=0,o=[...e].filter(e=>e.rawVal!==e.h);do{t=new Set;for(let e of new Set(o.flatMap(e=>e.l=u(e.l))))y(e.f,e.s,e.t),e.t=l}while(++r<100&&(o=[...t]).length);let n=[...e].filter(e=>e.rawVal!==e.h);e=l;for(let e of new Set(n.flatMap(e=>e.o=u(e.o))))j(e.t,g(e.f,e.t)),e.t=l;for(let e of n)e.h=e.rawVal},O={tags:new Proxy(e=>new Proxy(m,v(e)),v()),hydrate:(e,t)=>j(e,g(t,e)),add:b,state:S,derive:y},window.van=O;} \ No newline at end of file +{let e,t,o,r,l,n,s,i,d,f,a,h,w,m,_,u,c,g,v,y,x,V,b,P,S,T,j,p,C,E;i=(s=Object).getPrototypeOf,f={},a=i(d={isConnected:1}),h=i(i),w="remove",m="eventListener",_=Set,u=document,c=(e,t,o,r)=>(e??(setTimeout(o,r),new _)).add(t),g=(e,t,r)=>{let l=o;o=t;try{return e(r)}catch(e){return console.error(e),r}finally{o=l}},v=e=>e.filter(e=>e.t?.isConnected),y=e=>l=c(l,e,()=>{for(let e of l)e.o=v(e.o),e.l=v(e.l);l=n},1e3),x={get val(){return o?.i?.add(this),this.rawVal},get oldVal(){return o?.i?.add(this),this.h},set val(r){o?.m?.add(this),r!==this.rawVal&&(this.rawVal=r,this.o.length+this.l.length?(t?.add(this),e=c(e,this,C)):this.h=r)}},V=e=>({__proto__:x,rawVal:e,h:e,o:[],l:[]}),b=(e,t)=>{let o={i:new _,m:new _},l={f:e},n=r;r=[];let s=g(e,o,t);s=(s??u).nodeType?s:new Text(s);for(let e of o.i)o.m.has(e)||(y(e),e.o.push(l));for(let e of r)e.t=s;return r=n,l.t=s},P=(e,t=V(),o)=>{let l={i:new _,m:new _},n={f:e,s:t};n.t=o??r?.push(n)??d,t.val=g(e,l,t.rawVal);for(let e of l.i)l.m.has(e)||(y(e),e.l.push(n));return t},S=(e,...t)=>{for(let o of t.flat(1/0)){let t=i(o??0),r=t===x?b(()=>o.val):t===h?b(o):o;r!=n&&e.append(r)}return e},T=(e,t,...o)=>{let[r,...l]=i(o[0]??0)===a?o:[{},...o];u["createElement"+(e&&"NS")](e||t,t);for(let[e,o]of s.entries(r)){let r=t=>t?s.getOwnPropertyDescriptor(t,e)??r(i(t)):n,l=t+","+e,d=f[l]??=r(i(dom))?.set??0,a=e.startsWith("on"),_=a?(t,o)=>{let r=e.slice(2);dom[w+m](r,o),dom["add"+m](r,t)}:d?d.bind(dom):dom.setAttribute.bind(dom,e),u=i(o??0);a||u===h&&(o=P(o),u=x),u===x?b(()=>(_(o.val,o.h),dom)):_(o)}return S(dom,l)},j=e=>({get:(t,o)=>T.bind(n,e,o)}),p=(e,t)=>t===e||e[t?"replaceWith":w](t),C=()=>{let o=0,r=[...e].filter(e=>e.rawVal!==e.h);do{t=new _;for(let e of new _(r.flatMap(e=>e.l=v(e.l))))P(e.f,e.s,e.t),e.t=n}while(++o<100&&(r=[...t]).length);let l=[...e].filter(e=>e.rawVal!==e.h);e=n;for(let e of new _(l.flatMap(e=>e.o=v(e.o))))p(e.t,b(e.f,e.t)),e.t=n;for(let e of l)e.h=e.rawVal},E={tags:new Proxy(e=>new Proxy(T,j(e)),j()),hydrate:(e,t)=>p(e,b(t,e)),add:S,state:V,derive:P},window.van=E;} \ No newline at end of file diff --git a/public/van.version b/public/van.version index a73b4325..1d5e9e0b 100644 --- a/public/van.version +++ b/public/van.version @@ -1 +1 @@ -1.5.2 \ No newline at end of file +1.5.3 \ No newline at end of file diff --git a/src/van.js b/src/van.js index 568ec787..0f0715fb 100644 --- a/src/van.js +++ b/src/van.js @@ -1,13 +1,13 @@ // This file consistently uses `let` keyword instead of `const` for reducing the bundle size. // Global variables - aliasing some builtin symbols to reduce the bundle size. -let protoOf = Object.getPrototypeOf +let object = Object, protoOf = object.getPrototypeOf let changedStates, derivedStates, curDeps, curNewDerives, alwaysConnectedDom = {isConnected: 1} let gcCycleInMs = 1000, statesToGc, propSetterCache = {} -let objProto = protoOf(alwaysConnectedDom), funcProto = protoOf(protoOf), _undefined +let objProto = protoOf(alwaysConnectedDom), funcProto = protoOf(protoOf), _undefined, remove = 'remove', evl = 'eventListener', st = Set, dc=document let addAndScheduleOnFirst = (set, s, f, waitMs) => - (set ?? (setTimeout(f, waitMs), new Set)).add(s) + (set ?? (setTimeout(f, waitMs), new st)).add(s) let runAndCaptureDeps = (f, deps, arg) => { let prevDeps = curDeps @@ -62,10 +62,10 @@ let state = initVal => ({ }) let bind = (f, dom) => { - let deps = {_getters: new Set, _setters: new Set}, binding = {f}, prevNewDerives = curNewDerives + let deps = {_getters: new st, _setters: new st}, binding = {f}, prevNewDerives = curNewDerives curNewDerives = [] let newDom = runAndCaptureDeps(f, deps, dom) - newDom = (newDom ?? document).nodeType ? newDom : new Text(newDom) + newDom = (newDom ?? dc).nodeType ? newDom : new Text(newDom) for (let d of deps._getters) deps._setters.has(d) || (addStatesToGc(d), d._bindings.push(binding)) for (let l of curNewDerives) l._dom = newDom @@ -74,7 +74,7 @@ let bind = (f, dom) => { } let derive = (f, s = state(), dom) => { - let deps = {_getters: new Set, _setters: new Set}, listener = {f, s} + let deps = {_getters: new st, _setters: new st}, listener = {f, s} listener._dom = dom ?? curNewDerives?.push(listener) ?? alwaysConnectedDom s.val = runAndCaptureDeps(f, deps, s.rawVal) for (let d of deps._getters) @@ -83,7 +83,7 @@ let derive = (f, s = state(), dom) => { } let add = (dom, ...children) => { - for (let c of children.flat(Infinity)) { + for (let c of children.flat(1/0)) { let protoOfC = protoOf(c ?? 0) let child = protoOfC === stateProto ? bind(() => c.val) : protoOfC === funcProto ? bind(c) : c @@ -94,22 +94,22 @@ let add = (dom, ...children) => { let tag = (ns, name, ...args) => { let [props, ...children] = protoOf(args[0] ?? 0) === objProto ? args : [{}, ...args] - let dom = ns ? document.createElementNS(ns, name) : document.createElement(name) - for (let [k, v] of Object.entries(props)) { + let n = ns&&'NS', doc = dc['createElement'+n](ns||name,name) + for (let [k, v] of object.entries(props)) { let getPropDescriptor = proto => proto ? - Object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : + object.getOwnPropertyDescriptor(proto, k) ?? getPropDescriptor(protoOf(proto)) : _undefined let cacheKey = name + "," + k let propSetter = propSetterCache[cacheKey] ??= getPropDescriptor(protoOf(dom))?.set ?? 0 - let setter = k.startsWith("on") ? + let on = k.startsWith("on"), setter = on ? (v, oldV) => { let event = k.slice(2) - dom.removeEventListener(event, oldV) - dom.addEventListener(event, v) + dom[remove+evl](event, oldV) + dom['add'+evl](event, v) } : propSetter ? propSetter.bind(dom) : dom.setAttribute.bind(dom, k) let protoOfV = protoOf(v ?? 0) - k.startsWith("on") || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto) + on || protoOfV === funcProto && (v = derive(v), protoOfV = stateProto) protoOfV === stateProto ? bind(() => (setter(v.val, v._oldVal), dom)) : setter(v) } return add(dom, children) @@ -117,18 +117,18 @@ let tag = (ns, name, ...args) => { let handler = ns => ({get: (_, name) => tag.bind(_undefined, ns, name)}) -let update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove() +let update = (dom, newDom) => newDom === dom || dom[newDom?'replaceWith':remove](newDom) let updateDoms = () => { let iter = 0, derivedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) do { - derivedStates = new Set - for (let l of new Set(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) + derivedStates = new st + for (let l of new st(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) derive(l.f, l.s, l._dom), l._dom = _undefined } while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length) let changedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) changedStates = _undefined - for (let b of new Set(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) + for (let b of new st(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) update(b._dom, bind(b.f, b._dom)), b._dom = _undefined for (let s of changedStatesArray) s._oldVal = s.rawVal }