ripple 0.2.87 → 0.2.89
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 +2 -1
- package/src/compiler/phases/1-parse/index.js +74 -7
- package/src/compiler/phases/2-analyze/index.js +3 -1
- package/src/compiler/phases/3-transform/client/index.js +52 -17
- package/src/runtime/array.js +9 -242
- package/src/runtime/index-client.js +3 -1
- package/src/runtime/internal/client/constants.js +2 -0
- package/src/runtime/internal/client/for.js +403 -403
- package/src/runtime/internal/client/if.js +29 -29
- package/src/runtime/internal/client/index.js +4 -0
- package/src/runtime/internal/client/operations.js +0 -1
- package/src/runtime/internal/client/render.js +5 -5
- package/src/runtime/internal/client/runtime.js +2 -2
- package/src/runtime/internal/client/script.js +16 -0
- package/src/runtime/internal/client/utils.js +4 -0
- package/src/runtime/internal/server/index.js +5 -2
- package/src/runtime/object.js +29 -0
- package/src/runtime/proxy.js +341 -0
- package/src/utils/events.js +3 -3
- package/tests/client/__snapshots__/basic.test.ripple.snap +13 -0
- package/tests/client/array.test.ripple +3 -3
- package/tests/client/basic.test.ripple +90 -0
- package/tests/client/head.test.ripple +196 -0
- package/tests/client/object.test.ripple +183 -0
- package/types/index.d.ts +8 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.89",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"@jridgewell/sourcemap-codec": "^1.5.5",
|
|
67
67
|
"acorn": "^8.15.0",
|
|
68
68
|
"acorn-typescript": "^1.4.13",
|
|
69
|
+
"clsx": "^2.1.1",
|
|
69
70
|
"esrap": "^2.1.0",
|
|
70
71
|
"is-reference": "^3.0.3",
|
|
71
72
|
"magic-string": "^0.30.18",
|
|
@@ -80,13 +80,17 @@ function RipplePlugin(config) {
|
|
|
80
80
|
// Look ahead to see if this is followed by [ for tuple syntax
|
|
81
81
|
if (this.pos + 1 < this.input.length) {
|
|
82
82
|
const nextChar = this.input.charCodeAt(this.pos + 1);
|
|
83
|
-
if (nextChar === 91) {
|
|
84
|
-
// [ character
|
|
85
|
-
// This is a tuple literal #[
|
|
86
|
-
// Consume both # and [
|
|
83
|
+
if (nextChar === 91 || nextChar === 123) {
|
|
84
|
+
// [ or { character
|
|
85
|
+
// This is a tuple literal #[ or #{
|
|
86
|
+
// Consume both # and [ or {
|
|
87
87
|
++this.pos; // consume #
|
|
88
|
-
++this.pos; // consume [
|
|
89
|
-
|
|
88
|
+
++this.pos; // consume [ or {
|
|
89
|
+
if (nextChar === 123) {
|
|
90
|
+
return this.finishToken(tt.braceL, '#{');
|
|
91
|
+
} else {
|
|
92
|
+
return this.finishToken(tt.bracketL, '#[');
|
|
93
|
+
}
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
96
|
}
|
|
@@ -181,6 +185,8 @@ function RipplePlugin(config) {
|
|
|
181
185
|
// Check if this is a tuple literal starting with #[
|
|
182
186
|
if (this.type === tt.bracketL && this.value === '#[') {
|
|
183
187
|
return this.parseTrackedArrayExpression();
|
|
188
|
+
} else if (this.type === tt.braceL && this.value === '#{') {
|
|
189
|
+
return this.parseTrackedObjectExpression();
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
return super.parseExprAtom(refDestructuringErrors, forNew, forInit);
|
|
@@ -221,6 +227,38 @@ function RipplePlugin(config) {
|
|
|
221
227
|
return this.finishNode(node, 'TrackedArrayExpression');
|
|
222
228
|
}
|
|
223
229
|
|
|
230
|
+
parseTrackedObjectExpression() {
|
|
231
|
+
const node = this.startNode();
|
|
232
|
+
this.next(); // consume the '#{'
|
|
233
|
+
|
|
234
|
+
node.properties = [];
|
|
235
|
+
|
|
236
|
+
// Parse object properties similar to regular object parsing
|
|
237
|
+
let first = true;
|
|
238
|
+
while (!this.eat(tt.braceR)) {
|
|
239
|
+
if (!first) {
|
|
240
|
+
this.expect(tt.comma);
|
|
241
|
+
if (this.afterTrailingComma(tt.braceR)) break;
|
|
242
|
+
} else {
|
|
243
|
+
first = false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (this.type === tt.ellipsis) {
|
|
247
|
+
// Spread property
|
|
248
|
+
const prop = this.parseSpread();
|
|
249
|
+
node.properties.push(prop);
|
|
250
|
+
if (this.type === tt.comma && this.input.charCodeAt(this.pos) === 125) {
|
|
251
|
+
this.raise(this.pos, 'Trailing comma is not permitted after the rest element');
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
// Regular property
|
|
255
|
+
node.properties.push(this.parseProperty(false, {}));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return this.finishNode(node, 'TrackedObjectExpression');
|
|
260
|
+
}
|
|
261
|
+
|
|
224
262
|
parseExportDefaultDeclaration() {
|
|
225
263
|
// Check if this is "export default component"
|
|
226
264
|
if (this.value === 'component') {
|
|
@@ -793,7 +831,36 @@ function RipplePlugin(config) {
|
|
|
793
831
|
this.next();
|
|
794
832
|
}
|
|
795
833
|
} else {
|
|
796
|
-
if (open.name.name === '
|
|
834
|
+
if (open.name.name === 'script') {
|
|
835
|
+
let content = '';
|
|
836
|
+
|
|
837
|
+
// TODO implement this where we get a string for content of the content of the script tag
|
|
838
|
+
// This is a temporary workaround to get the content of the script tag
|
|
839
|
+
const start = open.end;
|
|
840
|
+
const input = this.input.slice(start);
|
|
841
|
+
const end = input.indexOf('</script>');
|
|
842
|
+
content = input.slice(0, end);
|
|
843
|
+
|
|
844
|
+
const newLines = content.match(regex_newline_characters)?.length;
|
|
845
|
+
if (newLines) {
|
|
846
|
+
this.curLine = open.loc.end.line + newLines;
|
|
847
|
+
this.lineStart = start + content.lastIndexOf('\n') + 1;
|
|
848
|
+
}
|
|
849
|
+
this.pos = start + content.length + 1;
|
|
850
|
+
|
|
851
|
+
this.type = tok.jsxTagStart;
|
|
852
|
+
this.next();
|
|
853
|
+
if (this.value === '/') {
|
|
854
|
+
this.next();
|
|
855
|
+
this.jsx_parseElementName();
|
|
856
|
+
this.exprAllowed = true;
|
|
857
|
+
this.#path.pop();
|
|
858
|
+
this.next();
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
element.content = content;
|
|
862
|
+
this.finishNode(element, 'Element');
|
|
863
|
+
} else if (open.name.name === 'style') {
|
|
797
864
|
// jsx_parseOpeningElementAt treats ID selectors (ie. #myid) or type selectors (ie. div) as identifier and read it
|
|
798
865
|
// So backtrack to the end of the <style> tag to make sure everything is included
|
|
799
866
|
const start = open.end;
|
|
@@ -488,7 +488,9 @@ const visitors = {
|
|
|
488
488
|
if (attr.name.type === 'Identifier') {
|
|
489
489
|
attribute_names.add(attr.name);
|
|
490
490
|
}
|
|
491
|
-
|
|
491
|
+
if (attr.value !== null) {
|
|
492
|
+
visit(attr.value, state);
|
|
493
|
+
}
|
|
492
494
|
} else if (attr.type === 'SpreadAttribute') {
|
|
493
495
|
visit(attr.argument, state);
|
|
494
496
|
} else if (attr.type === 'RefAttribute') {
|
|
@@ -133,16 +133,12 @@ function visit_title_element(node, context) {
|
|
|
133
133
|
),
|
|
134
134
|
);
|
|
135
135
|
} else {
|
|
136
|
-
|
|
136
|
+
context.state.init.push(
|
|
137
|
+
b.stmt(b.assignment('=', b.id('_$_.document.title'), result)),
|
|
138
|
+
);
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
function visit_style_element(node, context) {
|
|
141
|
-
context.state.template.push(
|
|
142
|
-
b.literal(`<style>${sanitize_template_string(node.css)}</style>`),
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
142
|
const visitors = {
|
|
147
143
|
_: function set_scope(node, { next, state }) {
|
|
148
144
|
const scope = state.scopes.get(node);
|
|
@@ -342,6 +338,25 @@ const visitors = {
|
|
|
342
338
|
);
|
|
343
339
|
},
|
|
344
340
|
|
|
341
|
+
TrackedObjectExpression(node, context) {
|
|
342
|
+
if (context.state.to_ts) {
|
|
343
|
+
if (!context.state.imports.has(`import { TrackedObject } from 'ripple'`)) {
|
|
344
|
+
context.state.imports.add(`import { TrackedObject } from 'ripple'`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return b.new(
|
|
348
|
+
b.id('TrackedObject'),
|
|
349
|
+
b.object(node.properties.map((prop) => context.visit(prop)))
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return b.call(
|
|
354
|
+
'_$_.tracked_object',
|
|
355
|
+
b.object(node.properties.map((prop) => context.visit(prop))),
|
|
356
|
+
b.id('__block'),
|
|
357
|
+
);
|
|
358
|
+
},
|
|
359
|
+
|
|
345
360
|
MemberExpression(node, context) {
|
|
346
361
|
const parent = context.path.at(-1);
|
|
347
362
|
|
|
@@ -487,9 +502,19 @@ const visitors = {
|
|
|
487
502
|
Element(node, context) {
|
|
488
503
|
const { state, visit } = context;
|
|
489
504
|
|
|
490
|
-
if (context.state.inside_head
|
|
491
|
-
|
|
492
|
-
|
|
505
|
+
if (context.state.inside_head) {
|
|
506
|
+
if (node.id.type === 'Identifier' && node.id.name === 'style') {
|
|
507
|
+
state.template.push(`<style>${sanitize_template_string(node.css)}</style>`);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
if (node.id.type === 'Identifier' && node.id.name === 'script') {
|
|
511
|
+
const id = state.flush_node();
|
|
512
|
+
state.template.push('<!>');
|
|
513
|
+
context.state.init.push(
|
|
514
|
+
b.stmt(b.call('_$_.script', id, b.literal(sanitize_template_string(node.content)))),
|
|
515
|
+
);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
493
518
|
}
|
|
494
519
|
|
|
495
520
|
const is_dom_element = is_element_dom_element(node);
|
|
@@ -698,18 +723,18 @@ const visitors = {
|
|
|
698
723
|
const metadata = { tracking: false, await: false };
|
|
699
724
|
let expression = visit(class_attribute.value, { ...state, metadata });
|
|
700
725
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
726
|
+
const hash_arg = node.metadata.scoped && state.component.css
|
|
727
|
+
? b.literal(state.component.css.hash)
|
|
728
|
+
: undefined;
|
|
704
729
|
const is_html = context.state.metadata.namespace === 'html' && node.id.name !== 'svg';
|
|
705
730
|
|
|
706
731
|
if (metadata.tracking) {
|
|
707
732
|
local_updates.push(
|
|
708
|
-
b.stmt(b.call('_$_.set_class', id, expression,
|
|
733
|
+
b.stmt(b.call('_$_.set_class', id, expression, hash_arg, b.literal(is_html))),
|
|
709
734
|
);
|
|
710
735
|
} else {
|
|
711
736
|
state.init.push(
|
|
712
|
-
b.stmt(b.call('_$_.set_class', id, expression,
|
|
737
|
+
b.stmt(b.call('_$_.set_class', id, expression, hash_arg, b.literal(is_html))),
|
|
713
738
|
);
|
|
714
739
|
}
|
|
715
740
|
}
|
|
@@ -766,7 +791,8 @@ const visitors = {
|
|
|
766
791
|
if (attr.type === 'Attribute') {
|
|
767
792
|
if (attr.name.type === 'Identifier') {
|
|
768
793
|
const metadata = { tracking: false, await: false };
|
|
769
|
-
let property =
|
|
794
|
+
let property =
|
|
795
|
+
attr.value === null ? b.literal(true) : visit(attr.value, { ...state, metadata });
|
|
770
796
|
|
|
771
797
|
if (metadata.tracking || attr.name.tracked) {
|
|
772
798
|
if (attr.name.name === 'children') {
|
|
@@ -1139,6 +1165,14 @@ const visitors = {
|
|
|
1139
1165
|
return context.next();
|
|
1140
1166
|
},
|
|
1141
1167
|
|
|
1168
|
+
ExportNamedDeclaration(node, context) {
|
|
1169
|
+
if (!context.state.to_ts && node.exportKind === 'type') {
|
|
1170
|
+
return b.empty;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
return context.next();
|
|
1174
|
+
},
|
|
1175
|
+
|
|
1142
1176
|
TryStatement(node, context) {
|
|
1143
1177
|
if (!is_inside_component(context)) {
|
|
1144
1178
|
context.next();
|
|
@@ -1598,7 +1632,8 @@ function transform_children(children, context) {
|
|
|
1598
1632
|
for (const head_element of head_elements) {
|
|
1599
1633
|
visit_head_element(head_element, context);
|
|
1600
1634
|
}
|
|
1601
|
-
|
|
1635
|
+
|
|
1636
|
+
if (context.state.inside_head) {
|
|
1602
1637
|
const title_element = children.find(
|
|
1603
1638
|
(node) =>
|
|
1604
1639
|
node.type === 'Element' && node.id.type === 'Identifier' && node.id.name === 'title',
|
package/src/runtime/array.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/** @import { Block } from '#client' */
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { get_descriptor } from './internal/client/utils.js';
|
|
2
|
+
import { safe_scope } from './internal/client/runtime.js';
|
|
3
|
+
import { array_proxy } from './proxy.js';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* @template T
|
|
@@ -15,8 +14,7 @@ export function TrackedArray(...elements) {
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
var block = safe_scope();
|
|
18
|
-
|
|
19
|
-
return proxy({ elements, block });
|
|
17
|
+
return array_proxy({ elements, block });
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
/**
|
|
@@ -29,7 +27,7 @@ export function TrackedArray(...elements) {
|
|
|
29
27
|
TrackedArray.from = function (arrayLike, mapFn, thisArg) {
|
|
30
28
|
var block = safe_scope();
|
|
31
29
|
var elements = mapFn ? Array.from(arrayLike, mapFn, thisArg) : Array.from(arrayLike);
|
|
32
|
-
return
|
|
30
|
+
return array_proxy({ elements, block, from_static: true });
|
|
33
31
|
};
|
|
34
32
|
|
|
35
33
|
/**
|
|
@@ -40,7 +38,7 @@ TrackedArray.from = function (arrayLike, mapFn, thisArg) {
|
|
|
40
38
|
TrackedArray.of = function (...items) {
|
|
41
39
|
var block = safe_scope();
|
|
42
40
|
var elements = Array.of(...items);
|
|
43
|
-
return
|
|
41
|
+
return array_proxy({ elements, block, from_static: true });
|
|
44
42
|
};
|
|
45
43
|
|
|
46
44
|
/**
|
|
@@ -55,246 +53,15 @@ TrackedArray.fromAsync = async function (arrayLike, mapFn, thisArg) {
|
|
|
55
53
|
var elements = mapFn
|
|
56
54
|
? await Array.fromAsync(arrayLike, mapFn, thisArg)
|
|
57
55
|
: await Array.fromAsync(arrayLike);
|
|
58
|
-
return
|
|
56
|
+
return array_proxy({ elements, block, from_static: true });
|
|
59
57
|
};
|
|
60
58
|
|
|
61
59
|
/**
|
|
62
60
|
* @template T
|
|
63
|
-
* @param {
|
|
64
|
-
* elements: Iterable<T>,
|
|
65
|
-
* block: Block,
|
|
66
|
-
* from_static?: boolean,
|
|
67
|
-
* use_array?: boolean
|
|
68
|
-
* }} params
|
|
69
|
-
* @returns {TrackedArray<T>}
|
|
70
|
-
*/
|
|
71
|
-
function proxy({ elements, block, from_static = false, use_array = false }) {
|
|
72
|
-
/** @type {T[]} */
|
|
73
|
-
var arr;
|
|
74
|
-
var first;
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
from_static &&
|
|
78
|
-
(first = get_first_if_length(/** @type {Array<T>} */ (elements))) !== undefined
|
|
79
|
-
) {
|
|
80
|
-
arr = new Array();
|
|
81
|
-
arr[0] = /** @type {T} */ (/** @type {unknown} */ (first));
|
|
82
|
-
} else if (use_array) {
|
|
83
|
-
arr = /** @type {T[]} */ (elements);
|
|
84
|
-
} else {
|
|
85
|
-
arr = new Array(...elements);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
var tracked_elements = new Map();
|
|
89
|
-
var tracked_len = tracked(arr.length, block);
|
|
90
|
-
tracked_elements.set('length', tracked_len);
|
|
91
|
-
|
|
92
|
-
return new Proxy(arr, {
|
|
93
|
-
get(target, prop, receiver) {
|
|
94
|
-
var t = tracked_elements.get(prop);
|
|
95
|
-
var exists = prop in target;
|
|
96
|
-
|
|
97
|
-
if (t === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
|
|
98
|
-
t = tracked(exists ? /** @type {any} */ (target)[prop] : UNINITIALIZED, block);
|
|
99
|
-
tracked_elements.set(prop, t);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (t !== undefined) {
|
|
103
|
-
var v = get(t);
|
|
104
|
-
return v === UNINITIALIZED ? undefined : v;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
var result = Reflect.get(target, prop, receiver);
|
|
108
|
-
|
|
109
|
-
if (typeof result === 'function') {
|
|
110
|
-
if (methods_returning_arrays.has(/** @type {string} */ (prop))) {
|
|
111
|
-
/** @type {(this: any, ...args: any[]) => any} */
|
|
112
|
-
return function (...args) {
|
|
113
|
-
var output = Reflect.apply(result, receiver, args);
|
|
114
|
-
|
|
115
|
-
if (Array.isArray(output) && output !== target) {
|
|
116
|
-
return proxy({ elements: output, block, use_array: true });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return output;
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// When generating an iterator, we need to ensure that length is tracked
|
|
124
|
-
if (prop === 'entries' || prop === 'values' || prop === 'keys') {
|
|
125
|
-
receiver.length;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return result;
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
set(target, prop, value, receiver) {
|
|
133
|
-
var t = tracked_elements.get(prop);
|
|
134
|
-
var exists = prop in target;
|
|
135
|
-
|
|
136
|
-
if (prop === 'length') {
|
|
137
|
-
for (var i = value; i < tracked_len.v; i += 1) {
|
|
138
|
-
var other_t = tracked_elements.get(i + '');
|
|
139
|
-
if (other_t !== undefined) {
|
|
140
|
-
set(other_t, UNINITIALIZED, block);
|
|
141
|
-
} else if (i in target) {
|
|
142
|
-
// If the item exists in the original, we need to create a uninitialized tracked,
|
|
143
|
-
// else a later read of the property would result in a tracked being created with
|
|
144
|
-
// the value of the original item at that index.
|
|
145
|
-
other_t = tracked(UNINITIALIZED, block);
|
|
146
|
-
tracked_elements.set(i + '', other_t);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// If we haven't yet created a tracked for this property, we need to ensure
|
|
152
|
-
// we do so otherwise if we read it later, then the write won't be tracked and
|
|
153
|
-
// the heuristics of effects will be different vs if we had read the proxied
|
|
154
|
-
// object property before writing to that property.
|
|
155
|
-
if (t === undefined) {
|
|
156
|
-
if (!exists || get_descriptor(target, prop)?.writable) {
|
|
157
|
-
t = tracked(undefined, block);
|
|
158
|
-
set(t, value, block);
|
|
159
|
-
|
|
160
|
-
tracked_elements.set(prop, t);
|
|
161
|
-
}
|
|
162
|
-
} else {
|
|
163
|
-
exists = t.v !== UNINITIALIZED;
|
|
164
|
-
|
|
165
|
-
set(t, value, block);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
var result = Reflect.set(target, prop, value, receiver);
|
|
169
|
-
|
|
170
|
-
if (!exists) {
|
|
171
|
-
// If we have mutated an array directly, we might need to
|
|
172
|
-
// signal that length has also changed. Do it before updating metadata
|
|
173
|
-
// to ensure that iterating over the array as a result of a metadata update
|
|
174
|
-
// will not cause the length to be out of sync.
|
|
175
|
-
if (typeof prop === 'string') {
|
|
176
|
-
var n = Number(prop);
|
|
177
|
-
|
|
178
|
-
if (Number.isInteger(n) && n >= tracked_len.v) {
|
|
179
|
-
set(tracked_len, n + 1, block);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return result;
|
|
185
|
-
},
|
|
186
|
-
|
|
187
|
-
setPrototypeOf() {
|
|
188
|
-
throw new Error(`Cannot set prototype of \`TrackedArray\``);
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
deleteProperty(target, prop) {
|
|
192
|
-
var t = tracked_elements.get(prop);
|
|
193
|
-
|
|
194
|
-
if (t === undefined) {
|
|
195
|
-
if (prop in target) {
|
|
196
|
-
const t = tracked(UNINITIALIZED, block);
|
|
197
|
-
tracked_elements.set(prop, t);
|
|
198
|
-
}
|
|
199
|
-
} else {
|
|
200
|
-
set(t, UNINITIALIZED, block);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return Reflect.deleteProperty(target, prop);
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
has(target, prop) {
|
|
207
|
-
if (prop === TRACKED_ARRAY) {
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
var t = tracked_elements.get(prop);
|
|
211
|
-
var exists = (t !== undefined && t.v !== UNINITIALIZED) || Reflect.has(target, prop);
|
|
212
|
-
|
|
213
|
-
if (t !== undefined || !exists || get_descriptor(target, prop)?.writable) {
|
|
214
|
-
if (t === undefined) {
|
|
215
|
-
t = tracked(exists ? /** @type {any} */ (target)[prop] : UNINITIALIZED, block);
|
|
216
|
-
|
|
217
|
-
tracked_elements.set(prop, t);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
var value = get(t);
|
|
221
|
-
if (value === UNINITIALIZED) {
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return exists;
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
defineProperty(_, prop, descriptor) {
|
|
230
|
-
if (
|
|
231
|
-
!('value' in descriptor) ||
|
|
232
|
-
descriptor.configurable === false ||
|
|
233
|
-
descriptor.enumerable === false ||
|
|
234
|
-
descriptor.writable === false
|
|
235
|
-
) {
|
|
236
|
-
// we disallow non-basic descriptors, because unless they are applied to the
|
|
237
|
-
// target object — which we avoid, so that state can be forked — we will run
|
|
238
|
-
// afoul of the various invariants
|
|
239
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor#invariants
|
|
240
|
-
throw new Error(
|
|
241
|
-
'Only basic property descriptors are supported with value and configurable, enumerable, and writable set to true',
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
var t = tracked_elements.get(prop);
|
|
246
|
-
|
|
247
|
-
if (t === undefined) {
|
|
248
|
-
t = tracked(descriptor.value, block);
|
|
249
|
-
tracked_elements.set(prop, t);
|
|
250
|
-
} else {
|
|
251
|
-
set(t, descriptor.value, block);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return true;
|
|
255
|
-
},
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* @template T
|
|
261
|
-
* @param {Array<T>} array
|
|
262
|
-
* @returns {number | void}
|
|
263
|
-
*/
|
|
264
|
-
function get_first_if_length(array) {
|
|
265
|
-
var first = array[0];
|
|
266
|
-
|
|
267
|
-
if (
|
|
268
|
-
array.length === 1 &&
|
|
269
|
-
0 in array &&
|
|
270
|
-
Number.isInteger(first) &&
|
|
271
|
-
/** @type {number} */ (first) >= 0 &&
|
|
272
|
-
/** @type {number} */ (first) <= MAX_ARRAY_LENGTH
|
|
273
|
-
) {
|
|
274
|
-
return /** @type {number} */ (first);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const methods_returning_arrays = new Set([
|
|
279
|
-
'concat',
|
|
280
|
-
'filter',
|
|
281
|
-
'flat',
|
|
282
|
-
'flatMap',
|
|
283
|
-
'map',
|
|
284
|
-
'slice',
|
|
285
|
-
'splice',
|
|
286
|
-
'toReversed',
|
|
287
|
-
'toSorted',
|
|
288
|
-
'toSpliced',
|
|
289
|
-
'with',
|
|
290
|
-
]);
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* @template T
|
|
294
|
-
* @param {Iterable<T>} elements
|
|
61
|
+
* @param {Array<T>} elements
|
|
295
62
|
* @param {Block} block
|
|
296
63
|
* @returns {TrackedArray<T>}
|
|
297
64
|
*/
|
|
298
65
|
export function tracked_array(elements, block) {
|
|
299
|
-
return
|
|
300
|
-
}
|
|
66
|
+
return array_proxy({ elements, block, from_static: true });
|
|
67
|
+
}
|
|
@@ -45,12 +45,14 @@ export { create_context as createContext } from './internal/client/context.js';
|
|
|
45
45
|
export {
|
|
46
46
|
flush_sync as flushSync,
|
|
47
47
|
track,
|
|
48
|
-
trackSplit,
|
|
48
|
+
track_split as trackSplit,
|
|
49
49
|
untrack,
|
|
50
50
|
} from './internal/client/runtime.js';
|
|
51
51
|
|
|
52
52
|
export { TrackedArray } from './array.js';
|
|
53
53
|
|
|
54
|
+
export { TrackedObject } from './object.js';
|
|
55
|
+
|
|
54
56
|
export { TrackedSet } from './set.js';
|
|
55
57
|
|
|
56
58
|
export { TrackedMap } from './map.js';
|
|
@@ -22,6 +22,8 @@ export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK | COMPOSITE_BLO
|
|
|
22
22
|
export var UNINITIALIZED = Symbol();
|
|
23
23
|
/** @type {unique symbol} */
|
|
24
24
|
export const TRACKED_ARRAY = Symbol();
|
|
25
|
+
/** @type {unique symbol} */
|
|
26
|
+
export const TRACKED_OBJECT = Symbol();
|
|
25
27
|
export var COMPUTED_PROPERTY = Symbol();
|
|
26
28
|
export var REF_PROP = 'ref';
|
|
27
29
|
/** @type {unique symbol} */
|