Skip to content

Commit

Permalink
Minor optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
dy committed Nov 18, 2023
1 parent 81263bc commit fd16383
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 70 deletions.
8 changes: 6 additions & 2 deletions r&d.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@
+ allows dynamic subscription to requested fields ( no need for preact/signals neither for signal-struct )
+ we anyways need sandbox even in case of subscript

## [ ] Store: how to organize array.length subscription?
## [x] Store: how to organize array.length subscription? -> see signals-proxy

* It causes recursion in `:x='array.push(x)'`

Expand Down Expand Up @@ -441,7 +441,7 @@

4. Subscript-based something

## [ ] :each over/undersubscription
## [x] :each over/undersubscription -> proxy-signals store solves that

* we must subscribe to each item from the list - it should update itself only, not the whole list. How?

Expand Down Expand Up @@ -708,3 +708,7 @@
## [x] let/const in expressions: allow or prohibit -> let's prohibit, force user to wrap into a function himself

- allowing forces wrapping internally, which creates return statement confustion

## [x] Take over parent signals, rather than inherit?

- Parent state can dynamically obtain new signal, and nested states won't have access to that
17 changes: 5 additions & 12 deletions sprae.auto.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,17 +450,14 @@
return s2.value;
if (parent)
return parent[key];
if (sandbox.hasOwnProperty(key))
return sandbox[key];
return sandbox[key];
},
set(values2, key, v2) {
if (_len) {
if (key === "length") {
n(() => {
for (let i2 = v2, l2 = signals.length; i2 < l2; i2++)
delete state[i2];
for (let i2 = signals.length; i2 < v2; i2++)
state[i2] = null;
_len.value = signals.length = values2.length = v2;
});
return true;
Expand All @@ -474,29 +471,25 @@
s2._set(v2);
else if (Array.isArray(v2) && Array.isArray(cur)) {
s(() => n(() => {
let i2 = 0, l2 = v2.length;
let i2 = 0, l2 = v2.length, vals = values2[key];
for (; i2 < l2; i2++)
cur[i2] = values2[key][i2] = v2[i2];
cur[i2] = vals[i2] = v2[i2];
cur.length = l2;
s2.value = null, s2.value = cur;
}));
} else {
if (Array.isArray(cur))
cur.length = 0;
s2.value = createState(values2[key] = v2);
}
if (_len && key >= _len.peek())
_len.value = signals.length = values2.length = Number(key) + 1;
return true;
},
deleteProperty(values2, key) {
if (key in signals)
signals[key]._del?.(), delete signals[key], delete values2[key];
signals[key]?._del?.(), delete signals[key], delete values2[key];
return true;
}
});
for (let key in values)
values[key], signals[key] = initSignals?.[key] ?? null;
signals[key] = initSignals?.[key] ?? initSignal(key);
function initSignal(key) {
if (values.hasOwnProperty(key)) {
const desc = Object.getOwnPropertyDescriptor(values, key);
Expand Down
2 changes: 1 addition & 1 deletion sprae.auto.min.js

Large diffs are not rendered by default.

17 changes: 5 additions & 12 deletions sprae.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,17 +449,14 @@ function createState(values, parent) {
return s2.value;
if (parent)
return parent[key];
if (sandbox.hasOwnProperty(key))
return sandbox[key];
return sandbox[key];
},
set(values2, key, v2) {
if (_len) {
if (key === "length") {
n(() => {
for (let i2 = v2, l2 = signals.length; i2 < l2; i2++)
delete state[i2];
for (let i2 = signals.length; i2 < v2; i2++)
state[i2] = null;
_len.value = signals.length = values2.length = v2;
});
return true;
Expand All @@ -473,29 +470,25 @@ function createState(values, parent) {
s2._set(v2);
else if (Array.isArray(v2) && Array.isArray(cur)) {
s(() => n(() => {
let i2 = 0, l2 = v2.length;
let i2 = 0, l2 = v2.length, vals = values2[key];
for (; i2 < l2; i2++)
cur[i2] = values2[key][i2] = v2[i2];
cur[i2] = vals[i2] = v2[i2];
cur.length = l2;
s2.value = null, s2.value = cur;
}));
} else {
if (Array.isArray(cur))
cur.length = 0;
s2.value = createState(values2[key] = v2);
}
if (_len && key >= _len.peek())
_len.value = signals.length = values2.length = Number(key) + 1;
return true;
},
deleteProperty(values2, key) {
if (key in signals)
signals[key]._del?.(), delete signals[key], delete values2[key];
signals[key]?._del?.(), delete signals[key], delete values2[key];
return true;
}
});
for (let key in values)
values[key], signals[key] = initSignals?.[key] ?? null;
signals[key] = initSignals?.[key] ?? initSignal(key);
function initSignal(key) {
if (values.hasOwnProperty(key)) {
const desc = Object.getOwnPropertyDescriptor(values, key);
Expand Down
2 changes: 1 addition & 1 deletion sprae.min.js

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions src/directives.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// directives & parsing
import sprae from './core.js'
import createState, { effect, computed, untracked, batch, _dispose, _signals } from './state.signals-proxy.js'
import { queueMicrotask, WeakishMap } from './util.js'
import { queueMicrotask } from './util.js'

// reserved directives - order matters!
// primary initialized first by selector, secondary initialized by iterating attributes
Expand Down Expand Up @@ -107,9 +107,11 @@ primary['each'] = (tpl, expr, state) => {
const signals = items[_signals]
for (let i = prevl; i < newl; i++) {
items[i]; // touch item to create signal
const el = tpl.cloneNode(true), scope = createState({
[itemVar]: signals[i] ?? items[i], [idxVar]: keys?.[i] ?? i
}, state)
const el = tpl.cloneNode(true),
scope = createState({
[itemVar]: signals[i] ?? items[i],
[idxVar]: keys?.[i] ?? i
}, state)
holder.before(el)
sprae(el, scope)
const { _del } = (signals[i] ||= {});
Expand Down
12 changes: 4 additions & 8 deletions src/state.signals-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function createState(values, parent) {
const s = signals[key] || initSignal(key)
if (s) return s.value // existing property
if (parent) return parent[key]; // touch parent
if (sandbox.hasOwnProperty(key)) return sandbox[key] // Array, window etc
return sandbox[key] // Array, window etc
},
set(values, key, v) {
if (_len) {
Expand All @@ -66,8 +66,6 @@ export default function createState(values, parent) {
batch(() => {
// force cleaning up tail
for (let i = v, l = signals.length; i < l; i++) delete state[i]
// force init new signals
for (let i = signals.length; i < v; i++) state[i] = null
_len.value = signals.length = values.length = v;
})
return true
Expand All @@ -84,16 +82,14 @@ export default function createState(values, parent) {
// patch array
else if (Array.isArray(v) && Array.isArray(cur)) {
untracked(() => batch(() => {
let i = 0, l = v.length;
for (; i < l; i++) cur[i] = values[key][i] = v[i]
let i = 0, l = v.length, vals = values[key];
for (; i < l; i++) cur[i] = vals[i] = v[i]
cur.length = l // forces deleting tail signals
s.value = null, s.value = cur // bump effects
}))
}
// .x = y
else {
// reflect change in values
if (Array.isArray(cur)) cur.length = 0 // cleanup array subs
s.value = createState(values[key] = v)
}

Expand All @@ -103,7 +99,7 @@ export default function createState(values, parent) {
return true
},
deleteProperty(values, key) {
if (key in signals) signals[key]._del?.(), delete signals[key], delete values[key]
signals[key]?._del?.(), delete signals[key], delete values[key]
return true
}
})
Expand Down
30 changes: 0 additions & 30 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,3 @@
// reset stacktrace or plan for fastest next call
// https://twitter.com/_developit/status/1634033380940455936
export const queueMicrotask = Promise.prototype.then.bind(Promise.resolve());

// based on https://github.com/WebReflection/not-so-weak/
const refs = new WeakMap;

const set = value => {
const ref = new WeakRef(value);
refs.set(value, ref);
return ref;
};

const get = value => refs.get(value) || set(value);

export class WeakishMap extends Map {
#registry = new FinalizationRegistry(key => super.delete(key));
get size() { return [...this].length }
constructor(entries = []) {
super();
for (const [key, value] of entries) this.set(key, value);
}
get(key) {
return super.get(key)?.deref();
}
set(key, value) {
let ref = super.get(key);
if (ref) this.#registry.unregister(ref);
ref = get(value);
this.#registry.register(value, key, ref);
return super.set(key, ref);
}
}

0 comments on commit fd16383

Please sign in to comment.