Skip to content

Commit 49c1c39

Browse files
committed
A pretty lame attempt at improving holes recognition
1 parent e9b2e76 commit 49c1c39

7 files changed

Lines changed: 53 additions & 35 deletions

File tree

dist/dev/json.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var errors = {
2121
invalid_interpolation: (template, value) => new SyntaxError(`Invalid interpolation - expected hole or array: ${String(value)} found in template ${asTemplate(template)}`),
2222
invalid_hole: value => new SyntaxError(`Invalid interpolation - expected hole: ${String(value)}`),
2323
invalid_key: value => new SyntaxError(`Invalid key attribute or position in template: ${String(value)}`),
24+
invalid_ref: template => new SyntaxError(`Invalid ref attribute or position in template: ${asTemplate(template)}`),
2425
invalid_array: value => new SyntaxError(`Invalid array - expected html/svg but found something else: ${String(value)}`),
2526
invalid_component: value => new SyntaxError(`Invalid component: ${String(value)}`),
2627
};

dist/dev/parser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var errors = {
2121
invalid_interpolation: (template, value) => new SyntaxError(`Invalid interpolation - expected hole or array: ${String(value)} found in template ${asTemplate(template)}`),
2222
invalid_hole: value => new SyntaxError(`Invalid interpolation - expected hole: ${String(value)}`),
2323
invalid_key: value => new SyntaxError(`Invalid key attribute or position in template: ${String(value)}`),
24+
invalid_ref: template => new SyntaxError(`Invalid ref attribute or position in template: ${asTemplate(template)}`),
2425
invalid_array: value => new SyntaxError(`Invalid array - expected html/svg but found something else: ${String(value)}`),
2526
invalid_component: value => new SyntaxError(`Invalid component: ${String(value)}`),
2627
};

src/dom/rabbit.js

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { children } from './ish.js';
88
import { effect } from './signals.js';
99
import { isArray } from '../utils.js';
1010
import { PersistentFragment, diffFragment, nodes } from './persistent-fragment.js';
11-
import { ARRAY, COMMENT, COMPONENT, EVENT, KEY, REF, SIGNAL, ref } from './update.js';
11+
import { ARRAY, COMMENT, COMPONENT, EVENT, KEY, REF, SIGNAL, HOLE, ref } from './update.js';
1212

1313
import { _get as getDirect, _set as setDirect } from './direct.js';
1414
import { Signal, _get as getSignal, _set as setSignal } from './signals.js';
@@ -37,7 +37,7 @@ const component = (Component, obj, signals) => {
3737
const signal = getSignal();
3838
const length = signals.length;
3939
let i = 0;
40-
setSignal(/** @param {unknown} value */ value => i < length ? signals[i++] : (signals[i++] = signal(value)));
40+
setSignal((value, options) => i < length ? signals[i++] : (signals[i++] = signal(value, options)));
4141
const wasDirect = getDirect();
4242
if (wasDirect) setDirect(!wasDirect);
4343
try { return Component(obj, global); }
@@ -64,6 +64,30 @@ const getHole = (hole, value) => {
6464
return hole;
6565
};
6666

67+
const notifyRefs = (refs, template) => {
68+
for (const node of refs) {
69+
const value = node[ref];
70+
switch (typeof value) {
71+
case 'object': {
72+
if (value instanceof Signal)
73+
value.value = node;
74+
else {
75+
//@ts-ignore
76+
if (DEBUG && !value) throw errors.invalid_ref(template);
77+
value.current = node;
78+
}
79+
break;
80+
}
81+
case 'function': {
82+
value(node);
83+
break;
84+
}
85+
//@ts-ignore
86+
default: if (DEBUG) throw errors.invalid_ref(template);
87+
}
88+
}
89+
};
90+
6791
const props = Symbol();
6892
const global = {};
6993

@@ -143,20 +167,25 @@ export class Hole {
143167
}
144168
}
145169
else {
146-
let commit = true;
170+
let t = type, commit = true, isComment = type & COMMENT;
147171
//@ts-ignore
148172
if (DEBUG && (type & ARRAY) && !isArray(value)) throw errors.invalid_interpolation(this.t[3], value);
149-
if (!direct && (type & COMMENT) && !(type & SIGNAL)) {
173+
if (!direct && isComment && !(type & SIGNAL)) {
150174
if (type & ARRAY) {
151175
commit = false;
152176
//@ts-ignore
153177
if (value.length) {
154178
//@ts-ignore
155-
node.before(...(node[nodes] = value[0] instanceof Hole ? value.map(dom) : value));
179+
const isHole = value[0] instanceof Hole;
180+
if (isHole) t |= HOLE;
181+
//@ts-ignore
182+
node.before(...(node[nodes] = isHole ? value.map(dom) : value));
156183
}
157184
}
158185
else if (value instanceof Hole) {
186+
t |= HOLE;
159187
commit = false;
188+
//@ts-ignore
160189
update(node, dom(value));
161190
}
162191
}
@@ -171,21 +200,12 @@ export class Hole {
171200
}
172201
}
173202
//@ts-ignore
174-
changes[length] = [type, update, value, node];
175-
if (direct && (type & COMMENT)) node.remove();
176-
}
177-
}
178-
if (refs) {
179-
for (const node of refs) {
180-
const value = node[ref];
181-
if (typeof value === 'function')
182-
value(node);
183-
else if (value instanceof Signal)
184-
value.value = node;
185-
else if (value)
186-
value.current = node;
203+
changes[length] = [t, update, value, node];
204+
if (direct && isComment) node.remove();
187205
}
188206
}
207+
//@ts-ignore
208+
if (refs) notifyRefs(refs, DEBUG && this.t[3]);
189209
}
190210

191211
const { childNodes } = root;
@@ -235,16 +255,16 @@ export class Hole {
235255
else update(prev, value);
236256
}
237257
else {
238-
let change = value;
258+
let change = value, isComment = type & COMMENT, isSignal = type & SIGNAL, isHole = type & HOLE;
239259
if (type & ARRAY) {
240260
if (DEBUG && !isArray(value)) throw errors.invalid_interpolation([], value);
241-
if (type & COMMENT) {
261+
if (isComment) {
242262
//@ts-ignore
243263
const l = value.length;
244264
const h = prev.length;
245265
// TODO: a smarter differ that does not require 2 loops
246266
//@ts-ignore
247-
if (l && (value[0] instanceof Hole)) {
267+
if (l && (isHole || (value[0] instanceof Hole && (entry[0] |= HOLE)))) {
248268
//@ts-ignore
249269
if (DEBUG && h && !(prev[0] instanceof Hole)) throw errors.invalid_interpolation([], value[0]);
250270
change = [];
@@ -260,21 +280,13 @@ export class Hole {
260280
//@ts-ignore
261281
else if ((type & EVENT) && (value[0] === prev[0])) continue;
262282
}
263-
else if (type & COMMENT) {
264-
if (type & SIGNAL) {
265-
if (value === prev) {
266-
update(entry[3], change);
267-
continue;
268-
}
269-
}
270-
else if (prev instanceof Hole) {
271-
if (DEBUG && !(value instanceof Hole)) throw errors.invalid_interpolation([], value);
272-
value = getHole(prev, /** @type {Hole} */(value));
273-
//@ts-ignore
274-
change = value.n;
275-
}
283+
else if (isHole && !isSignal) {
284+
if (DEBUG && !(value instanceof Hole)) throw errors.invalid_interpolation([], value);
285+
value = getHole(prev, /** @type {Hole} */(value));
286+
//@ts-ignore
287+
change = value.n;
276288
}
277-
if (value !== prev) {
289+
if (isSignal || value !== prev) {
278290
entry[2] = value;
279291
update(entry[3], change);
280292
}

src/dom/update.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const TOGGLE = 1 << 12;
3131
export const UNSAFE = 1 << 13;
3232
export const REF = 1 << 14;
3333
export const SIGNAL = 1 << 15;
34+
export const HOLE = 1 << 16;
3435

3536
// COMPONENT flags
3637
const COMPONENT_DIRECT = COMPONENT | DIRECT;

src/errors.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default {
2121
invalid_interpolation: (template, value) => new SyntaxError(`Invalid interpolation - expected hole or array: ${String(value)} found in template ${asTemplate(template)}`),
2222
invalid_hole: value => new SyntaxError(`Invalid interpolation - expected hole: ${String(value)}`),
2323
invalid_key: value => new SyntaxError(`Invalid key attribute or position in template: ${String(value)}`),
24+
invalid_ref: template => new SyntaxError(`Invalid ref attribute or position in template: ${asTemplate(template)}`),
2425
invalid_array: value => new SyntaxError(`Invalid array - expected html/svg but found something else: ${String(value)}`),
2526
invalid_component: value => new SyntaxError(`Invalid component: ${String(value)}`),
2627
};

types/dom/update.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const TOGGLE: number;
1414
export const UNSAFE: number;
1515
export const REF: number;
1616
export const SIGNAL: number;
17+
export const HOLE: number;
1718
export const fragment: (content: string, xml?: boolean) => DocumentFragment;
1819
export const ref: unique symbol;
1920
export function isKeyed(): boolean;

types/errors.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ declare namespace _default {
1414
function invalid_interpolation(template: any, value: any): SyntaxError;
1515
function invalid_hole(value: any): SyntaxError;
1616
function invalid_key(value: any): SyntaxError;
17+
function invalid_ref(template: any): SyntaxError;
1718
function invalid_array(value: any): SyntaxError;
1819
function invalid_component(value: any): SyntaxError;
1920
}

0 commit comments

Comments
 (0)