Skip to content

Commit

Permalink
Reduce the vanjs file size even more (by 32 bytes, minimized).
Browse files Browse the repository at this point in the history
  • Loading branch information
X-Ryl669 committed Sep 2, 2024
1 parent eeb061b commit b8c5501
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 101 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 1 addition & 1 deletion public/van-1.5.2.debug.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion public/van-latest.debug.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
36 changes: 18 additions & 18 deletions public/van-latest.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -94,41 +94,41 @@ 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)
}

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
}
Expand Down
2 changes: 1 addition & 1 deletion public/van-latest.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 39 additions & 34 deletions public/van-latest.nomodule.debug.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(() => {
// van.js
var protoOf = Object.getPrototypeOf;
var object = Object;
var protoOf = object.getPrototypeOf;
var changedStates;
var derivedStates;
var curDeps;
Expand All @@ -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;
Expand Down Expand Up @@ -55,71 +60,71 @@
_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)
l._dom = newDom;
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
Expand Down Expand Up @@ -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"
Expand All @@ -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) => {
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit b8c5501

Please sign in to comment.