svelte 4.1.2 → 4.2.1
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/compiler.cjs +107 -62
- package/elements.d.ts +1 -0
- package/package.json +4 -2
- package/src/.eslintrc.json +6 -0
- package/src/compiler/compile/Component.js +2 -2
- package/src/compiler/compile/create_module.js +10 -10
- package/src/compiler/compile/nodes/Binding.js +2 -2
- package/src/compiler/compile/nodes/EachBlock.js +5 -3
- package/src/compiler/compile/nodes/Element.js +31 -3
- package/src/compiler/compile/nodes/shared/get_const_tags.js +2 -2
- package/src/compiler/compile/render_dom/wrappers/Element/index.js +3 -6
- package/src/compiler/compile/render_dom/wrappers/InlineComponent/index.js +8 -3
- package/src/compiler/compile/render_dom/wrappers/Window.js +8 -8
- package/src/compiler/compile/render_dom/wrappers/shared/is_dynamic.js +5 -2
- package/src/compiler/compile/render_ssr/index.js +4 -0
- package/src/compiler/parse/read/css-tree-cq/css_tree_parse.js +4 -4
- package/src/compiler/parse/read/css-tree-cq/node/query_feature_range.js +3 -3
- package/src/compiler/utils/fuzzymatch.js +1 -5
- package/src/compiler/utils/globals.js +1 -1
- package/src/compiler/utils/mapped_code.js +12 -1
- package/src/runtime/internal/Component.js +15 -4
- package/src/runtime/internal/dom.js +35 -33
- package/src/shared/version.js +1 -1
- package/svelte-html.d.ts +252 -0
- package/types/index.d.ts.map +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { is_html, is_svg, is_void } from '../../../shared/utils/names.js';
|
|
2
2
|
import Node from './shared/Node.js';
|
|
3
|
+
import { walk } from 'estree-walker';
|
|
3
4
|
import Attribute from './Attribute.js';
|
|
4
5
|
import Binding from './Binding.js';
|
|
5
6
|
import EventHandler from './EventHandler.js';
|
|
@@ -430,7 +431,7 @@ export default class Element extends Node {
|
|
|
430
431
|
}
|
|
431
432
|
if (this.name === 'textarea') {
|
|
432
433
|
if (info.children.length > 0) {
|
|
433
|
-
const value_attribute = info.attributes
|
|
434
|
+
const value_attribute = get_value_attribute(info.attributes);
|
|
434
435
|
if (value_attribute) {
|
|
435
436
|
component.error(value_attribute, compiler_errors.textarea_duplicate_value);
|
|
436
437
|
return;
|
|
@@ -449,7 +450,7 @@ export default class Element extends Node {
|
|
|
449
450
|
// Special case — treat these the same way:
|
|
450
451
|
// <option>{foo}</option>
|
|
451
452
|
// <option value={foo}>{foo}</option>
|
|
452
|
-
const value_attribute = info.attributes
|
|
453
|
+
const value_attribute = get_value_attribute(info.attributes);
|
|
453
454
|
if (!value_attribute) {
|
|
454
455
|
info.attributes.push({
|
|
455
456
|
type: 'Attribute',
|
|
@@ -875,7 +876,7 @@ export default class Element extends Node {
|
|
|
875
876
|
) {
|
|
876
877
|
const interactive_handlers = handlers
|
|
877
878
|
.map((handler) => handler.name)
|
|
878
|
-
.filter((
|
|
879
|
+
.filter((handler_name) => a11y_interactive_handlers.has(handler_name));
|
|
879
880
|
if (interactive_handlers.length > 0) {
|
|
880
881
|
component.warn(
|
|
881
882
|
this,
|
|
@@ -1420,3 +1421,30 @@ function within_custom_element(parent) {
|
|
|
1420
1421
|
}
|
|
1421
1422
|
return false;
|
|
1422
1423
|
}
|
|
1424
|
+
|
|
1425
|
+
/**
|
|
1426
|
+
* @param {any[]} attributes
|
|
1427
|
+
*/
|
|
1428
|
+
function get_value_attribute(attributes) {
|
|
1429
|
+
let node_value;
|
|
1430
|
+
attributes.forEach((node) => {
|
|
1431
|
+
if (node.type !== 'Spread' && node.name.toLowerCase() === 'value') {
|
|
1432
|
+
node_value = node;
|
|
1433
|
+
}
|
|
1434
|
+
if (node.type === 'Spread') {
|
|
1435
|
+
walk(/** @type {any} */ (node.expression), {
|
|
1436
|
+
enter(/** @type {import('estree').Node} */ node) {
|
|
1437
|
+
if (node_value) {
|
|
1438
|
+
this.skip();
|
|
1439
|
+
}
|
|
1440
|
+
if (node.type === 'Identifier') {
|
|
1441
|
+
if (/** @type {import('estree').Identifier} */ (node).name.toLowerCase() === 'value') {
|
|
1442
|
+
node_value = node;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
return node_value;
|
|
1450
|
+
}
|
|
@@ -73,8 +73,8 @@ function sort_consts_nodes(consts_nodes, component) {
|
|
|
73
73
|
}, [])
|
|
74
74
|
);
|
|
75
75
|
if (cycle && cycle.length) {
|
|
76
|
-
const
|
|
77
|
-
const node =
|
|
76
|
+
const node_list = lookup.get(cycle[0]);
|
|
77
|
+
const node = node_list[0];
|
|
78
78
|
component.error(node.node, compiler_errors.cyclical_const_tags(cycle));
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -990,7 +990,8 @@ export default class ElementWrapper extends Wrapper {
|
|
|
990
990
|
const static_attributes = [];
|
|
991
991
|
this.attributes.forEach((attr) => {
|
|
992
992
|
if (attr instanceof SpreadAttributeWrapper) {
|
|
993
|
-
|
|
993
|
+
const snippet = { type: 'SpreadElement', argument: attr.node.expression.manipulate(block) };
|
|
994
|
+
static_attributes.push(snippet);
|
|
994
995
|
} else {
|
|
995
996
|
const name = attr.property_name || attr.name;
|
|
996
997
|
static_attributes.push(p`${name}: ${attr.get_value(block)}`);
|
|
@@ -1240,11 +1241,7 @@ export default class ElementWrapper extends Wrapper {
|
|
|
1240
1241
|
}
|
|
1241
1242
|
if (this.dynamic_style_dependencies.size > 0) {
|
|
1242
1243
|
maybe_create_style_changed_var();
|
|
1243
|
-
|
|
1244
|
-
condition =
|
|
1245
|
-
all_deps.size === this.dynamic_style_dependencies.size
|
|
1246
|
-
? style_changed_var
|
|
1247
|
-
: x`${style_changed_var} || ${condition}`;
|
|
1244
|
+
condition = x`${condition} || ${style_changed_var}`;
|
|
1248
1245
|
}
|
|
1249
1246
|
block.chunks.update.push(b`
|
|
1250
1247
|
if (${condition}) {
|
|
@@ -105,14 +105,19 @@ export default class InlineComponentWrapper extends Wrapper {
|
|
|
105
105
|
this.slots.set(name, slot_definition);
|
|
106
106
|
}
|
|
107
107
|
warn_if_reactive() {
|
|
108
|
-
|
|
109
|
-
const
|
|
108
|
+
let { name } = this.node;
|
|
109
|
+
const top = name.split('.')[0]; // <T.foo/> etc. should check for T instead of "T.foo"
|
|
110
|
+
const variable = this.renderer.component.var_lookup.get(top);
|
|
110
111
|
if (!variable) {
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
const ignores = extract_ignores_above_node(this.node);
|
|
114
115
|
this.renderer.component.push_ignores(ignores);
|
|
115
|
-
if (
|
|
116
|
+
if (
|
|
117
|
+
variable.reassigned ||
|
|
118
|
+
variable.export_name || // or a prop
|
|
119
|
+
variable.mutated
|
|
120
|
+
) {
|
|
116
121
|
this.renderer.component.warn(this.node, compiler_warnings.reactive_component(name));
|
|
117
122
|
}
|
|
118
123
|
this.renderer.component.pop_ignores();
|
|
@@ -94,14 +94,14 @@ export default class WindowWrapper extends Wrapper {
|
|
|
94
94
|
bindings.scrollX && bindings.scrollY
|
|
95
95
|
? x`"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
|
|
96
96
|
: x`"${bindings.scrollX || bindings.scrollY}" in this._state`;
|
|
97
|
-
const
|
|
98
|
-
const
|
|
97
|
+
const scroll_x = bindings.scrollX && x`this._state.${bindings.scrollX}`;
|
|
98
|
+
const scroll_y = bindings.scrollY && x`this._state.${bindings.scrollY}`;
|
|
99
99
|
renderer.meta_bindings.push(b`
|
|
100
100
|
if (${condition}) {
|
|
101
|
-
@_scrollTo(${
|
|
101
|
+
@_scrollTo(${scroll_x || '@_window.pageXOffset'}, ${scroll_y || '@_window.pageYOffset'});
|
|
102
102
|
}
|
|
103
|
-
${
|
|
104
|
-
${
|
|
103
|
+
${scroll_x && `${scroll_x} = @_window.pageXOffset;`}
|
|
104
|
+
${scroll_y && `${scroll_y} = @_window.pageYOffset;`}
|
|
105
105
|
`);
|
|
106
106
|
block.event_listeners.push(x`
|
|
107
107
|
@listen(@_window, "${event}", () => {
|
|
@@ -132,17 +132,17 @@ export default class WindowWrapper extends Wrapper {
|
|
|
132
132
|
// special case... might need to abstract this out if we add more special cases
|
|
133
133
|
if (bindings.scrollX || bindings.scrollY) {
|
|
134
134
|
const condition = renderer.dirty([bindings.scrollX, bindings.scrollY].filter(Boolean));
|
|
135
|
-
const
|
|
135
|
+
const scroll_x = bindings.scrollX
|
|
136
136
|
? renderer.reference(bindings.scrollX)
|
|
137
137
|
: x`@_window.pageXOffset`;
|
|
138
|
-
const
|
|
138
|
+
const scroll_y = bindings.scrollY
|
|
139
139
|
? renderer.reference(bindings.scrollY)
|
|
140
140
|
: x`@_window.pageYOffset`;
|
|
141
141
|
block.chunks.update.push(b`
|
|
142
142
|
if (${condition} && !${scrolling}) {
|
|
143
143
|
${scrolling} = true;
|
|
144
144
|
@_clearTimeout(${scrolling_timeout});
|
|
145
|
-
@_scrollTo(${
|
|
145
|
+
@_scrollTo(${scroll_x}, ${scroll_y});
|
|
146
146
|
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
|
|
147
147
|
}
|
|
148
148
|
`);
|
|
@@ -3,8 +3,11 @@ import { is_reserved_keyword } from '../../../utils/reserved_keywords.js';
|
|
|
3
3
|
/** @param {import('../../../../interfaces.js').Var} variable */
|
|
4
4
|
export default function is_dynamic(variable) {
|
|
5
5
|
if (variable) {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// Only variables declared in the instance script tags should be considered dynamic
|
|
7
|
+
const is_declared_in_reactive_context = !variable.module && !variable.global;
|
|
8
|
+
|
|
9
|
+
if (is_declared_in_reactive_context && (variable.mutated || variable.reassigned)) return true; // dynamic internal state
|
|
10
|
+
if (is_declared_in_reactive_context && variable.writable && variable.export_name) return true; // writable props
|
|
8
11
|
if (is_reserved_keyword(variable.name)) return true;
|
|
9
12
|
}
|
|
10
13
|
return false;
|
|
@@ -144,9 +144,13 @@ export default function ssr(component, options) {
|
|
|
144
144
|
? b`
|
|
145
145
|
let $$settled;
|
|
146
146
|
let $$rendered;
|
|
147
|
+
let #previous_head = $$result.head;
|
|
147
148
|
|
|
148
149
|
do {
|
|
149
150
|
$$settled = true;
|
|
151
|
+
// $$result.head is mutated by the literal expression
|
|
152
|
+
// need to reset it if we're looping back to prevent duplication
|
|
153
|
+
$$result.head = #previous_head;
|
|
150
154
|
|
|
151
155
|
${reactive_declarations}
|
|
152
156
|
|
|
@@ -8,7 +8,7 @@ import * as node from './node/index.js';
|
|
|
8
8
|
*
|
|
9
9
|
* The new nodes are located in `./node`.
|
|
10
10
|
*/
|
|
11
|
-
const
|
|
11
|
+
const cq_syntax = fork({
|
|
12
12
|
atrule: {
|
|
13
13
|
// extend or override at-rule dictionary
|
|
14
14
|
container: {
|
|
@@ -16,8 +16,8 @@ const cqSyntax = fork({
|
|
|
16
16
|
prelude() {
|
|
17
17
|
return this.createSingleNodeList(this.ContainerQuery());
|
|
18
18
|
},
|
|
19
|
-
block(
|
|
20
|
-
return this.Block(
|
|
19
|
+
block(is_style_block = false) {
|
|
20
|
+
return this.Block(is_style_block);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -25,4 +25,4 @@ const cqSyntax = fork({
|
|
|
25
25
|
node
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
export const parse =
|
|
28
|
+
export const parse = cq_syntax.parse;
|
|
@@ -16,7 +16,7 @@ export const structure = {
|
|
|
16
16
|
value: ['Identifier', 'Number', 'Comparison', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
function
|
|
19
|
+
function lookup_non_ws_type_and_value(offset, type, reference_str) {
|
|
20
20
|
let current_type;
|
|
21
21
|
|
|
22
22
|
do {
|
|
@@ -26,7 +26,7 @@ function lookup_non_WS_type_and_value(offset, type, referenceStr) {
|
|
|
26
26
|
}
|
|
27
27
|
} while (current_type !== 0); // NULL -> 0
|
|
28
28
|
|
|
29
|
-
return current_type === type ? this.lookupValue(offset - 1,
|
|
29
|
+
return current_type === type ? this.lookupValue(offset - 1, reference_str) : false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export function parse() {
|
|
@@ -40,7 +40,7 @@ export function parse() {
|
|
|
40
40
|
while (!this.eof && this.tokenType !== RightParenthesis) {
|
|
41
41
|
switch (this.tokenType) {
|
|
42
42
|
case Number:
|
|
43
|
-
if (
|
|
43
|
+
if (lookup_non_ws_type_and_value.call(this, 1, Delim, '/')) {
|
|
44
44
|
child = this.Ratio();
|
|
45
45
|
} else {
|
|
46
46
|
child = this.Number();
|
|
@@ -26,11 +26,7 @@ function _distance(str1, str2) {
|
|
|
26
26
|
str1 = String(str1);
|
|
27
27
|
str2 = String(str2);
|
|
28
28
|
const distance = levenshtein(str1, str2);
|
|
29
|
-
|
|
30
|
-
return 1 - distance / str1.length;
|
|
31
|
-
} else {
|
|
32
|
-
return 1 - distance / str2.length;
|
|
33
|
-
}
|
|
29
|
+
return 1 - distance / Math.max(str1.length, str2.length);
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
// helper functions
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** ----------------------------------------------------------------------
|
|
2
2
|
This file is automatically generated by `scripts/globals-extractor.js`.
|
|
3
|
-
Generated At: 2023-
|
|
3
|
+
Generated At: 2023-08-11T04:11:50.562Z
|
|
4
4
|
---------------------------------------------------------------------- */
|
|
5
5
|
|
|
6
6
|
export default new Set([
|
|
@@ -292,7 +292,18 @@ export function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_
|
|
|
292
292
|
toUrl: {
|
|
293
293
|
enumerable: false,
|
|
294
294
|
value: function toUrl() {
|
|
295
|
-
|
|
295
|
+
let b64 = '';
|
|
296
|
+
if (typeof window !== 'undefined' && window.btoa) {
|
|
297
|
+
// btoa doesn't support multi-byte characters
|
|
298
|
+
b64 = window.btoa(unescape(encodeURIComponent(this.toString())));
|
|
299
|
+
} else if (typeof Buffer !== 'undefined') {
|
|
300
|
+
b64 = Buffer.from(this.toString(), 'utf8').toString('base64');
|
|
301
|
+
} else {
|
|
302
|
+
throw new Error(
|
|
303
|
+
'Unsupported environment: `window.btoa` or `Buffer` should be present to use toUrl.'
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
return 'data:application/json;charset=utf-8;base64,' + b64;
|
|
296
307
|
}
|
|
297
308
|
}
|
|
298
309
|
});
|
|
@@ -84,7 +84,17 @@ function make_dirty(component, i) {
|
|
|
84
84
|
component.$$.dirty[(i / 31) | 0] |= 1 << i % 31;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
// TODO: Document the other params
|
|
88
|
+
/**
|
|
89
|
+
* @param {SvelteComponent} component
|
|
90
|
+
* @param {import('./public.js').ComponentConstructorOptions} options
|
|
91
|
+
*
|
|
92
|
+
* @param {import('./utils.js')['not_equal']} not_equal Used to compare props and state values.
|
|
93
|
+
* @param {(target: Element | ShadowRoot) => void} [append_styles] Function that appends styles to the DOM when the component is first initialised.
|
|
94
|
+
* This will be the `add_css` function from the compiled component.
|
|
95
|
+
*
|
|
96
|
+
* @returns {void}
|
|
97
|
+
*/
|
|
88
98
|
export function init(
|
|
89
99
|
component,
|
|
90
100
|
options,
|
|
@@ -92,7 +102,7 @@ export function init(
|
|
|
92
102
|
create_fragment,
|
|
93
103
|
not_equal,
|
|
94
104
|
props,
|
|
95
|
-
append_styles,
|
|
105
|
+
append_styles = null,
|
|
96
106
|
dirty = [-1]
|
|
97
107
|
) {
|
|
98
108
|
const parent_component = current_component;
|
|
@@ -139,8 +149,9 @@ export function init(
|
|
|
139
149
|
if (options.target) {
|
|
140
150
|
if (options.hydrate) {
|
|
141
151
|
start_hydrating();
|
|
152
|
+
// TODO: what is the correct type here?
|
|
153
|
+
// @ts-expect-error
|
|
142
154
|
const nodes = children(options.target);
|
|
143
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
144
155
|
$$.fragment && $$.fragment.l(nodes);
|
|
145
156
|
nodes.forEach(detach);
|
|
146
157
|
} else {
|
|
@@ -283,7 +294,7 @@ if (typeof HTMLElement === 'function') {
|
|
|
283
294
|
'toAttribute'
|
|
284
295
|
);
|
|
285
296
|
if (attribute_value == null) {
|
|
286
|
-
this.removeAttribute(key);
|
|
297
|
+
this.removeAttribute(this.$$p_d[key].attribute || key);
|
|
287
298
|
} else {
|
|
288
299
|
this.setAttribute(this.$$p_d[key].attribute || key, attribute_value);
|
|
289
300
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ResizeObserverSingleton } from './ResizeObserverSingleton.js';
|
|
2
1
|
import { contenteditable_truthy_values, has_prop } from './utils.js';
|
|
2
|
+
|
|
3
|
+
import { ResizeObserverSingleton } from './ResizeObserverSingleton.js';
|
|
4
|
+
|
|
3
5
|
// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM
|
|
4
6
|
// at the end of hydration without touching the remaining nodes.
|
|
5
7
|
let is_hydrating = false;
|
|
@@ -50,14 +52,14 @@ function init_hydrate(target) {
|
|
|
50
52
|
let children = /** @type {ArrayLike<NodeEx2>} */ (target.childNodes);
|
|
51
53
|
// If target is <head>, there may be children without claim_order
|
|
52
54
|
if (target.nodeName === 'HEAD') {
|
|
53
|
-
const
|
|
55
|
+
const my_children = [];
|
|
54
56
|
for (let i = 0; i < children.length; i++) {
|
|
55
57
|
const node = children[i];
|
|
56
58
|
if (node.claim_order !== undefined) {
|
|
57
|
-
|
|
59
|
+
my_children.push(node);
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
|
-
children =
|
|
62
|
+
children = my_children;
|
|
61
63
|
}
|
|
62
64
|
/*
|
|
63
65
|
* Reorder claimed children optimally.
|
|
@@ -87,15 +89,15 @@ function init_hydrate(target) {
|
|
|
87
89
|
// Find the largest subsequence length such that it ends in a value less than our current value
|
|
88
90
|
// upper_bound returns first greater value, so we subtract one
|
|
89
91
|
// with fast path for when we are on the current longest subsequence
|
|
90
|
-
const
|
|
92
|
+
const seq_len =
|
|
91
93
|
(longest > 0 && children[m[longest]].claim_order <= current
|
|
92
94
|
? longest + 1
|
|
93
95
|
: upper_bound(1, longest, (idx) => children[m[idx]].claim_order, current)) - 1;
|
|
94
|
-
p[i] = m[
|
|
95
|
-
const
|
|
96
|
+
p[i] = m[seq_len] + 1;
|
|
97
|
+
const new_len = seq_len + 1;
|
|
96
98
|
// We can guarantee that current is the smallest value. Otherwise, we would have generated a longer sequence.
|
|
97
|
-
m[
|
|
98
|
-
longest = Math.max(
|
|
99
|
+
m[new_len] = i;
|
|
100
|
+
longest = Math.max(new_len, longest);
|
|
99
101
|
}
|
|
100
102
|
// The longest increasing subsequence of nodes (initially reversed)
|
|
101
103
|
|
|
@@ -108,28 +110,28 @@ function init_hydrate(target) {
|
|
|
108
110
|
/**
|
|
109
111
|
* @type {NodeEx2[]}
|
|
110
112
|
*/
|
|
111
|
-
const
|
|
113
|
+
const to_move = [];
|
|
112
114
|
let last = children.length - 1;
|
|
113
115
|
for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {
|
|
114
116
|
lis.push(children[cur - 1]);
|
|
115
117
|
for (; last >= cur; last--) {
|
|
116
|
-
|
|
118
|
+
to_move.push(children[last]);
|
|
117
119
|
}
|
|
118
120
|
last--;
|
|
119
121
|
}
|
|
120
122
|
for (; last >= 0; last--) {
|
|
121
|
-
|
|
123
|
+
to_move.push(children[last]);
|
|
122
124
|
}
|
|
123
125
|
lis.reverse();
|
|
124
126
|
// We sort the nodes being moved to guarantee that their insertion order matches the claim order
|
|
125
|
-
|
|
127
|
+
to_move.sort((a, b) => a.claim_order - b.claim_order);
|
|
126
128
|
// Finally, we move the nodes
|
|
127
|
-
for (let i = 0, j = 0; i <
|
|
128
|
-
while (j < lis.length &&
|
|
129
|
+
for (let i = 0, j = 0; i < to_move.length; i++) {
|
|
130
|
+
while (j < lis.length && to_move[i].claim_order >= lis[j].claim_order) {
|
|
129
131
|
j++;
|
|
130
132
|
}
|
|
131
133
|
const anchor = j < lis.length ? lis[j] : null;
|
|
132
|
-
target.insertBefore(
|
|
134
|
+
target.insertBefore(to_move[i], anchor);
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -624,26 +626,26 @@ function init_claim_info(nodes) {
|
|
|
624
626
|
* @template {ChildNodeEx} R
|
|
625
627
|
* @param {ChildNodeArray} nodes
|
|
626
628
|
* @param {(node: ChildNodeEx) => node is R} predicate
|
|
627
|
-
* @param {(node: ChildNodeEx) => ChildNodeEx | undefined}
|
|
628
|
-
* @param {() => R}
|
|
629
|
-
* @param {boolean}
|
|
629
|
+
* @param {(node: ChildNodeEx) => ChildNodeEx | undefined} process_node
|
|
630
|
+
* @param {() => R} create_node
|
|
631
|
+
* @param {boolean} dont_update_last_index
|
|
630
632
|
* @returns {R}
|
|
631
633
|
*/
|
|
632
|
-
function claim_node(nodes, predicate,
|
|
634
|
+
function claim_node(nodes, predicate, process_node, create_node, dont_update_last_index = false) {
|
|
633
635
|
// Try to find nodes in an order such that we lengthen the longest increasing subsequence
|
|
634
636
|
init_claim_info(nodes);
|
|
635
|
-
const
|
|
637
|
+
const result_node = (() => {
|
|
636
638
|
// We first try to find an element after the previous one
|
|
637
639
|
for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {
|
|
638
640
|
const node = nodes[i];
|
|
639
641
|
if (predicate(node)) {
|
|
640
|
-
const replacement =
|
|
642
|
+
const replacement = process_node(node);
|
|
641
643
|
if (replacement === undefined) {
|
|
642
644
|
nodes.splice(i, 1);
|
|
643
645
|
} else {
|
|
644
646
|
nodes[i] = replacement;
|
|
645
647
|
}
|
|
646
|
-
if (!
|
|
648
|
+
if (!dont_update_last_index) {
|
|
647
649
|
nodes.claim_info.last_index = i;
|
|
648
650
|
}
|
|
649
651
|
return node;
|
|
@@ -654,13 +656,13 @@ function claim_node(nodes, predicate, processNode, createNode, dontUpdateLastInd
|
|
|
654
656
|
for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {
|
|
655
657
|
const node = nodes[i];
|
|
656
658
|
if (predicate(node)) {
|
|
657
|
-
const replacement =
|
|
659
|
+
const replacement = process_node(node);
|
|
658
660
|
if (replacement === undefined) {
|
|
659
661
|
nodes.splice(i, 1);
|
|
660
662
|
} else {
|
|
661
663
|
nodes[i] = replacement;
|
|
662
664
|
}
|
|
663
|
-
if (!
|
|
665
|
+
if (!dont_update_last_index) {
|
|
664
666
|
nodes.claim_info.last_index = i;
|
|
665
667
|
} else if (replacement === undefined) {
|
|
666
668
|
// Since we spliced before the last_index, we decrease it
|
|
@@ -670,11 +672,11 @@ function claim_node(nodes, predicate, processNode, createNode, dontUpdateLastInd
|
|
|
670
672
|
}
|
|
671
673
|
}
|
|
672
674
|
// If we can't find any matching node, we create a new one
|
|
673
|
-
return
|
|
675
|
+
return create_node();
|
|
674
676
|
})();
|
|
675
|
-
|
|
677
|
+
result_node.claim_order = nodes.claim_info.total_claimed;
|
|
676
678
|
nodes.claim_info.total_claimed += 1;
|
|
677
|
-
return
|
|
679
|
+
return result_node;
|
|
678
680
|
}
|
|
679
681
|
|
|
680
682
|
/**
|
|
@@ -736,13 +738,13 @@ export function claim_text(nodes, data) {
|
|
|
736
738
|
(node) => node.nodeType === 3,
|
|
737
739
|
/** @param {Text} node */
|
|
738
740
|
(node) => {
|
|
739
|
-
const
|
|
740
|
-
if (node.data.startsWith(
|
|
741
|
-
if (node.data.length !==
|
|
742
|
-
return node.splitText(
|
|
741
|
+
const data_str = '' + data;
|
|
742
|
+
if (node.data.startsWith(data_str)) {
|
|
743
|
+
if (node.data.length !== data_str.length) {
|
|
744
|
+
return node.splitText(data_str.length);
|
|
743
745
|
}
|
|
744
746
|
} else {
|
|
745
|
-
node.data =
|
|
747
|
+
node.data = data_str;
|
|
746
748
|
}
|
|
747
749
|
},
|
|
748
750
|
() => text(data),
|
package/src/shared/version.js
CHANGED