rusteerio 1.0.1 → 1.1.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/Cargo.lock +42 -1
- package/Cargo.toml +8 -1
- package/README.md +90 -51
- package/THIRD_PARTY_NOTICES.md +107 -2
- package/dist/{chunk-DMRD3FGC.mjs → chunk-FPRP6UIX.mjs} +2233 -751
- package/dist/chunk-FPRP6UIX.mjs.map +1 -0
- package/dist/index.cjs +2232 -750
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/slim.cjs +2226 -745
- package/dist/slim.cjs.map +1 -1
- package/dist/slim.d.mts +2 -2
- package/dist/slim.d.ts +2 -2
- package/dist/slim.mjs +1 -1
- package/dist/{types-BP6TpxE5.d.mts → types-Cs9UP1Vv.d.mts} +3 -3
- package/dist/{types-BP6TpxE5.d.ts → types-Cs9UP1Vv.d.ts} +3 -3
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/native/src/arena.rs +219 -80
- package/native/src/attributes.rs +11 -5
- package/native/src/document_order.rs +711 -0
- package/native/src/extraction.rs +15 -3
- package/native/src/gc.rs +12 -3
- package/native/src/id_hash.rs +42 -0
- package/native/src/immutable.rs +256 -0
- package/native/src/lib.rs +1039 -171
- package/native/src/runtime.rs +189 -33
- package/native/src/selector.rs +346 -44
- package/native/src/sink.rs +14 -1
- package/native/src/snapshot.rs +527 -0
- package/native/src/stream.rs +2 -2
- package/native/src/tokenizer.rs +29 -12
- package/native/vendor/html5ever-0.35.0/src/tokenizer/char_ref/mod.rs +79 -0
- package/package.json +3 -1
- package/rusteerio.darwin-arm64.node +0 -0
- package/rusteerio.darwin-x64.node +0 -0
- package/rusteerio.linux-arm64-gnu.node +0 -0
- package/rusteerio.linux-arm64-musl.node +0 -0
- package/rusteerio.linux-x64-gnu.node +0 -0
- package/rusteerio.linux-x64-musl.node +0 -0
- package/rusteerio.win32-arm64-msvc.node +0 -0
- package/rusteerio.win32-x64-msvc.node +0 -0
- package/src/attributes.ts +78 -44
- package/src/codec.ts +22 -3
- package/src/extract.ts +86 -2
- package/src/hooks.ts +148 -2
- package/src/index.ts +51 -40
- package/src/match.ts +207 -0
- package/src/native.ts +9 -1
- package/src/nodes.ts +531 -183
- package/src/router.ts +792 -229
- package/src/selection.ts +239 -125
- package/src/snapshot.ts +255 -0
- package/src/transport.ts +51 -42
- package/dist/chunk-DMRD3FGC.mjs.map +0 -1
|
@@ -52,17 +52,30 @@ function decodeString(value) {
|
|
|
52
52
|
}
|
|
53
53
|
return start === 0 ? value : parts.join("") + value.slice(start);
|
|
54
54
|
}
|
|
55
|
-
var stringToken = /"(?:[^"\\]|\\[\s\S])*"/g;
|
|
56
55
|
var encodeJsonCandidate = /[\ud800-\ue800]|\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
|
|
57
56
|
var escapedJsonCandidate = /\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
|
|
58
57
|
var decodeJsonCandidate = /[\ue000-\ue800]|\\ue[0-8][\da-f]{2}/i;
|
|
59
58
|
function encodeJson(value) {
|
|
60
59
|
if (!encodeJsonCandidate.test(value)) return value;
|
|
61
60
|
if (isWellFormed?.call(value) && !encoded.test(value) && !escapedJsonCandidate.test(value)) return value;
|
|
62
|
-
return value
|
|
61
|
+
return mapJsonStrings(value, encodeString);
|
|
63
62
|
}
|
|
64
63
|
function decodeJson(value) {
|
|
65
|
-
return decodeJsonCandidate.test(value) ? value
|
|
64
|
+
return decodeJsonCandidate.test(value) ? mapJsonStrings(value, decodeString) : value;
|
|
65
|
+
}
|
|
66
|
+
function mapJsonStrings(json, transform) {
|
|
67
|
+
const parts = [];
|
|
68
|
+
let copied = 0;
|
|
69
|
+
let quote = json.indexOf('"');
|
|
70
|
+
while (quote !== -1) {
|
|
71
|
+
let end = quote + 1;
|
|
72
|
+
while (end < json.length && json.charCodeAt(end) !== 34) end += json.charCodeAt(end) === 92 ? 2 : 1;
|
|
73
|
+
if (end >= json.length) break;
|
|
74
|
+
parts.push(json.slice(copied, quote), JSON.stringify(transform(JSON.parse(json.slice(quote, end + 1)))));
|
|
75
|
+
copied = end + 1;
|
|
76
|
+
quote = json.indexOf('"', copied);
|
|
77
|
+
}
|
|
78
|
+
return copied === 0 ? json : parts.join("") + json.slice(copied);
|
|
66
79
|
}
|
|
67
80
|
function encodeOptions(value) {
|
|
68
81
|
if (value === void 0) return '{"__utf16Codec":true}';
|
|
@@ -74,12 +87,39 @@ function encodeOptions(value) {
|
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
// src/transport.ts
|
|
77
|
-
var registryKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.
|
|
90
|
+
var registryKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.v2");
|
|
78
91
|
var globals = globalThis;
|
|
79
|
-
var registry = globals[registryKey] ??= {
|
|
92
|
+
var registry = globals[registryKey] ??= { userErrors: /* @__PURE__ */ new WeakSet() };
|
|
93
|
+
var transportedKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.prototype");
|
|
94
|
+
var jsonMethods = /* @__PURE__ */ new Set(["op", "node", "exportTree", "parserDiagnostics", "adopt"]);
|
|
95
|
+
var argumentEncoders = {
|
|
96
|
+
op: (args) => {
|
|
97
|
+
args[1] = encodeJson(args[1]);
|
|
98
|
+
},
|
|
99
|
+
create: (args) => {
|
|
100
|
+
args[0] = encodeString(args[0]);
|
|
101
|
+
if (typeof args[2] === "string") args[2] = encodeOptions(args[2]);
|
|
102
|
+
},
|
|
103
|
+
select: (args) => {
|
|
104
|
+
args[0] = encodeString(args[0]);
|
|
105
|
+
},
|
|
106
|
+
matches: (args) => {
|
|
107
|
+
args[0] = encodeString(args[0]);
|
|
108
|
+
},
|
|
109
|
+
attr: (args) => {
|
|
110
|
+
args[1] = encodeString(args[1]);
|
|
111
|
+
},
|
|
112
|
+
setAttribute: (args) => {
|
|
113
|
+
args[1] = encodeString(args[1]);
|
|
114
|
+
if (typeof args[2] === "string") args[2] = encodeString(args[2]);
|
|
115
|
+
},
|
|
116
|
+
render: (args) => {
|
|
117
|
+
if (typeof args[1] === "string") args[1] = encodeJson(args[1]);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
80
120
|
function wrapNativeBinding(binding) {
|
|
81
121
|
const raw = binding;
|
|
82
|
-
const {
|
|
122
|
+
const { userErrors } = registry;
|
|
83
123
|
const restoreError = (error) => {
|
|
84
124
|
if (error instanceof Error && !userErrors.has(error)) {
|
|
85
125
|
const message = decodeString(error.message);
|
|
@@ -107,41 +147,33 @@ function wrapNativeBinding(binding) {
|
|
|
107
147
|
throw error;
|
|
108
148
|
}
|
|
109
149
|
};
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
if (typeof
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (typeof args[2] === "string") args[2] = encodeOptions(args[2]);
|
|
127
|
-
} else if (property2 === "select" || property2 === "matches") args[0] = encodeString(args[0]);
|
|
128
|
-
else if (property2 === "attr") args[1] = encodeString(args[1]);
|
|
129
|
-
else if (property2 === "adopt") args[0] = originals.get(args[0]) ?? args[0];
|
|
130
|
-
const result = Reflect.apply(value, target, args);
|
|
131
|
-
if (property2 === "op" && args[0] === "serialize" && typeof result === "string" && result.startsWith("{")) {
|
|
132
|
-
const error = JSON.parse(result).__nativeError;
|
|
133
|
-
if (error?.name === "URIError") throw new URIError(error.message);
|
|
134
|
-
}
|
|
135
|
-
return typeof result === "string" ? jsonMethods.has(String(property2)) ? decodeJson(result) : decodeString(result) : result;
|
|
136
|
-
});
|
|
137
|
-
methods.set(property2, method);
|
|
138
|
-
return method;
|
|
150
|
+
const transportMethod = (name, method) => {
|
|
151
|
+
const encodeArguments = argumentEncoders[name];
|
|
152
|
+
const decode = jsonMethods.has(name) ? decodeJson : decodeString;
|
|
153
|
+
const isOperation = name === "op";
|
|
154
|
+
return function transported(...args) {
|
|
155
|
+
try {
|
|
156
|
+
if (encodeArguments) encodeArguments(args);
|
|
157
|
+
const result = method.apply(this, args);
|
|
158
|
+
if (typeof result !== "string") return result;
|
|
159
|
+
if (isOperation && args[0] === "serialize" && result.startsWith("{")) {
|
|
160
|
+
const error = JSON.parse(result).__nativeError;
|
|
161
|
+
if (error?.name === "URIError") throw new URIError(error.message);
|
|
162
|
+
}
|
|
163
|
+
return decode(result);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
return restoreError(error);
|
|
139
166
|
}
|
|
140
|
-
}
|
|
141
|
-
documents.set(document, wrapped2);
|
|
142
|
-
originals.set(wrapped2, document);
|
|
143
|
-
return wrapped2;
|
|
167
|
+
};
|
|
144
168
|
};
|
|
169
|
+
const prototype = raw.NativeDocument.prototype;
|
|
170
|
+
if (!Object.hasOwn(prototype, transportedKey)) {
|
|
171
|
+
for (const name of Object.getOwnPropertyNames(prototype)) {
|
|
172
|
+
const method = prototype[name];
|
|
173
|
+
if (name !== "constructor" && typeof method === "function") prototype[name] = transportMethod(name, method);
|
|
174
|
+
}
|
|
175
|
+
Object.defineProperty(prototype, transportedKey, { value: true });
|
|
176
|
+
}
|
|
145
177
|
const wrapStream = (stream) => {
|
|
146
178
|
let carry = "";
|
|
147
179
|
return {
|
|
@@ -161,7 +193,7 @@ function wrapNativeBinding(binding) {
|
|
|
161
193
|
carry = "";
|
|
162
194
|
await invoke(() => stream.write(encodeString(final)));
|
|
163
195
|
}
|
|
164
|
-
return
|
|
196
|
+
return invoke(() => stream.finish());
|
|
165
197
|
},
|
|
166
198
|
abort() {
|
|
167
199
|
carry = "";
|
|
@@ -175,12 +207,19 @@ function wrapNativeBinding(binding) {
|
|
|
175
207
|
}
|
|
176
208
|
});
|
|
177
209
|
const wrapped = { ...raw };
|
|
178
|
-
|
|
210
|
+
const Document2 = raw.NativeDocument;
|
|
211
|
+
wrapped.NativeDocument = function NativeDocument(html, isDocument2, options) {
|
|
212
|
+
try {
|
|
213
|
+
return new Document2(encodeString(html), isDocument2, encodeOptions(options));
|
|
214
|
+
} catch (error) {
|
|
215
|
+
return restoreError(error);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
179
218
|
if (raw.NativeStream) wrapped.NativeStream = wrapConstructor(raw.NativeStream, ([options, isDocument2, bridge]) => [encodeOptions(options), isDocument2, bridge && wrapBridge(bridge)], wrapStream);
|
|
180
219
|
if (raw.NativeHookStream) wrapped.NativeHookStream = wrapConstructor(raw.NativeHookStream, ([isDocument2, options, bridge]) => [isDocument2, encodeOptions(options), wrapBridge(bridge)], wrapStream);
|
|
181
|
-
if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) =>
|
|
182
|
-
if (raw.parseAsync) wrapped.parseAsync =
|
|
183
|
-
if (raw.parseManyAsync) wrapped.parseManyAsync =
|
|
220
|
+
if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) => invoke(() => raw.parseWithTreeAdapter(encodeString(source), isDocument2, encodeOptions(options), wrapBridge(bridge)));
|
|
221
|
+
if (raw.parseAsync) wrapped.parseAsync = (source, isDocument2, options) => invoke(() => raw.parseAsync(encodeString(source), isDocument2, encodeOptions(options)));
|
|
222
|
+
if (raw.parseManyAsync) wrapped.parseManyAsync = (sources, isDocument2, threads, options) => invoke(() => raw.parseManyAsync(sources.map(encodeString), isDocument2, threads, encodeOptions(options)));
|
|
184
223
|
if (raw.extractPlanManyAsync) wrapped.extractPlanManyAsync = async (sources, plan, threads, options) => decodeJson(await invoke(() => raw.extractPlanManyAsync(sources.map(encodeString), encodeJson(plan), threads, encodeOptions(options))));
|
|
185
224
|
if (raw.extractManyAsync) wrapped.extractManyAsync = async (sources, queries, threads, isDocument2, options) => decodeJson(await invoke(() => raw.extractManyAsync(sources.map(encodeString), queries.map((query) => ({ ...query, key: encodeString(query.key), selector: encodeString(query.selector), ...query.attr === void 0 ? {} : { attr: encodeString(query.attr) } })), threads, isDocument2, encodeOptions(options))));
|
|
186
225
|
return wrapped;
|
|
@@ -190,10 +229,13 @@ function wrapNativeBinding(binding) {
|
|
|
190
229
|
var cached;
|
|
191
230
|
var attempted = false;
|
|
192
231
|
var bindingError;
|
|
232
|
+
function packageDirectory() {
|
|
233
|
+
return typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
234
|
+
}
|
|
193
235
|
function nativeBinding() {
|
|
194
236
|
if (attempted) return cached;
|
|
195
237
|
attempted = true;
|
|
196
|
-
const moduleDirectory =
|
|
238
|
+
const moduleDirectory = packageDirectory();
|
|
197
239
|
const require2 = createRequire(join(moduleDirectory, "rusteerio-loader.cjs"));
|
|
198
240
|
const directories = [moduleDirectory, dirname(moduleDirectory)];
|
|
199
241
|
const libc = process.platform === "linux" ? process.report?.getReport()?.header?.glibcVersionRuntime ? "gnu" : "musl" : void 0;
|
|
@@ -346,8 +388,8 @@ function treeAdapterBridge(adapter, options) {
|
|
|
346
388
|
const doctype = invoke("isDocumentTypeNode", [node]);
|
|
347
389
|
const name = element ? invoke("getTagName", [node]) : doctype ? "!doctype" : node.name;
|
|
348
390
|
const type = element ? name === "script" || name === "style" ? name : "tag" : text ? "text" : comment ? "comment" : doctype ? "directive" : node.type ?? "root";
|
|
349
|
-
const
|
|
350
|
-
const record = { id, type, children: Array.from(
|
|
391
|
+
const children = element || type === "root" || type === "cdata" ? invoke("getChildNodes", [node]) ?? [] : [];
|
|
392
|
+
const record = { id, type, children: Array.from(children, identify), parent: identify(invoke("getParentNode", [node])) };
|
|
351
393
|
if (name !== void 0) record.name = name;
|
|
352
394
|
if (element) {
|
|
353
395
|
record.namespace = invoke("getNamespaceURI", [node]);
|
|
@@ -449,11 +491,19 @@ function createTreeAdapterSession(options, isDocument2) {
|
|
|
449
491
|
function parseNativeDocument(source, options, isDocument2) {
|
|
450
492
|
const binding = requireNative();
|
|
451
493
|
const nativeOptions = parserOptions(source, options);
|
|
494
|
+
if (!options._useHtmlParser2 && options.treeAdapter && canReplay(options)) {
|
|
495
|
+
const document2 = routeDocument(new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions)), options);
|
|
496
|
+
const nodes = replayIntoAdapter(document2, options.treeAdapter, isDocument2);
|
|
497
|
+
if (nodes) {
|
|
498
|
+
attachParsedNodes(document2.state, nodes);
|
|
499
|
+
return document2;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
452
502
|
if (!options._useHtmlParser2 && options.treeAdapter) {
|
|
453
|
-
const
|
|
454
|
-
if (!
|
|
503
|
+
const parse3 = binding.parseWithTreeAdapter;
|
|
504
|
+
if (!parse3) throw new Error("This native addon does not support treeAdapter hooks; rebuild the Rust addon.");
|
|
455
505
|
const adapter = treeAdapterBridge(options.treeAdapter, options);
|
|
456
|
-
return bindAdapterDocument(
|
|
506
|
+
return bindAdapterDocument(parse3(source, isDocument2, JSON.stringify(nativeOptions), adapter.bridge), options, adapter);
|
|
457
507
|
}
|
|
458
508
|
const document = new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions));
|
|
459
509
|
deliverParseErrors(document, options);
|
|
@@ -506,205 +556,833 @@ function createDiagnosticSession(options, isDocument2 = true) {
|
|
|
506
556
|
}
|
|
507
557
|
};
|
|
508
558
|
}
|
|
559
|
+
function canReplay(options) {
|
|
560
|
+
const adapter = options.treeAdapter;
|
|
561
|
+
return !options.onParseError && !options.sourceCodeLocationInfo && adapter.onItemPush === void 0 && adapter.onItemPop === void 0;
|
|
562
|
+
}
|
|
563
|
+
function replayIntoAdapter(document, adapter, isDocument2) {
|
|
564
|
+
const state = document.state;
|
|
565
|
+
const root = document.rootId() - state.base;
|
|
566
|
+
const size = state.baseline;
|
|
567
|
+
const nodes = new Array(size);
|
|
568
|
+
for (let local = 0; local < Math.min(size, 65); local++) recordAt(state, local);
|
|
569
|
+
for (let local = 0; local < size; local++) {
|
|
570
|
+
const snapshot = plainSnapshot(state, local);
|
|
571
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
572
|
+
if (!snapshot && !record) continue;
|
|
573
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
574
|
+
if (local === root) {
|
|
575
|
+
nodes[local] = isDocument2 ? adapter.createDocument() : adapter.createDocumentFragment();
|
|
576
|
+
const mode = record?.["x-mode"];
|
|
577
|
+
if (isDocument2 && mode !== void 0) adapter.setDocumentMode(nodes[local], mode);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const parentLocal = snapshot ? snapshot.linkOf(local, 1) : record.parent;
|
|
581
|
+
const parent = parentLocal == null ? void 0 : nodes[parentLocal];
|
|
582
|
+
if (parent === void 0) return void 0;
|
|
583
|
+
switch (type) {
|
|
584
|
+
case "tag":
|
|
585
|
+
case "script":
|
|
586
|
+
case "style": {
|
|
587
|
+
const element = snapshot ? adapter.createElement(snapshot.nameOf(local), snapshot.namespaceOf(local), snapshot.attributeObjects(local)) : adapter.createElement(record.name, record.namespace, attributeList(record));
|
|
588
|
+
adapter.appendChild(parent, element);
|
|
589
|
+
nodes[local] = element;
|
|
590
|
+
break;
|
|
591
|
+
}
|
|
592
|
+
case "root": {
|
|
593
|
+
const content = adapter.createDocumentFragment();
|
|
594
|
+
adapter.setTemplateContent(parent, content);
|
|
595
|
+
nodes[local] = content;
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
case "text": {
|
|
599
|
+
adapter.insertText(parent, (snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
600
|
+
const children = adapter.getChildNodes(parent);
|
|
601
|
+
nodes[local] = children[children.length - 1];
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
case "comment": {
|
|
605
|
+
const comment = adapter.createCommentNode((snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
606
|
+
adapter.appendChild(parent, comment);
|
|
607
|
+
nodes[local] = comment;
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
case "directive": {
|
|
611
|
+
if (!record || record.name !== "!doctype" || !isDocument2) return void 0;
|
|
612
|
+
adapter.setDocumentType(parent, record["x-name"] ?? "", record["x-publicId"] ?? "", record["x-systemId"] ?? "");
|
|
613
|
+
nodes[local] = Array.from(adapter.getChildNodes(parent) ?? []).find((child) => adapter.isDocumentTypeNode(child));
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
default:
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const changes = differencesFromParse(adapter, nodes, state, root);
|
|
621
|
+
if (!changes) return void 0;
|
|
622
|
+
for (const change of changes) operation(document, "setNode", { id: state.base + change.local, field: change.field, value: change.value });
|
|
623
|
+
return nodes;
|
|
624
|
+
}
|
|
625
|
+
function attributeList(record) {
|
|
626
|
+
const attributes = record.attribs ?? {};
|
|
627
|
+
return Object.keys(attributes).map((name) => {
|
|
628
|
+
const namespace = record.attribsNamespace?.[name];
|
|
629
|
+
const prefix = record.attribsPrefix?.[name];
|
|
630
|
+
return { name, value: attributes[name], ...namespace === void 0 ? {} : { namespace }, ...prefix === void 0 ? {} : { prefix } };
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
function differencesFromParse(adapter, nodes, state, root) {
|
|
634
|
+
const changes = [];
|
|
635
|
+
for (let local = 0; local < nodes.length; local++) {
|
|
636
|
+
const node = nodes[local];
|
|
637
|
+
const snapshot = plainSnapshot(state, local);
|
|
638
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
639
|
+
if (!snapshot && !record) continue;
|
|
640
|
+
if (!node) return void 0;
|
|
641
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
642
|
+
if (local !== root && adapter.getParentNode(node) !== nodes[snapshot ? snapshot.linkOf(local, 1) : record.parent]) return void 0;
|
|
643
|
+
if (type !== "text" && type !== "comment" && type !== "directive") {
|
|
644
|
+
const children = adapter.getChildNodes(node) ?? [];
|
|
645
|
+
const count = snapshot ? snapshot.childCount(local) : record.children.length;
|
|
646
|
+
if (children.length !== count) return void 0;
|
|
647
|
+
for (let index = 0; index < count; index++) if (children[index] !== nodes[snapshot ? snapshot.childAt(local, index) : record.children[index]]) return void 0;
|
|
648
|
+
}
|
|
649
|
+
if (type === "tag" || type === "script" || type === "style") {
|
|
650
|
+
const name = snapshot ? snapshot.nameOf(local) : record.name;
|
|
651
|
+
const namespace = snapshot ? snapshot.namespaceOf(local) : record.namespace;
|
|
652
|
+
if (!adapter.isElementNode(node) || adapter.getTagName(node) !== name || adapter.getNamespaceURI(node) !== namespace) return void 0;
|
|
653
|
+
const attributes = adapter.getAttrList(node) ?? [];
|
|
654
|
+
const expected = snapshot ? snapshot.attributeObjects(local) : attributeList(record);
|
|
655
|
+
const isSame = attributes.length === expected.length && attributes.every((attribute, index) => attribute.name === expected[index].name && attribute.value === expected[index].value);
|
|
656
|
+
if (!isSame) {
|
|
657
|
+
const values = /* @__PURE__ */ Object.create(null);
|
|
658
|
+
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
659
|
+
const prefixes = /* @__PURE__ */ Object.create(null);
|
|
660
|
+
for (const attribute of attributes) {
|
|
661
|
+
values[attribute.name] = attribute.value;
|
|
662
|
+
if (attribute.namespace !== void 0) namespaces[attribute.name] = attribute.namespace;
|
|
663
|
+
if (attribute.prefix !== void 0) prefixes[attribute.name] = attribute.prefix;
|
|
664
|
+
}
|
|
665
|
+
changes.push({ local, field: "attribs", value: values }, { local, field: "attribsNamespace", value: namespaces }, { local, field: "attribsPrefix", value: prefixes });
|
|
666
|
+
}
|
|
667
|
+
} else if (type === "text" || type === "comment") {
|
|
668
|
+
if (type === "text" ? !adapter.isTextNode(node) : !adapter.isCommentNode(node)) return void 0;
|
|
669
|
+
const data2 = type === "text" ? adapter.getTextNodeContent(node) : adapter.getCommentNodeContent(node);
|
|
670
|
+
if (data2 !== (snapshot ? snapshot.dataOf(local) : record.data)) changes.push({ local, field: "data", value: data2 });
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return changes;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/snapshot.ts
|
|
677
|
+
var HEADER = 5;
|
|
678
|
+
var STRIDE = 15;
|
|
679
|
+
var ABSENT = 4294967295;
|
|
680
|
+
var HAS_START_INDEX = 1;
|
|
681
|
+
var HAS_END_INDEX = 2;
|
|
682
|
+
var HAS_NAMESPACE = 4;
|
|
683
|
+
var EMPTY_ATTRIBUTE_MAPS = 8;
|
|
684
|
+
var OPAQUE = 16;
|
|
685
|
+
var RELEASED = 32;
|
|
686
|
+
var noChildren = Object.freeze([]);
|
|
687
|
+
var noAttributes = Object.freeze({});
|
|
688
|
+
var SnapshotRecord = class {
|
|
689
|
+
constructor(snapshot, id, base) {
|
|
690
|
+
this.snapshot = snapshot;
|
|
691
|
+
this.id = id;
|
|
692
|
+
this.base = base;
|
|
693
|
+
this.decodedData = void 0;
|
|
694
|
+
this.decodedAttributes = void 0;
|
|
695
|
+
this.decodedChildren = void 0;
|
|
696
|
+
}
|
|
697
|
+
snapshot;
|
|
698
|
+
id;
|
|
699
|
+
base;
|
|
700
|
+
decodedData;
|
|
701
|
+
decodedAttributes;
|
|
702
|
+
decodedChildren;
|
|
703
|
+
get type() {
|
|
704
|
+
return this.snapshot.name(this.snapshot.nodes[this.base]);
|
|
705
|
+
}
|
|
706
|
+
get name() {
|
|
707
|
+
const name = this.snapshot.nodes[this.base + 6];
|
|
708
|
+
return name ? this.snapshot.name(name - 1) : void 0;
|
|
709
|
+
}
|
|
710
|
+
get data() {
|
|
711
|
+
if (this.decodedData !== void 0) return this.decodedData;
|
|
712
|
+
const data2 = this.snapshot.nodes[this.base + 7];
|
|
713
|
+
return data2 ? this.decodedData = this.snapshot.string(data2 - 1) : void 0;
|
|
714
|
+
}
|
|
715
|
+
get parent() {
|
|
716
|
+
const parent = this.snapshot.nodes[this.base + 1];
|
|
717
|
+
return parent ? parent - 1 : null;
|
|
718
|
+
}
|
|
719
|
+
get prev() {
|
|
720
|
+
const prev = this.snapshot.nodes[this.base + 2];
|
|
721
|
+
return prev ? prev - 1 : null;
|
|
722
|
+
}
|
|
723
|
+
get next() {
|
|
724
|
+
const next = this.snapshot.nodes[this.base + 3];
|
|
725
|
+
return next ? next - 1 : null;
|
|
726
|
+
}
|
|
727
|
+
get startIndex() {
|
|
728
|
+
return this.index(HAS_START_INDEX, 11);
|
|
729
|
+
}
|
|
730
|
+
get endIndex() {
|
|
731
|
+
return this.index(HAS_END_INDEX, 12);
|
|
732
|
+
}
|
|
733
|
+
get namespace() {
|
|
734
|
+
const nodes = this.snapshot.nodes;
|
|
735
|
+
return nodes[this.base + 10] & HAS_NAMESPACE ? this.snapshot.name(nodes[this.base + 13]) : void 0;
|
|
736
|
+
}
|
|
737
|
+
get attribsNamespace() {
|
|
738
|
+
return this.snapshot.nodes[this.base + 10] & EMPTY_ATTRIBUTE_MAPS ? {} : void 0;
|
|
739
|
+
}
|
|
740
|
+
get attribsPrefix() {
|
|
741
|
+
return this.snapshot.nodes[this.base + 10] & EMPTY_ATTRIBUTE_MAPS ? {} : void 0;
|
|
742
|
+
}
|
|
743
|
+
get attribs() {
|
|
744
|
+
return this.decodedAttributes ??= this.snapshot.attributesOf(this.id);
|
|
745
|
+
}
|
|
746
|
+
get children() {
|
|
747
|
+
return this.decodedChildren ??= this.snapshot.childrenOf(this.id);
|
|
748
|
+
}
|
|
749
|
+
index(flag, offset) {
|
|
750
|
+
const nodes = this.snapshot.nodes;
|
|
751
|
+
if (!(nodes[this.base + 10] & flag)) return void 0;
|
|
752
|
+
const value = nodes[this.base + offset];
|
|
753
|
+
return value === ABSENT ? null : value;
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
var recordFields = ["type", "name", "data", "parent", "prev", "next", "startIndex", "endIndex", "namespace", "attribsNamespace", "attribsPrefix", "attribs", "children"];
|
|
757
|
+
function plainRecord(record) {
|
|
758
|
+
if (!(record instanceof SnapshotRecord)) return record;
|
|
759
|
+
const copy = { id: record.id };
|
|
760
|
+
for (const field of recordFields) {
|
|
761
|
+
const value = record[field];
|
|
762
|
+
if (value !== void 0) copy[field] = value;
|
|
763
|
+
}
|
|
764
|
+
for (const key of Object.keys(record)) if (!key.startsWith("decoded") && key !== "snapshot" && key !== "base" && key !== "id") copy[key] = record[key];
|
|
765
|
+
return copy;
|
|
766
|
+
}
|
|
767
|
+
var NodeSnapshot = class {
|
|
768
|
+
size;
|
|
769
|
+
nodes;
|
|
770
|
+
children;
|
|
771
|
+
attributes;
|
|
772
|
+
strings;
|
|
773
|
+
text;
|
|
774
|
+
isEncoded;
|
|
775
|
+
names = [];
|
|
776
|
+
/** Node object constructors by interned type, resolved once per snapshot. */
|
|
777
|
+
viewConstructors = void 0;
|
|
778
|
+
constructor(raw) {
|
|
779
|
+
const { data: data2 } = raw;
|
|
780
|
+
const childrenStart = HEADER + data2[0];
|
|
781
|
+
const attributesStart = childrenStart + data2[1];
|
|
782
|
+
const stringsStart = attributesStart + data2[2];
|
|
783
|
+
this.text = raw.text;
|
|
784
|
+
this.isEncoded = data2[4] === 1;
|
|
785
|
+
this.nodes = data2.subarray(HEADER, childrenStart);
|
|
786
|
+
this.children = data2.subarray(childrenStart, attributesStart);
|
|
787
|
+
this.attributes = data2.subarray(attributesStart, stringsStart);
|
|
788
|
+
this.strings = data2.subarray(stringsStart, stringsStart + data2[3]);
|
|
789
|
+
this.size = this.nodes.length / STRIDE;
|
|
790
|
+
}
|
|
791
|
+
/** The record, `null` for a released node, or `undefined` when it must be read individually. */
|
|
792
|
+
record(local) {
|
|
793
|
+
if (local >= this.size) return void 0;
|
|
794
|
+
const base = local * STRIDE;
|
|
795
|
+
const flags = this.nodes[base + 10];
|
|
796
|
+
if (flags & RELEASED) return null;
|
|
797
|
+
if (flags & OPAQUE) return void 0;
|
|
798
|
+
const record = new SnapshotRecord(this, local, base);
|
|
799
|
+
const extras = this.nodes[base + 14];
|
|
800
|
+
if (extras) {
|
|
801
|
+
const fields = JSON.parse(this.string(extras - 1));
|
|
802
|
+
for (const key of Object.keys(fields)) Object.defineProperty(record, key, { value: fields[key], writable: true, enumerable: true, configurable: true });
|
|
803
|
+
}
|
|
804
|
+
return record;
|
|
805
|
+
}
|
|
806
|
+
/** Whether a node's fields all live in the arrays, so callers may read them without a record. */
|
|
807
|
+
isPlain(local) {
|
|
808
|
+
if (local >= this.size) return false;
|
|
809
|
+
const base = local * STRIDE;
|
|
810
|
+
return (this.nodes[base + 10] & (OPAQUE | RELEASED)) === 0 && this.nodes[base + 14] === 0;
|
|
811
|
+
}
|
|
812
|
+
typeOf(local) {
|
|
813
|
+
return this.name(this.nodes[local * STRIDE]);
|
|
814
|
+
}
|
|
815
|
+
nameOf(local) {
|
|
816
|
+
const name = this.nodes[local * STRIDE + 6];
|
|
817
|
+
return name ? this.name(name - 1) : void 0;
|
|
818
|
+
}
|
|
819
|
+
dataOf(local) {
|
|
820
|
+
const data2 = this.nodes[local * STRIDE + 7];
|
|
821
|
+
return data2 ? this.string(data2 - 1) : void 0;
|
|
822
|
+
}
|
|
823
|
+
/** The parent, previous or next sibling (`offset` 1, 2 or 3), or `null`. */
|
|
824
|
+
linkOf(local, offset) {
|
|
825
|
+
const link = this.nodes[local * STRIDE + offset];
|
|
826
|
+
return link ? link - 1 : null;
|
|
827
|
+
}
|
|
828
|
+
namespaceOf(local) {
|
|
829
|
+
const base = local * STRIDE;
|
|
830
|
+
return this.nodes[base + 10] & HAS_NAMESPACE ? this.name(this.nodes[base + 13]) : void 0;
|
|
831
|
+
}
|
|
832
|
+
/** A node's attributes as parse5 attribute objects; plain nodes have no namespaced ones. */
|
|
833
|
+
attributeObjects(local) {
|
|
834
|
+
const base = local * STRIDE;
|
|
835
|
+
const count = this.nodes[base + 9];
|
|
836
|
+
const first = this.nodes[base + 8];
|
|
837
|
+
const attributes = this.attributes;
|
|
838
|
+
const result = new Array(count);
|
|
839
|
+
for (let index = 0; index < count; index++) {
|
|
840
|
+
const pair = (first + index) * 2;
|
|
841
|
+
result[index] = { name: this.name(attributes[pair]), value: this.string(attributes[pair + 1]) };
|
|
842
|
+
}
|
|
843
|
+
return result;
|
|
844
|
+
}
|
|
845
|
+
/** Copies a node's attributes onto `target`, in order. */
|
|
846
|
+
copyAttributes(local, target) {
|
|
847
|
+
const base = local * STRIDE;
|
|
848
|
+
const count = this.nodes[base + 9];
|
|
849
|
+
const first = this.nodes[base + 8];
|
|
850
|
+
const attributes = this.attributes;
|
|
851
|
+
for (let index = 0; index < count; index++) {
|
|
852
|
+
const pair = (first + index) * 2;
|
|
853
|
+
const name = this.name(attributes[pair]);
|
|
854
|
+
const value = this.string(attributes[pair + 1]);
|
|
855
|
+
if (name === "__proto__") Object.defineProperty(target, name, { value, writable: true, enumerable: true, configurable: true });
|
|
856
|
+
else target[name] = value;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/** The flat child id list; a node's children start at `childStart(local)`. */
|
|
860
|
+
get childIds() {
|
|
861
|
+
return this.children;
|
|
862
|
+
}
|
|
863
|
+
childStart(local) {
|
|
864
|
+
return this.nodes[local * STRIDE + 4];
|
|
865
|
+
}
|
|
866
|
+
/** The interned reference of a node's type, comparable across nodes of this snapshot. */
|
|
867
|
+
typeReference(local) {
|
|
868
|
+
return this.nodes[local * STRIDE];
|
|
869
|
+
}
|
|
870
|
+
/** Child ids without materializing the record. */
|
|
871
|
+
childCount(local) {
|
|
872
|
+
return this.nodes[local * STRIDE + 5];
|
|
873
|
+
}
|
|
874
|
+
childAt(local, index) {
|
|
875
|
+
return this.children[this.nodes[local * STRIDE + 4] + index];
|
|
876
|
+
}
|
|
877
|
+
childrenOf(local) {
|
|
878
|
+
const base = local * STRIDE;
|
|
879
|
+
const count = this.nodes[base + 5];
|
|
880
|
+
if (count === 0) return noChildren;
|
|
881
|
+
const first = this.nodes[base + 4];
|
|
882
|
+
return Array.from(this.children.subarray(first, first + count));
|
|
883
|
+
}
|
|
884
|
+
attributesOf(local) {
|
|
885
|
+
const base = local * STRIDE;
|
|
886
|
+
const count = this.nodes[base + 9];
|
|
887
|
+
if (count === 0) return noAttributes;
|
|
888
|
+
const first = this.nodes[base + 8];
|
|
889
|
+
const attributes = this.attributes;
|
|
890
|
+
const result = {};
|
|
891
|
+
for (let index = 0; index < count; index++) {
|
|
892
|
+
const pair = (first + index) * 2;
|
|
893
|
+
const name = this.name(attributes[pair]);
|
|
894
|
+
const value = this.string(attributes[pair + 1]);
|
|
895
|
+
if (name === "__proto__") Object.defineProperty(result, name, { value, writable: true, enumerable: true, configurable: true });
|
|
896
|
+
else result[name] = value;
|
|
897
|
+
}
|
|
898
|
+
return result;
|
|
899
|
+
}
|
|
900
|
+
/** One attribute's value, without decoding the rest. */
|
|
901
|
+
attributeValue(local, name) {
|
|
902
|
+
const base = local * STRIDE;
|
|
903
|
+
const count = this.nodes[base + 9];
|
|
904
|
+
const first = this.nodes[base + 8];
|
|
905
|
+
const attributes = this.attributes;
|
|
906
|
+
for (let index = count - 1; index >= 0; index--) {
|
|
907
|
+
const pair = (first + index) * 2;
|
|
908
|
+
if (this.name(attributes[pair]) === name) return this.string(attributes[pair + 1]);
|
|
909
|
+
}
|
|
910
|
+
return void 0;
|
|
911
|
+
}
|
|
912
|
+
string(reference) {
|
|
913
|
+
const strings = this.strings;
|
|
914
|
+
const value = this.text.slice(strings[reference * 2], strings[reference * 2 + 1]);
|
|
915
|
+
return this.isEncoded ? decodeString(value) : value;
|
|
916
|
+
}
|
|
917
|
+
/** Names repeat across nodes, so each decodes once. */
|
|
918
|
+
name(reference) {
|
|
919
|
+
return this.names[reference] ??= this.string(reference);
|
|
920
|
+
}
|
|
921
|
+
};
|
|
509
922
|
|
|
510
923
|
// src/router.ts
|
|
511
|
-
var
|
|
924
|
+
var STRIDE2 = 2 ** 32;
|
|
925
|
+
var maximumDocuments = 2 ** 21;
|
|
926
|
+
var rootSlots = 1;
|
|
927
|
+
var VIEW_STATE = /* @__PURE__ */ Symbol.for("rusteerio.node.state");
|
|
928
|
+
var VIEW_LOCAL = /* @__PURE__ */ Symbol.for("rusteerio.node.local");
|
|
929
|
+
var VIEW_ATTRIBUTES = /* @__PURE__ */ Symbol.for("rusteerio.node.attributes");
|
|
930
|
+
var VIEW_SELF = /* @__PURE__ */ Symbol.for("rusteerio.node.self");
|
|
931
|
+
var DOCUMENT = /* @__PURE__ */ Symbol.for("rusteerio.selection.document");
|
|
932
|
+
var API = /* @__PURE__ */ Symbol.for("rusteerio.selection.api");
|
|
933
|
+
var IDS = /* @__PURE__ */ Symbol.for("rusteerio.selection.ids");
|
|
934
|
+
var VALUES = /* @__PURE__ */ Symbol.for("rusteerio.selection.values");
|
|
935
|
+
var LEASE = /* @__PURE__ */ Symbol.for("rusteerio.selection.lease");
|
|
936
|
+
var IS_PLAIN = /* @__PURE__ */ Symbol.for("rusteerio.selection.is-plain");
|
|
937
|
+
var VIEW_CHILD_TARGET = /* @__PURE__ */ Symbol.for("rusteerio.node.child-target");
|
|
938
|
+
var registryKey2 = /* @__PURE__ */ Symbol.for(`rusteerio.native-documents.v5:${packageDirectory()}`);
|
|
939
|
+
var stateKey = /* @__PURE__ */ Symbol.for("rusteerio.native-documents.state");
|
|
512
940
|
var globals2 = globalThis;
|
|
513
941
|
var registry2 = globals2[registryKey2] ??= (() => {
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const document = pin.document.deref();
|
|
524
|
-
if (!document) continue;
|
|
525
|
-
const entries = byDocument.get(document);
|
|
526
|
-
if (entries?.get(pin.local)?.pin === pin) entries.delete(pin.local);
|
|
527
|
-
const ids = batches.get(document) ?? [];
|
|
528
|
-
ids.push(pin.local);
|
|
529
|
-
batches.set(document, ids);
|
|
530
|
-
}
|
|
531
|
-
for (const [document, ids] of batches) {
|
|
532
|
-
snapshots.delete(document);
|
|
533
|
-
document.release?.(ids);
|
|
534
|
-
document.collectGarbage?.();
|
|
535
|
-
}
|
|
942
|
+
const created = {
|
|
943
|
+
space: {},
|
|
944
|
+
writes: 0,
|
|
945
|
+
states: [],
|
|
946
|
+
pending: /* @__PURE__ */ new Set(),
|
|
947
|
+
isScheduled: false,
|
|
948
|
+
leaseFinalizer: new FinalizationRegistry((token) => {
|
|
949
|
+
token.isReleased = true;
|
|
950
|
+
})
|
|
536
951
|
};
|
|
537
|
-
return
|
|
538
|
-
if (!handles.get(pin.global)?.deref()) handles.delete(pin.global);
|
|
539
|
-
pending.push(pin);
|
|
540
|
-
if (!scheduled) {
|
|
541
|
-
scheduled = true;
|
|
542
|
-
queueMicrotask(flush);
|
|
543
|
-
}
|
|
544
|
-
}) };
|
|
952
|
+
return created;
|
|
545
953
|
})();
|
|
954
|
+
function statesOf(document, ids) {
|
|
955
|
+
const states = [];
|
|
956
|
+
let previous;
|
|
957
|
+
for (const id of ids) {
|
|
958
|
+
if (id === void 0) continue;
|
|
959
|
+
if (previous && id >= previous.base && id < previous.base + STRIDE2) continue;
|
|
960
|
+
const state = stateIn(document, id);
|
|
961
|
+
if (!states.includes(state)) states.push(state);
|
|
962
|
+
previous = state;
|
|
963
|
+
}
|
|
964
|
+
return states;
|
|
965
|
+
}
|
|
966
|
+
function scheduleCollectionIfDue(state) {
|
|
967
|
+
if (state.raw.isCollectionDue?.()) scheduleCollection(state);
|
|
968
|
+
}
|
|
969
|
+
function scheduleCollection(state) {
|
|
970
|
+
registry2.pending.add(state);
|
|
971
|
+
if (registry2.pending.size > maximumPendingCollections) {
|
|
972
|
+
const evicted = registry2.pending.values().next().value;
|
|
973
|
+
registry2.pending.delete(evicted);
|
|
974
|
+
evicted.isCollectionEvicted = true;
|
|
975
|
+
}
|
|
976
|
+
if (registry2.isScheduled) return;
|
|
977
|
+
registry2.isScheduled = true;
|
|
978
|
+
setImmediate(() => {
|
|
979
|
+
registry2.isScheduled = false;
|
|
980
|
+
const states = [...registry2.pending];
|
|
981
|
+
registry2.pending.clear();
|
|
982
|
+
for (const pending of states) collectState(pending);
|
|
983
|
+
}).unref();
|
|
984
|
+
}
|
|
985
|
+
var maximumPendingCollections = 4;
|
|
986
|
+
function writeCount() {
|
|
987
|
+
return registry2.writes;
|
|
988
|
+
}
|
|
989
|
+
function stateFor(raw, options = {}) {
|
|
990
|
+
const holder = raw;
|
|
991
|
+
const existing = holder[stateKey];
|
|
992
|
+
if (existing) return existing;
|
|
993
|
+
const index = raw.routingIndex();
|
|
994
|
+
if (index >= maximumDocuments) throw new RangeError("Too many documents are alive at once.");
|
|
995
|
+
const baseline = raw.slotCount?.() ?? 0;
|
|
996
|
+
const state = {
|
|
997
|
+
raw,
|
|
998
|
+
base: index * STRIDE2,
|
|
999
|
+
space: registry2.space,
|
|
1000
|
+
options,
|
|
1001
|
+
rootLocal: void 0,
|
|
1002
|
+
routed: void 0,
|
|
1003
|
+
// Sized up front: node objects are cached out of order, and regrowing a holey array is costly.
|
|
1004
|
+
generation: 0,
|
|
1005
|
+
records: [],
|
|
1006
|
+
bulk: 0,
|
|
1007
|
+
snapshotSize: 0,
|
|
1008
|
+
stale: /* @__PURE__ */ new Set(),
|
|
1009
|
+
views: new Array(baseline),
|
|
1010
|
+
looseViews: /* @__PURE__ */ new Map(),
|
|
1011
|
+
looseViewLimit: minimumLooseViewLimit,
|
|
1012
|
+
weakViews: /* @__PURE__ */ new Map(),
|
|
1013
|
+
baseline,
|
|
1014
|
+
leases: /* @__PURE__ */ new Set(),
|
|
1015
|
+
leaseSweepSize: 64,
|
|
1016
|
+
data: /* @__PURE__ */ new Map(),
|
|
1017
|
+
isExposed: false,
|
|
1018
|
+
hasChildLists: false,
|
|
1019
|
+
collectionRetries: 0,
|
|
1020
|
+
isCollectionEvicted: false
|
|
1021
|
+
};
|
|
1022
|
+
holder[stateKey] = state;
|
|
1023
|
+
return state;
|
|
1024
|
+
}
|
|
1025
|
+
function exposeState(state) {
|
|
1026
|
+
if (state.isExposed) return;
|
|
1027
|
+
state.isExposed = true;
|
|
1028
|
+
registry2.states[state.base / STRIDE2] = new WeakRef(state);
|
|
1029
|
+
}
|
|
1030
|
+
function exposeTo(document, state) {
|
|
1031
|
+
if (document.state === state) return;
|
|
1032
|
+
exposeState(state);
|
|
1033
|
+
}
|
|
1034
|
+
function exposeDocumentTo(document, source) {
|
|
1035
|
+
const state = source?.state;
|
|
1036
|
+
if (state) exposeTo(document, state);
|
|
1037
|
+
}
|
|
1038
|
+
function cachedView(state, local) {
|
|
1039
|
+
const view = local < state.baseline ? state.views[local] : state.looseViews.get(local);
|
|
1040
|
+
return view ?? (state.weakViews.size ? state.weakViews.get(local)?.deref() : void 0);
|
|
1041
|
+
}
|
|
1042
|
+
var minimumLooseViewLimit = 1024;
|
|
1043
|
+
function cacheView(state, local, view) {
|
|
1044
|
+
if (local < state.baseline) {
|
|
1045
|
+
state.views[local] = view;
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
state.looseViews.set(local, view);
|
|
1049
|
+
if (state.looseViews.size >= state.looseViewLimit) {
|
|
1050
|
+
state.looseViewLimit = state.looseViews.size * 2;
|
|
1051
|
+
scheduleCollection(state);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
function uncacheView(state, local) {
|
|
1055
|
+
const view = cachedView(state, local);
|
|
1056
|
+
if (local < state.baseline) state.views[local] = void 0;
|
|
1057
|
+
state.looseViews.delete(local);
|
|
1058
|
+
state.weakViews.delete(local);
|
|
1059
|
+
return view;
|
|
1060
|
+
}
|
|
1061
|
+
function releaseSlotsFrom(state, end) {
|
|
1062
|
+
for (const local of state.data.keys()) if (local >= end) releaseSlot(state, local);
|
|
1063
|
+
for (const local of state.weakViews.keys()) if (local >= end) state.weakViews.delete(local);
|
|
1064
|
+
if (state.adapterNodes && state.adapterNodes.length > end) {
|
|
1065
|
+
for (let local = end; local < state.adapterNodes.length; local++) releaseAdapterNode(state, local);
|
|
1066
|
+
state.adapterNodes.length = end;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
function releaseSlot(state, local) {
|
|
1070
|
+
uncacheView(state, local);
|
|
1071
|
+
const entry = state.data.get(local);
|
|
1072
|
+
if (entry) {
|
|
1073
|
+
entry.isReleased = true;
|
|
1074
|
+
state.data.delete(local);
|
|
1075
|
+
}
|
|
1076
|
+
releaseAdapterNode(state, local);
|
|
1077
|
+
}
|
|
1078
|
+
function releaseAdapterNode(state, local) {
|
|
1079
|
+
const adapterNode = state.adapterNodes?.[local];
|
|
1080
|
+
if (!adapterNode) return;
|
|
1081
|
+
adapterNode[VIEW_SELF] = void 0;
|
|
1082
|
+
state.adapterNodes[local] = void 0;
|
|
1083
|
+
}
|
|
1084
|
+
function hasViews(state) {
|
|
1085
|
+
return state.views.length > 0 || state.looseViews.size > 0 || state.weakViews.size > 0;
|
|
1086
|
+
}
|
|
1087
|
+
function forEachView(state, visit) {
|
|
1088
|
+
state.views.forEach((view, local) => {
|
|
1089
|
+
if (view) visit(view, local);
|
|
1090
|
+
});
|
|
1091
|
+
for (const [local, view] of state.looseViews) visit(view, local);
|
|
1092
|
+
for (const [local, reference] of state.weakViews) {
|
|
1093
|
+
const view = reference.deref();
|
|
1094
|
+
if (view) visit(view, local);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
function weakenDetachedViews(state) {
|
|
1098
|
+
if (!state.raw.detachedSlots) return false;
|
|
1099
|
+
let isWeakened = false;
|
|
1100
|
+
for (const local of state.raw.detachedSlots(state.rootLocal ??= state.raw.rootId())) {
|
|
1101
|
+
const view = local < state.baseline ? state.views[local] : state.looseViews.get(local);
|
|
1102
|
+
if (!view) continue;
|
|
1103
|
+
if (local < state.baseline) state.views[local] = void 0;
|
|
1104
|
+
else state.looseViews.delete(local);
|
|
1105
|
+
state.weakViews.set(local, new WeakRef(view));
|
|
1106
|
+
isWeakened = true;
|
|
1107
|
+
}
|
|
1108
|
+
return isWeakened;
|
|
1109
|
+
}
|
|
1110
|
+
function exposedStateOf(id) {
|
|
1111
|
+
const state = registry2.states[Math.floor(id / STRIDE2)]?.deref();
|
|
1112
|
+
if (!state || !(id >= 0)) throw new RangeError(`Unknown native node handle ${id}`);
|
|
1113
|
+
return state;
|
|
1114
|
+
}
|
|
1115
|
+
function stateIn(document, id) {
|
|
1116
|
+
const own = document.state;
|
|
1117
|
+
if (own === void 0 || id < own.base || id >= own.base + STRIDE2) return exposedStateOf(id);
|
|
1118
|
+
if (own.isCollectionEvicted) resumeCollection(document);
|
|
1119
|
+
return own;
|
|
1120
|
+
}
|
|
1121
|
+
function resumeCollection(document) {
|
|
1122
|
+
const state = document.state;
|
|
1123
|
+
if (!state?.isCollectionEvicted) return;
|
|
1124
|
+
state.isCollectionEvicted = false;
|
|
1125
|
+
scheduleCollection(state);
|
|
1126
|
+
}
|
|
1127
|
+
function recordAt(state, local) {
|
|
1128
|
+
const cached2 = state.records[local];
|
|
1129
|
+
if (cached2 !== void 0) return cached2;
|
|
1130
|
+
const record = readRecord(state, local);
|
|
1131
|
+
state.records[local] = record;
|
|
1132
|
+
return record;
|
|
1133
|
+
}
|
|
1134
|
+
var minimumReadsBeforeSnapshot = 64;
|
|
1135
|
+
function readRecord(state, local) {
|
|
1136
|
+
const bulk = state.bulk;
|
|
1137
|
+
if (bulk instanceof NodeSnapshot) {
|
|
1138
|
+
const record = state.stale.size && state.stale.has(local) ? void 0 : bulk.record(local);
|
|
1139
|
+
if (record !== void 0) return record;
|
|
1140
|
+
} else if (state.raw.snapshot) {
|
|
1141
|
+
const reads = bulk + 1;
|
|
1142
|
+
const size = Math.max(state.snapshotSize, state.baseline);
|
|
1143
|
+
const firstSnapshotRead = state.generation === 0 ? size / 100 : 1 + size / 100;
|
|
1144
|
+
if (reads >= Math.min(minimumReadsBeforeSnapshot, firstSnapshotRead)) {
|
|
1145
|
+
const snapshot = new NodeSnapshot(state.raw.snapshot());
|
|
1146
|
+
state.snapshotSize = snapshot.size;
|
|
1147
|
+
state.bulk = snapshot;
|
|
1148
|
+
const record = snapshot.record(local);
|
|
1149
|
+
if (record !== void 0) return record;
|
|
1150
|
+
} else state.bulk = reads;
|
|
1151
|
+
}
|
|
1152
|
+
return rawOperation(state.raw, "node", { id: local });
|
|
1153
|
+
}
|
|
1154
|
+
function plainSnapshot(state, local) {
|
|
1155
|
+
const bulk = state.bulk;
|
|
1156
|
+
return bulk instanceof NodeSnapshot && !(state.stale.size && state.stale.has(local)) && bulk.isPlain(local) ? bulk : void 0;
|
|
1157
|
+
}
|
|
1158
|
+
function attributeAt(state, local, name) {
|
|
1159
|
+
const snapshot = plainSnapshot(state, local);
|
|
1160
|
+
if (snapshot) return snapshot.attributeValue(local, name);
|
|
1161
|
+
const attributes = recordAt(state, local)?.attribs;
|
|
1162
|
+
const value = attributes && Object.hasOwn(attributes, name) ? attributes[name] : void 0;
|
|
1163
|
+
return typeof value === "string" ? value : void 0;
|
|
1164
|
+
}
|
|
1165
|
+
function invalidate(state) {
|
|
1166
|
+
state.generation++;
|
|
1167
|
+
state.records = [];
|
|
1168
|
+
state.bulk = 0;
|
|
1169
|
+
state.stale.clear();
|
|
1170
|
+
}
|
|
1171
|
+
function invalidateNodes(state, locals) {
|
|
1172
|
+
const isSnapshot = state.bulk instanceof NodeSnapshot;
|
|
1173
|
+
for (const local of locals) {
|
|
1174
|
+
state.records[local] = void 0;
|
|
1175
|
+
if (isSnapshot) state.stale.add(local);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
function leaseNodes(document, owner, ids) {
|
|
1179
|
+
const token = { isReleased: false };
|
|
1180
|
+
const states = statesOf(document, ids);
|
|
1181
|
+
const lease = { ids, token, states };
|
|
1182
|
+
for (const state of states) addLease(state, lease);
|
|
1183
|
+
registry2.leaseFinalizer.register(owner, token);
|
|
1184
|
+
return lease;
|
|
1185
|
+
}
|
|
1186
|
+
function updateLease(document, lease, ids) {
|
|
1187
|
+
lease.ids = ids;
|
|
1188
|
+
lease.states = statesOf(document, ids);
|
|
1189
|
+
for (const state of lease.states) addLease(state, lease);
|
|
1190
|
+
}
|
|
1191
|
+
function addLease(state, lease) {
|
|
1192
|
+
state.leases.add(lease);
|
|
1193
|
+
if (state.leases.size < state.leaseSweepSize) return;
|
|
1194
|
+
for (const held of state.leases) if (held.token.isReleased) state.leases.delete(held);
|
|
1195
|
+
state.leaseSweepSize = state.leases.size * 2 + 64;
|
|
1196
|
+
}
|
|
1197
|
+
var collectionRetries = 3;
|
|
1198
|
+
function collectState(state) {
|
|
1199
|
+
registry2.pending.delete(state);
|
|
1200
|
+
state.isCollectionEvicted = false;
|
|
1201
|
+
if (!state.raw.collectPinned) return state.raw.collectGarbage?.();
|
|
1202
|
+
if (weakenDetachedViews(state)) state.collectionRetries = collectionRetries;
|
|
1203
|
+
const pins = [];
|
|
1204
|
+
const { base } = state;
|
|
1205
|
+
const end = base + STRIDE2;
|
|
1206
|
+
for (const lease of state.leases) {
|
|
1207
|
+
if (lease.token.isReleased) {
|
|
1208
|
+
state.leases.delete(lease);
|
|
1209
|
+
continue;
|
|
1210
|
+
}
|
|
1211
|
+
for (const id of lease.ids) if (id >= base && id < end) pins.push(id - base);
|
|
1212
|
+
}
|
|
1213
|
+
state.views.forEach((view, local) => {
|
|
1214
|
+
if (view) pins.push(local);
|
|
1215
|
+
});
|
|
1216
|
+
for (const local of state.looseViews.keys()) pins.push(local);
|
|
1217
|
+
for (const [local, reference] of state.weakViews) {
|
|
1218
|
+
if (reference.deref()) pins.push(local);
|
|
1219
|
+
else state.weakViews.delete(local);
|
|
1220
|
+
}
|
|
1221
|
+
const { free, ...stats } = state.raw.collectPinned(Uint32Array.from(pins), rootSlots);
|
|
1222
|
+
invalidate(state);
|
|
1223
|
+
for (const local of free) releaseSlot(state, local);
|
|
1224
|
+
releaseSlotsFrom(state, stats.slots);
|
|
1225
|
+
state.looseViewLimit = Math.max(minimumLooseViewLimit, state.looseViews.size * 2);
|
|
1226
|
+
if (state.collectionRetries > 0 && state.weakViews.size > 0) {
|
|
1227
|
+
state.collectionRetries--;
|
|
1228
|
+
scheduleCollection(state);
|
|
1229
|
+
}
|
|
1230
|
+
return stats;
|
|
1231
|
+
}
|
|
546
1232
|
function rawOperation(document, command, args) {
|
|
547
1233
|
const result = document.op(command, JSON.stringify(args));
|
|
548
1234
|
return result === "" || result === void 0 ? void 0 : JSON.parse(result);
|
|
549
1235
|
}
|
|
550
|
-
function
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
return handle;
|
|
568
|
-
}
|
|
569
|
-
function retainNodes(document, ids) {
|
|
570
|
-
return document.retainNodes?.(ids) ?? {};
|
|
571
|
-
}
|
|
572
|
-
var RoutedDocument = class _RoutedDocument {
|
|
1236
|
+
function globalRecord(state, record) {
|
|
1237
|
+
if (!record) return null;
|
|
1238
|
+
const { base } = state;
|
|
1239
|
+
const link = (local) => local == null ? null : base + local;
|
|
1240
|
+
return { ...plainRecord(record), id: base + record.id, children: (record.children ?? []).map((child) => base + child), parent: link(record.parent), prev: link(record.prev), next: link(record.next) };
|
|
1241
|
+
}
|
|
1242
|
+
var parentTypes = /* @__PURE__ */ new Set(["root", "tag", "script", "style", "cdata"]);
|
|
1243
|
+
var pointerFields = /* @__PURE__ */ new Set(["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"]);
|
|
1244
|
+
var idResultCommands = /* @__PURE__ */ new Set(["select", "matches", "uniqueSort", "traverse", "clone"]);
|
|
1245
|
+
var scratchCommands = /* @__PURE__ */ new Set(["select", "matches", "uniqueSort", "serializeArray", "serialize", "extractPlan"]);
|
|
1246
|
+
var writeCommands = /* @__PURE__ */ new Set(["create", "createNode", "setNode", "import", "insert", "clone", "remove", "removeAttr", "removeData", "addClass", "removeClass", "toggleClass"]);
|
|
1247
|
+
var attributeFields = /* @__PURE__ */ new Set(["attribs", "x-attribsNamespace", "x-attribsPrefix"]);
|
|
1248
|
+
var targetedAttributeWrites = /* @__PURE__ */ new Set(["attr", "removeAttr", "addClass", "removeClass", "toggleClass", "css"]);
|
|
1249
|
+
var recordOnlyWrites = /* @__PURE__ */ new Set([...targetedAttributeWrites, "data", "removeData"]);
|
|
1250
|
+
var structuralWrites = /* @__PURE__ */ new Set(["create", "createNode", "import", "insert", "clone", "remove", "html", "text", "data", "removeData"]);
|
|
1251
|
+
var RoutedDocument = class {
|
|
573
1252
|
nodeSpace = registry2.space;
|
|
574
1253
|
options;
|
|
575
|
-
|
|
1254
|
+
state;
|
|
576
1255
|
get raw() {
|
|
577
|
-
return this.
|
|
1256
|
+
return this.state.raw;
|
|
578
1257
|
}
|
|
579
|
-
constructor(document, options = {}
|
|
1258
|
+
constructor(document, options = {}) {
|
|
580
1259
|
this.options = options;
|
|
581
|
-
this.
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
1260
|
+
this.state = stateFor(document, options);
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Sets (or with `null` removes) an attribute, as the `attr` command does,
|
|
1264
|
+
* through a typed native call. Attribute objects already handed out are
|
|
1265
|
+
* updated in place instead of being read back.
|
|
1266
|
+
*/
|
|
1267
|
+
setAttribute(ids, name, value) {
|
|
1268
|
+
registry2.writes++;
|
|
1269
|
+
for (const { state, locals } of this.groups(ids)) {
|
|
1270
|
+
if (!state.raw.setAttribute) {
|
|
1271
|
+
this.call(state, "attr", { ids: locals, name, value });
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
invalidateNodes(state, locals);
|
|
1275
|
+
state.raw.setAttribute(locals, name, value);
|
|
1276
|
+
for (const local of locals) {
|
|
1277
|
+
const target = cachedView(state, local)?.[VIEW_ATTRIBUTES]?.target;
|
|
1278
|
+
if (!target) continue;
|
|
1279
|
+
if (value === null) delete target[name];
|
|
1280
|
+
else if (name === "__proto__") Object.defineProperty(target, name, { value, writable: true, enumerable: true, configurable: true });
|
|
1281
|
+
else target[name] = value;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
596
1284
|
}
|
|
597
1285
|
retainNode(id) {
|
|
598
|
-
this.
|
|
599
|
-
}
|
|
600
|
-
retainNodes(ids) {
|
|
601
|
-
return ids.filter((id) => id !== void 0).map((id) => this.lookup(id));
|
|
602
|
-
}
|
|
603
|
-
nodeDocument(id) {
|
|
604
|
-
return new _RoutedDocument(this.raw, this.options, this.lookup(id));
|
|
1286
|
+
this.owner(id);
|
|
605
1287
|
}
|
|
606
1288
|
collectGarbage() {
|
|
607
|
-
|
|
608
|
-
return this.raw.collectGarbage?.();
|
|
1289
|
+
return collectState(this.state);
|
|
609
1290
|
}
|
|
610
1291
|
retainNodeData(id, data2) {
|
|
611
|
-
this.
|
|
1292
|
+
dataEntry(this.owner(id), id).data = data2;
|
|
612
1293
|
}
|
|
613
1294
|
nodeData(id) {
|
|
614
|
-
|
|
1295
|
+
const state = this.owner(id);
|
|
1296
|
+
return state.data.get(id - state.base)?.data;
|
|
615
1297
|
}
|
|
616
1298
|
nodeDataOperation(id) {
|
|
617
|
-
const
|
|
1299
|
+
const entry = dataEntry(this.owner(id), id);
|
|
618
1300
|
const options = this.options;
|
|
619
|
-
return (command, args) =>
|
|
1301
|
+
return (command, args) => entry.isReleased ? void 0 : routedFor(entry.state).operate(command, { ...args, ids: [entry.state.base + entry.local], options });
|
|
620
1302
|
}
|
|
621
|
-
localNodeId(
|
|
622
|
-
return this.
|
|
1303
|
+
localNodeId(local) {
|
|
1304
|
+
return this.state.base + local;
|
|
623
1305
|
}
|
|
624
1306
|
rootId() {
|
|
625
|
-
return this.
|
|
1307
|
+
return this.state.base + (this.state.rootLocal ??= this.raw.rootId());
|
|
1308
|
+
}
|
|
1309
|
+
isOwnNode(id) {
|
|
1310
|
+
return id >= this.state.base && id < this.state.base + STRIDE2;
|
|
1311
|
+
}
|
|
1312
|
+
owner(id) {
|
|
1313
|
+
return stateIn(this, id);
|
|
626
1314
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
Object.defineProperty(view, "children", { enumerable: true, get: () => this.globals(document, record.children ?? []) });
|
|
631
|
-
for (const key of ["parent", "prev", "next"]) Object.defineProperty(view, key, { enumerable: true, get: () => record[key] == null ? null : this.global(document, record[key]) });
|
|
632
|
-
return view;
|
|
1315
|
+
globals(state, locals) {
|
|
1316
|
+
const { base } = state;
|
|
1317
|
+
return locals.map((local) => base + local);
|
|
633
1318
|
}
|
|
634
1319
|
groups(ids) {
|
|
635
1320
|
const groups = [];
|
|
1321
|
+
const own = this.state;
|
|
1322
|
+
let last;
|
|
636
1323
|
for (const id of ids) {
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
last.ids.push(handle.local);
|
|
641
|
-
last.global.push(id);
|
|
642
|
-
} else groups.push({ document: handle.document, ids: [handle.local], global: [id] });
|
|
1324
|
+
const state = id >= own.base && id < own.base + STRIDE2 ? own : exposedStateOf(id);
|
|
1325
|
+
if (last?.state === state) last.locals.push(id - state.base);
|
|
1326
|
+
else groups.push(last = { state, locals: [id - state.base] });
|
|
643
1327
|
}
|
|
644
1328
|
return groups;
|
|
645
1329
|
}
|
|
646
|
-
call(
|
|
647
|
-
if (command === "extractPlan" && JSON.stringify(args.plan).includes("innerHTML"))
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (handle) {
|
|
675
|
-
handle.document = target;
|
|
676
|
-
handle.local = newLocal;
|
|
677
|
-
}
|
|
678
|
-
localMap(target).set(newLocal, entry);
|
|
679
|
-
}
|
|
1330
|
+
call(state, command, args) {
|
|
1331
|
+
if (command === "extractPlan" && JSON.stringify(args.plan).includes("innerHTML")) invalidate(state);
|
|
1332
|
+
const isWrite = Object.hasOwn(args, "value") || writeCommands.has(command);
|
|
1333
|
+
if (isWrite) {
|
|
1334
|
+
registry2.writes++;
|
|
1335
|
+
const changed = recordOnlyWrites.has(command) ? args.ids ?? [] : command === "setNode" && attributeFields.has(args.field) ? [args.id] : void 0;
|
|
1336
|
+
if (changed) invalidateNodes(state, changed);
|
|
1337
|
+
else invalidate(state);
|
|
1338
|
+
}
|
|
1339
|
+
const result = rawOperation(state.raw, command, { ...args, options: args.options ?? this.options });
|
|
1340
|
+
if (isWrite) {
|
|
1341
|
+
refreshWrittenAttributes(state, command, args);
|
|
1342
|
+
refreshChildLists(state);
|
|
1343
|
+
scheduleCollectionIfDue(state);
|
|
1344
|
+
}
|
|
1345
|
+
return result;
|
|
1346
|
+
}
|
|
1347
|
+
/** Moves or copies nodes into `target`; returns their local ids there. */
|
|
1348
|
+
moveInto(target, ids, isCopy = false) {
|
|
1349
|
+
if (!isCopy) {
|
|
1350
|
+
for (const group of this.groups(ids)) {
|
|
1351
|
+
if (group.state === target) continue;
|
|
1352
|
+
if (!target.raw.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
1353
|
+
const adopted = JSON.parse(target.raw.adopt(group.state.raw, group.locals, true));
|
|
1354
|
+
rehome(group.state, target, adopted.mapping, ids);
|
|
1355
|
+
refreshChildLists(group.state);
|
|
1356
|
+
refreshChildLists(target);
|
|
1357
|
+
scheduleCollectionIfDue(group.state);
|
|
680
1358
|
}
|
|
681
|
-
return ids.map((id) =>
|
|
1359
|
+
return ids.map((id) => id - target.base);
|
|
682
1360
|
}
|
|
683
1361
|
const result = [];
|
|
684
1362
|
for (const group of this.groups(ids)) {
|
|
685
|
-
if (
|
|
686
|
-
result.push(...this.call(target, "clone", { ids: group.
|
|
1363
|
+
if (group.state === target) {
|
|
1364
|
+
result.push(...this.call(target, "clone", { ids: group.locals, deep: true }));
|
|
687
1365
|
continue;
|
|
688
1366
|
}
|
|
689
|
-
if (!target.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
690
|
-
|
|
691
|
-
const adopted = JSON.parse(target.adopt(group.
|
|
1367
|
+
if (!target.raw.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
1368
|
+
invalidate(target);
|
|
1369
|
+
const adopted = JSON.parse(target.raw.adopt(group.state.raw, group.locals, false));
|
|
692
1370
|
result.push(...adopted.roots);
|
|
693
1371
|
}
|
|
694
1372
|
return result;
|
|
695
1373
|
}
|
|
696
1374
|
scratch(command, args, ids) {
|
|
697
|
-
const
|
|
1375
|
+
const states = [...new Set(ids.map((id) => this.owner(id)))];
|
|
698
1376
|
const scratch = new (requireNative()).NativeDocument("", false, JSON.stringify(args.options ?? this.options));
|
|
699
1377
|
const toScratch = /* @__PURE__ */ new Map();
|
|
700
1378
|
const fromScratch = /* @__PURE__ */ new Map();
|
|
701
|
-
for (const
|
|
702
|
-
const records = JSON.parse(
|
|
1379
|
+
for (const state of states) {
|
|
1380
|
+
const records = JSON.parse(state.raw.exportTree());
|
|
703
1381
|
const roots = records.filter((record) => record.parent == null).map((record) => record.id);
|
|
704
1382
|
if (!scratch.adopt) throw new Error("The native addon does not support native document copies.");
|
|
705
|
-
const copied = JSON.parse(scratch.adopt(
|
|
1383
|
+
const copied = JSON.parse(scratch.adopt(state.raw, roots, false));
|
|
706
1384
|
for (const [local, copy] of copied.mapping) {
|
|
707
|
-
const global =
|
|
1385
|
+
const global = state.base + local;
|
|
708
1386
|
toScratch.set(global, copy);
|
|
709
1387
|
fromScratch.set(copy, global);
|
|
710
1388
|
}
|
|
@@ -712,177 +1390,308 @@ var RoutedDocument = class _RoutedDocument {
|
|
|
712
1390
|
const translated = { ...args };
|
|
713
1391
|
for (const key of ["ids", "contexts"]) if (Array.isArray(args[key])) translated[key] = args[key].map((id) => toScratch.get(id)).filter((id) => id !== void 0);
|
|
714
1392
|
if (args.pseudoMatches) translated.pseudoMatches = Object.fromEntries(Object.entries(args.pseudoMatches).map(([key, values]) => [key, values.map((id) => toScratch.get(id)).filter((id) => id !== void 0)]));
|
|
715
|
-
const result =
|
|
1393
|
+
const result = rawOperation(scratch, command, { ...translated, options: translated.options ?? this.options });
|
|
716
1394
|
return ["select", "matches", "uniqueSort"].includes(command) ? result.map((id) => fromScratch.get(id)).filter((id) => id !== void 0) : result;
|
|
717
1395
|
}
|
|
1396
|
+
isMixed(groups) {
|
|
1397
|
+
return groups.length > 1 && groups.some((group) => group.state !== groups[0].state);
|
|
1398
|
+
}
|
|
718
1399
|
select(selector, contexts) {
|
|
719
1400
|
const ids = contexts ?? [this.rootId()];
|
|
720
|
-
if (!ids.length) return this.call(this.
|
|
1401
|
+
if (!ids.length) return this.call(this.state, "select", { selector, contexts: [] });
|
|
721
1402
|
const groups = this.groups(ids);
|
|
722
|
-
if (
|
|
1403
|
+
if (this.isMixed(groups)) return this.scratch("select", { selector, contexts: ids }, ids);
|
|
723
1404
|
const group = groups[0];
|
|
724
|
-
const found = group.
|
|
725
|
-
return this.globals(group.
|
|
1405
|
+
const found = group.state === this.state ? group.state.raw.select(selector, group.locals) : this.call(group.state, "select", { selector, contexts: group.locals });
|
|
1406
|
+
return this.globals(group.state, found);
|
|
726
1407
|
}
|
|
727
1408
|
text(ids) {
|
|
728
|
-
return this.groups(ids).map((group) => group.
|
|
1409
|
+
return this.groups(ids).map((group) => group.state.raw.text(group.locals)).join("");
|
|
729
1410
|
}
|
|
730
1411
|
innerHtml(id) {
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
|
|
1412
|
+
const state = this.owner(id);
|
|
1413
|
+
const local = id - state.base;
|
|
1414
|
+
const isSplicing = recordAt(state, local)?.children?.some((child) => recordAt(state, child)?.type === "root") ?? false;
|
|
1415
|
+
if (isSplicing) invalidate(state);
|
|
1416
|
+
const html = state === this.state ? state.raw.innerHtml(local) : this.call(state, "html", { ids: [local] });
|
|
1417
|
+
if (isSplicing && state.hasChildLists && childRefresher) forEachView(state, childRefresher);
|
|
1418
|
+
return html;
|
|
734
1419
|
}
|
|
735
1420
|
outerHtml(ids) {
|
|
736
|
-
return this.groups(ids).map((group) => group.
|
|
1421
|
+
return this.groups(ids).map((group) => group.state === this.state ? group.state.raw.outerHtml(group.locals) : this.call(group.state, "render", { ids: group.locals })).join("");
|
|
737
1422
|
}
|
|
738
1423
|
attr(id, name) {
|
|
739
|
-
const
|
|
740
|
-
return this.call(
|
|
1424
|
+
const state = this.owner(id);
|
|
1425
|
+
return this.call(state, "attr", { ids: [id - state.base], name }) ?? void 0;
|
|
741
1426
|
}
|
|
742
1427
|
tagName(id) {
|
|
743
|
-
const
|
|
744
|
-
return
|
|
1428
|
+
const state = this.owner(id);
|
|
1429
|
+
return recordAt(state, id - state.base)?.name;
|
|
745
1430
|
}
|
|
746
1431
|
exportTree() {
|
|
747
|
-
return JSON.stringify(JSON.parse(this.raw.exportTree()).map((record) =>
|
|
1432
|
+
return JSON.stringify(JSON.parse(this.raw.exportTree()).map((record) => globalRecord(this.state, record)));
|
|
748
1433
|
}
|
|
749
1434
|
create(html, contextId) {
|
|
750
|
-
return
|
|
1435
|
+
return this.operate("create", { html, contextId });
|
|
751
1436
|
}
|
|
752
1437
|
op(command, json) {
|
|
753
1438
|
return JSON.stringify(this.operate(command, JSON.parse(json)) ?? null);
|
|
754
1439
|
}
|
|
755
1440
|
operate(command, args) {
|
|
756
1441
|
const options = args.options ?? this.options;
|
|
757
|
-
|
|
1442
|
+
const hasValue = Object.hasOwn(args, "value");
|
|
758
1443
|
if (command === "node") {
|
|
759
|
-
const
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
const
|
|
1444
|
+
const state = this.owner(args.id);
|
|
1445
|
+
return globalRecord(state, recordAt(state, args.id - state.base));
|
|
1446
|
+
}
|
|
1447
|
+
if (command === "createNode") return this.state.base + this.call(this.state, command, args);
|
|
1448
|
+
if (command === "import") return this.globals(this.state, this.call(this.state, command, args));
|
|
1449
|
+
if (command === "create") {
|
|
1450
|
+
const context = args.contextId == null ? void 0 : this.owner(args.contextId);
|
|
1451
|
+
const state = context ?? this.state;
|
|
1452
|
+
const contextLocal = context ? args.contextId - context.base : void 0;
|
|
768
1453
|
if (hasParserHooks(options)) {
|
|
769
|
-
const contextRecord = context ?
|
|
770
|
-
const
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
let
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
if (
|
|
783
|
-
|
|
784
|
-
|
|
1454
|
+
const contextRecord = context ? recordAt(context, contextLocal) : void 0;
|
|
1455
|
+
const children = parsedChildren(args.html, { ...options, ...contextRecord ? { __contextName: contextRecord.name, __contextNamespace: contextRecord.namespace } : {} });
|
|
1456
|
+
return this.globals(state, this.moveInto(state, children));
|
|
1457
|
+
}
|
|
1458
|
+
return this.globals(state, this.call(state, command, { ...args, contextId: contextLocal }));
|
|
1459
|
+
}
|
|
1460
|
+
if (command === "setNode" || command === "prop" && hasValue && (args.name === "children" || args.name === "childNodes" || pointerFields.has(args.name))) {
|
|
1461
|
+
const field = command === "setNode" ? args.field : args.name;
|
|
1462
|
+
let result2 = null;
|
|
1463
|
+
for (const id of command === "setNode" ? [args.id] : args.ids ?? []) {
|
|
1464
|
+
let state = this.owner(id);
|
|
1465
|
+
let nodeId2 = id;
|
|
1466
|
+
let value = args.value;
|
|
1467
|
+
if (field === "children" || field === "childNodes") value = this.moveInto(state, value ?? []);
|
|
1468
|
+
else if (pointerFields.has(field) && value != null) {
|
|
1469
|
+
const pointer = this.owner(value);
|
|
1470
|
+
if (pointer !== state) {
|
|
1471
|
+
const moved = [id];
|
|
1472
|
+
this.moveInto(pointer, moved);
|
|
1473
|
+
nodeId2 = moved[0];
|
|
1474
|
+
state = pointer;
|
|
1475
|
+
}
|
|
1476
|
+
value = args.value - pointer.base;
|
|
785
1477
|
}
|
|
786
|
-
|
|
1478
|
+
const local = nodeId2 - state.base;
|
|
1479
|
+
result2 = this.call(state, command, command === "setNode" ? { ...args, id: local, value } : { ...args, ids: [local], value });
|
|
787
1480
|
}
|
|
788
|
-
|
|
789
|
-
}
|
|
1481
|
+
return result2;
|
|
1482
|
+
}
|
|
1483
|
+
if (command === "insert") {
|
|
790
1484
|
const targets = args.targetIds ?? [];
|
|
791
1485
|
const nodes = args.nodeIds ?? [];
|
|
792
|
-
|
|
1486
|
+
const sameDocument = targets.length > 0 && this.groups([...targets, ...nodes]);
|
|
1487
|
+
if (sameDocument && sameDocument.length === 1) {
|
|
1488
|
+
const { state } = sameDocument[0];
|
|
1489
|
+
const inserted = this.call(state, command, { ...args, targetIds: targets.map((id) => id - state.base), nodeIds: nodes.map((id) => id - state.base) });
|
|
1490
|
+
return this.globals(state, inserted);
|
|
1491
|
+
}
|
|
1492
|
+
const result2 = [];
|
|
793
1493
|
for (let index = 0; index < targets.length; index++) {
|
|
794
|
-
const target = this.
|
|
795
|
-
const
|
|
796
|
-
const
|
|
797
|
-
|
|
1494
|
+
const target = this.owner(targets[index]);
|
|
1495
|
+
const targetLocal = targets[index] - target.base;
|
|
1496
|
+
const local = this.moveInto(target, nodes, index + 1 < targets.length);
|
|
1497
|
+
const inserted = this.call(target, command, { ...args, targetIds: [targetLocal], nodeIds: local });
|
|
1498
|
+
result2.push(...this.globals(target, inserted));
|
|
798
1499
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
const record = rawOperation(target.document, "node", { id: target.local });
|
|
804
|
-
if (!["root", "tag", "script", "style", "cdata"].includes(record.type)) continue;
|
|
805
|
-
const parsed = parseNativeDocument(String(args.value), { ...options, __contextName: record.name, __contextNamespace: record.namespace }, false);
|
|
806
|
-
const children2 = rawOperation(parsed, "node", { id: parsed.rootId() }).children;
|
|
807
|
-
const local = this.move(target.document, children2);
|
|
808
|
-
result = this.call(target.document, "setNode", { id: target.local, field: "children", value: local, options });
|
|
809
|
-
}
|
|
810
|
-
} else if (command === "contains") {
|
|
811
|
-
const parent = this.lookup(args.container ?? args.parent);
|
|
812
|
-
const child = this.lookup(args.contained ?? args.child);
|
|
813
|
-
result = parent.document === child.document && this.call(parent.document, command, { container: parent.local, contained: child.local });
|
|
814
|
-
} else if (command === "prop" && Object.hasOwn(args, "value") && ["children", "childNodes", "parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(args.name)) {
|
|
815
|
-
result = null;
|
|
1500
|
+
return result2;
|
|
1501
|
+
}
|
|
1502
|
+
if (command === "html" && hasValue && hasParserHooks(options)) {
|
|
1503
|
+
let result2 = null;
|
|
816
1504
|
for (const id of args.ids ?? []) {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
this.move(pointer.document, [id]);
|
|
824
|
-
handle = this.lookup(id);
|
|
825
|
-
}
|
|
826
|
-
value = this.lookup(args.value).local;
|
|
827
|
-
}
|
|
828
|
-
result = this.call(handle.document, command, { ...args, ids: [handle.local], value });
|
|
1505
|
+
const state = this.owner(id);
|
|
1506
|
+
const local = id - state.base;
|
|
1507
|
+
const record = recordAt(state, local);
|
|
1508
|
+
if (!record || !parentTypes.has(record.type)) continue;
|
|
1509
|
+
const children = parsedChildren(String(args.value), { ...options, __contextName: record.name, __contextNamespace: record.namespace });
|
|
1510
|
+
result2 = this.call(state, "setNode", { id: local, field: "children", value: this.moveInto(state, children), options });
|
|
829
1511
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
const
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
1512
|
+
return result2;
|
|
1513
|
+
}
|
|
1514
|
+
if (command === "contains") {
|
|
1515
|
+
const container = args.container ?? args.parent;
|
|
1516
|
+
const contained = args.contained ?? args.child;
|
|
1517
|
+
const parent = this.owner(container);
|
|
1518
|
+
const isSameDocument = contained >= parent.base && contained < parent.base + STRIDE2;
|
|
1519
|
+
return isSameDocument && this.call(parent, command, { container: container - parent.base, contained: contained - parent.base });
|
|
1520
|
+
}
|
|
1521
|
+
const ids = command === "select" ? args.contexts ?? [this.rootId()] : args.ids ?? [];
|
|
1522
|
+
const groups = this.groups(ids);
|
|
1523
|
+
if (this.isMixed(groups) && scratchCommands.has(command)) return this.scratch(command, { ...args, options }, ids) ?? null;
|
|
1524
|
+
if (command === "extractPlan") {
|
|
1525
|
+
const group = groups[0];
|
|
1526
|
+
return this.call(group?.state ?? this.state, command, { ...args, options, ids: group?.locals ?? [] }) ?? null;
|
|
1527
|
+
}
|
|
1528
|
+
if (idResultCommands.has(command)) {
|
|
1529
|
+
const isSelect = command === "select";
|
|
1530
|
+
if (!groups.length && (isSelect || command === "matches")) return this.call(this.state, command, { ...args, options, ids: [], ...isSelect ? { contexts: [] } : {} });
|
|
1531
|
+
const result2 = [];
|
|
1532
|
+
for (const group of groups) {
|
|
1533
|
+
const pseudoMatches = args.pseudoMatches ? Object.fromEntries(Object.entries(args.pseudoMatches).map(([key, values2]) => [key, values2.filter((id) => id >= group.state.base && id < group.state.base + STRIDE2).map((id) => id - group.state.base)])) : void 0;
|
|
1534
|
+
const values = this.call(group.state, command, { ...args, options, ids: group.locals, ...isSelect ? { contexts: group.locals } : {}, ...pseudoMatches ? { pseudoMatches } : {} });
|
|
1535
|
+
result2.push(...this.globals(group.state, values));
|
|
854
1536
|
}
|
|
1537
|
+
return result2;
|
|
1538
|
+
}
|
|
1539
|
+
if (command === "render" && !hasValue) {
|
|
1540
|
+
const optionsJson = JSON.stringify(options);
|
|
1541
|
+
return groups.map((group) => group.state.raw.render ? group.state.raw.render(group.locals, optionsJson) : this.call(group.state, command, { ...args, options, ids: group.locals })).join("");
|
|
855
1542
|
}
|
|
1543
|
+
if ((command === "outerHtml" || command === "text") && !hasValue) return groups.map((group) => this.call(group.state, command, { ...args, options, ids: group.locals })).join("");
|
|
1544
|
+
if (command === "hasClass") return groups.some((group) => this.call(group.state, command, { ...args, options, ids: group.locals }));
|
|
1545
|
+
if (command === "serializeArray" || command === "serialize") return groups.length ? this.call(groups[0].state, command, { ...args, options, ids: groups[0].locals }) : command === "serializeArray" ? [] : "";
|
|
1546
|
+
if (command === "html") for (const group of groups) invalidate(group.state);
|
|
1547
|
+
const isWrite = hasValue || writeCommands.has(command);
|
|
1548
|
+
let result = null;
|
|
1549
|
+
for (const group of isWrite ? groups : groups.slice(0, 1)) result = this.call(group.state, command, { ...args, options, ids: group.locals });
|
|
856
1550
|
return result ?? null;
|
|
857
1551
|
}
|
|
858
1552
|
};
|
|
1553
|
+
function parsedChildren(html, options) {
|
|
1554
|
+
const parsed = parseNativeDocument(html, options, false);
|
|
1555
|
+
exposeState(parsed.state);
|
|
1556
|
+
return parsed.operate("node", { id: parsed.rootId() }).children;
|
|
1557
|
+
}
|
|
1558
|
+
function dataEntry(state, id) {
|
|
1559
|
+
const local = id - state.base;
|
|
1560
|
+
let entry = state.data.get(local);
|
|
1561
|
+
if (!entry) state.data.set(local, entry = { state, local });
|
|
1562
|
+
return entry;
|
|
1563
|
+
}
|
|
1564
|
+
function rehome(source, target, mapping, ids) {
|
|
1565
|
+
registry2.writes++;
|
|
1566
|
+
invalidate(source);
|
|
1567
|
+
invalidate(target);
|
|
1568
|
+
exposeState(target);
|
|
1569
|
+
const moved = /* @__PURE__ */ new Map();
|
|
1570
|
+
for (const [oldLocal, newLocal] of mapping) {
|
|
1571
|
+
moved.set(source.base + oldLocal, target.base + newLocal);
|
|
1572
|
+
const node = uncacheView(source, oldLocal);
|
|
1573
|
+
if (node) {
|
|
1574
|
+
node[VIEW_STATE] = target;
|
|
1575
|
+
node[VIEW_LOCAL] = newLocal;
|
|
1576
|
+
cacheView(target, newLocal, node);
|
|
1577
|
+
if (node[VIEW_CHILD_TARGET]) target.hasChildLists = true;
|
|
1578
|
+
}
|
|
1579
|
+
const entry = source.data.get(oldLocal);
|
|
1580
|
+
if (entry) {
|
|
1581
|
+
source.data.delete(oldLocal);
|
|
1582
|
+
entry.state = target;
|
|
1583
|
+
entry.local = newLocal;
|
|
1584
|
+
target.data.set(newLocal, entry);
|
|
1585
|
+
}
|
|
1586
|
+
const adapterNode = source.adapterNodes?.[oldLocal];
|
|
1587
|
+
if (adapterNode) {
|
|
1588
|
+
source.adapterNodes[oldLocal] = void 0;
|
|
1589
|
+
(target.adapterNodes ??= [])[newLocal] = adapterNode;
|
|
1590
|
+
adapterNode[VIEW_STATE] = target;
|
|
1591
|
+
adapterNode[VIEW_LOCAL] = newLocal;
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
const rewrite = (list) => {
|
|
1595
|
+
let isTouched = false;
|
|
1596
|
+
for (let index = 0; index < list.length; index++) {
|
|
1597
|
+
const next = moved.get(list[index]);
|
|
1598
|
+
if (next !== void 0) {
|
|
1599
|
+
list[index] = next;
|
|
1600
|
+
isTouched = true;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
return isTouched;
|
|
1604
|
+
};
|
|
1605
|
+
for (const lease of [...source.leases]) {
|
|
1606
|
+
if (!rewrite(lease.ids)) continue;
|
|
1607
|
+
target.leases.add(lease);
|
|
1608
|
+
if (!lease.states.includes(target)) lease.states.push(target);
|
|
1609
|
+
if (!lease.ids.some((id) => id >= source.base && id < source.base + STRIDE2)) {
|
|
1610
|
+
source.leases.delete(lease);
|
|
1611
|
+
lease.states = lease.states.filter((state) => state !== source);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
rewrite(ids);
|
|
1615
|
+
}
|
|
1616
|
+
function refreshWrittenAttributes(state, command, args) {
|
|
1617
|
+
if (!hasViews(state)) return;
|
|
1618
|
+
let locals;
|
|
1619
|
+
if (targetedAttributeWrites.has(command)) locals = args.ids ?? [];
|
|
1620
|
+
else if (command === "setNode") {
|
|
1621
|
+
if (!attributeFields.has(args.field)) return;
|
|
1622
|
+
locals = [args.id];
|
|
1623
|
+
} else if (structuralWrites.has(command)) return;
|
|
1624
|
+
const refresh = (view) => {
|
|
1625
|
+
if (view && view[VIEW_ATTRIBUTES]) attributeRefresher?.(view);
|
|
1626
|
+
};
|
|
1627
|
+
if (locals) for (const local of locals) refresh(cachedView(state, local));
|
|
1628
|
+
else forEachView(state, refresh);
|
|
1629
|
+
}
|
|
1630
|
+
var attributeRefresher;
|
|
1631
|
+
var childRefresher;
|
|
1632
|
+
function onViewRefresh(attributes, children) {
|
|
1633
|
+
attributeRefresher = attributes;
|
|
1634
|
+
childRefresher = children;
|
|
1635
|
+
}
|
|
1636
|
+
function refreshChildLists(state) {
|
|
1637
|
+
if (!state.hasChildLists || !childRefresher) return;
|
|
1638
|
+
const touched = state.raw.takeTouched?.();
|
|
1639
|
+
if (touched === void 0) return;
|
|
1640
|
+
if (touched === null) {
|
|
1641
|
+
forEachView(state, childRefresher);
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
for (const local of touched) {
|
|
1645
|
+
const view = cachedView(state, local);
|
|
1646
|
+
if (view) childRefresher(view);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
859
1649
|
function routeDocument(document, options = {}) {
|
|
860
1650
|
return document.nodeSpace === registry2.space ? document : new RoutedDocument(document, options);
|
|
861
1651
|
}
|
|
1652
|
+
function routedFor(state) {
|
|
1653
|
+
return state.routed ??= new RoutedDocument(state.raw, state.options);
|
|
1654
|
+
}
|
|
862
1655
|
function sameNodeSpace(first, second) {
|
|
863
1656
|
return first === second || !!first.nodeSpace && first.nodeSpace === second.nodeSpace;
|
|
864
1657
|
}
|
|
1658
|
+
function isLocalState(state) {
|
|
1659
|
+
return state.space === registry2.space;
|
|
1660
|
+
}
|
|
1661
|
+
function isRouted(document) {
|
|
1662
|
+
return document.nodeSpace === registry2.space;
|
|
1663
|
+
}
|
|
865
1664
|
|
|
866
1665
|
// src/nodes.ts
|
|
867
|
-
var
|
|
868
|
-
var
|
|
869
|
-
var nodeState = nodeGlobals[nodeStateKey] ??= { views: /* @__PURE__ */ new WeakMap(), bindings: /* @__PURE__ */ new WeakMap(), caches: /* @__PURE__ */ new WeakMap(), finalizer: new FinalizationRegistry(({ cache, id }) => {
|
|
870
|
-
if (!cache.get(id)?.deref()) cache.delete(id);
|
|
871
|
-
}) };
|
|
872
|
-
var { bindings, caches } = nodeState;
|
|
873
|
-
var arrayIndex = /^(?:0|[1-9]\d*)$/;
|
|
1666
|
+
var VIEW_CHILDREN = /* @__PURE__ */ Symbol.for("rusteerio.node.children");
|
|
1667
|
+
var emptyRecord = Object.freeze({ id: -1, type: "released", children: [] });
|
|
874
1668
|
function operation(document, command, args = {}) {
|
|
875
1669
|
const direct = document.operate;
|
|
876
1670
|
if (direct) return direct.call(document, command, args);
|
|
877
1671
|
const value = document.op(command, JSON.stringify(args));
|
|
878
1672
|
return value === void 0 || value === "" ? void 0 : JSON.parse(value);
|
|
879
1673
|
}
|
|
1674
|
+
function viewId(node) {
|
|
1675
|
+
const view = node;
|
|
1676
|
+
const state = view?.[VIEW_STATE];
|
|
1677
|
+
return state !== void 0 && view[VIEW_SELF] === view && isLocalState(state) ? state.base + view[VIEW_LOCAL] : void 0;
|
|
1678
|
+
}
|
|
1679
|
+
function isNativeNode(node) {
|
|
1680
|
+
const view = node;
|
|
1681
|
+
return view?.[VIEW_STATE] !== void 0 && view[VIEW_SELF] === view;
|
|
1682
|
+
}
|
|
1683
|
+
function viewIdIn(document, node) {
|
|
1684
|
+
const id = viewId(node);
|
|
1685
|
+
if (id !== void 0) exposeTo(document, node[VIEW_STATE]);
|
|
1686
|
+
return id;
|
|
1687
|
+
}
|
|
880
1688
|
function nodeBinding(node) {
|
|
881
|
-
|
|
1689
|
+
const id = node && typeof node === "object" ? viewId(node) : void 0;
|
|
1690
|
+
return id === void 0 ? void 0 : { document: routedFor(node[VIEW_STATE]), id };
|
|
882
1691
|
}
|
|
883
1692
|
function nodeId(node, document) {
|
|
884
|
-
const
|
|
885
|
-
return
|
|
1693
|
+
const id = node && typeof node === "object" ? viewId(node) : void 0;
|
|
1694
|
+
return id !== void 0 && (!document || isRouted(document)) ? id : void 0;
|
|
886
1695
|
}
|
|
887
1696
|
function hydrateLocation(location) {
|
|
888
1697
|
if (!location || typeof location !== "object") return location;
|
|
@@ -895,26 +1704,201 @@ function hydrateLocation(location) {
|
|
|
895
1704
|
return location;
|
|
896
1705
|
}
|
|
897
1706
|
function nodeRecord(document, id) {
|
|
898
|
-
return operation(document, "node", { id });
|
|
1707
|
+
if (!isRouted(document)) return operation(document, "node", { id });
|
|
1708
|
+
const state = stateIn(document, id);
|
|
1709
|
+
return recordAt(state, id - state.base);
|
|
1710
|
+
}
|
|
1711
|
+
var isElementType = (type) => type === "tag" || type === "script" || type === "style";
|
|
1712
|
+
function traverseRecords(document, ids, kind) {
|
|
1713
|
+
if (!isRouted(document)) return void 0;
|
|
1714
|
+
const result = [];
|
|
1715
|
+
for (const id of ids) {
|
|
1716
|
+
const state = stateIn(document, id);
|
|
1717
|
+
const { base } = state;
|
|
1718
|
+
const node = recordAt(state, id - base);
|
|
1719
|
+
if (!node) continue;
|
|
1720
|
+
const isElement2 = (local) => isElementType(recordAt(state, local)?.type);
|
|
1721
|
+
if (kind === "children") {
|
|
1722
|
+
for (const child of node.children ?? []) if (isElement2(child)) result.push(base + child);
|
|
1723
|
+
} else if (kind === "contents") {
|
|
1724
|
+
for (const child of node.children ?? []) result.push(base + child);
|
|
1725
|
+
} else if (kind === "parent") {
|
|
1726
|
+
if (node.parent != null && isElement2(node.parent)) result.push(base + node.parent);
|
|
1727
|
+
} else if (kind === "parents" || kind === "ancestors") {
|
|
1728
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1729
|
+
for (let parent = node.parent; parent != null && !seen.has(parent); ) {
|
|
1730
|
+
seen.add(parent);
|
|
1731
|
+
const ancestor = recordAt(state, parent);
|
|
1732
|
+
if (!ancestor || ancestor.type === "root") break;
|
|
1733
|
+
if (isElementType(ancestor.type)) result.push(base + parent);
|
|
1734
|
+
parent = ancestor.parent;
|
|
1735
|
+
}
|
|
1736
|
+
} else if (kind === "next" || kind === "prev" || kind === "nextAll" || kind === "prevAll") {
|
|
1737
|
+
const isForward = kind === "next" || kind === "nextAll";
|
|
1738
|
+
const isSingle = kind === "next" || kind === "prev";
|
|
1739
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1740
|
+
for (let sibling = isForward ? node.next : node.prev; sibling != null && !seen.has(sibling); ) {
|
|
1741
|
+
seen.add(sibling);
|
|
1742
|
+
const record = recordAt(state, sibling);
|
|
1743
|
+
if (!record) break;
|
|
1744
|
+
if (isElementType(record.type)) {
|
|
1745
|
+
result.push(base + sibling);
|
|
1746
|
+
if (isSingle) break;
|
|
1747
|
+
}
|
|
1748
|
+
sibling = isForward ? record.next : record.prev;
|
|
1749
|
+
}
|
|
1750
|
+
} else if (kind === "siblings") {
|
|
1751
|
+
const parent = node.parent == null ? null : recordAt(state, node.parent);
|
|
1752
|
+
const local = id - base;
|
|
1753
|
+
for (const other of parent?.children ?? []) if (other !== local && isElement2(other)) result.push(base + other);
|
|
1754
|
+
} else return void 0;
|
|
1755
|
+
}
|
|
1756
|
+
return result;
|
|
1757
|
+
}
|
|
1758
|
+
function viewAt(state, local) {
|
|
1759
|
+
const existing = state.views[local] ?? cachedView(state, local);
|
|
1760
|
+
if (existing) return existing;
|
|
1761
|
+
const parsed = state.adapterNodes?.[local];
|
|
1762
|
+
if (parsed) {
|
|
1763
|
+
state.adapterNodes[local] = void 0;
|
|
1764
|
+
return adoptObject(state, local, parsed);
|
|
1765
|
+
}
|
|
1766
|
+
const snapshot = plainSnapshot(state, local);
|
|
1767
|
+
let constructor;
|
|
1768
|
+
if (snapshot) constructor = viewConstructor(snapshot.typeOf(local), false);
|
|
1769
|
+
else {
|
|
1770
|
+
const record = recordAt(state, local);
|
|
1771
|
+
if (!record) return void 0;
|
|
1772
|
+
constructor = viewConstructor(record.type, record.sourceCodeLocation !== void 0);
|
|
1773
|
+
}
|
|
1774
|
+
const view = new constructor(state, local);
|
|
1775
|
+
cacheView(state, local, view);
|
|
1776
|
+
return view;
|
|
1777
|
+
}
|
|
1778
|
+
function rootNode(document, id) {
|
|
1779
|
+
if (!isRouted(document)) throw new TypeError("Native nodes require a routed document");
|
|
1780
|
+
const state = stateIn(document, id);
|
|
1781
|
+
const local = id - state.base;
|
|
1782
|
+
const existing = cachedView(state, local);
|
|
1783
|
+
if (existing) return existing;
|
|
1784
|
+
if (state.adapterNodes?.[local] || state.options.sourceCodeLocationInfo) return viewAt(state, local);
|
|
1785
|
+
const view = new (viewConstructor("root", false))(state, local);
|
|
1786
|
+
cacheView(state, local, view);
|
|
1787
|
+
return view;
|
|
1788
|
+
}
|
|
1789
|
+
function getNode(document, id, original) {
|
|
1790
|
+
if (!isRouted(document)) throw new TypeError("Native nodes require a routed document");
|
|
1791
|
+
const state = stateIn(document, id);
|
|
1792
|
+
const local = id - state.base;
|
|
1793
|
+
if (original === void 0) return viewAt(state, local);
|
|
1794
|
+
return adoptObject(state, local, original);
|
|
1795
|
+
}
|
|
1796
|
+
function viewRecord(view) {
|
|
1797
|
+
const state = view[VIEW_STATE];
|
|
1798
|
+
const local = view[VIEW_LOCAL];
|
|
1799
|
+
return state.records[local] ?? recordAt(state, local) ?? emptyRecord;
|
|
1800
|
+
}
|
|
1801
|
+
function linkedView(view, local) {
|
|
1802
|
+
return local == null ? null : viewAt(view[VIEW_STATE], local) ?? null;
|
|
1803
|
+
}
|
|
1804
|
+
function setField(view, field, value) {
|
|
1805
|
+
const state = view[VIEW_STATE];
|
|
1806
|
+
operation(routedFor(state), "setNode", { id: state.base + view[VIEW_LOCAL], field, value });
|
|
899
1807
|
}
|
|
900
|
-
function
|
|
901
|
-
|
|
1808
|
+
function setPointer(view, field, value) {
|
|
1809
|
+
setField(view, field, value == null ? null : importNodes(routedFor(view[VIEW_STATE]), [value])[0]);
|
|
902
1810
|
}
|
|
903
|
-
function
|
|
904
|
-
const
|
|
1811
|
+
function attributesOf(view) {
|
|
1812
|
+
const state = view[VIEW_STATE];
|
|
1813
|
+
let attributes = view[VIEW_ATTRIBUTES];
|
|
1814
|
+
if (!attributes) view[VIEW_ATTRIBUTES] = attributes = createAttributes(view, state.options._useHtmlParser2 === false ? null : Object.prototype);
|
|
1815
|
+
if (attributes.generation !== state.generation || attributes.state !== state) syncAttributes(view, attributes);
|
|
1816
|
+
return attributes.proxy;
|
|
1817
|
+
}
|
|
1818
|
+
function createAttributes(view, prototype) {
|
|
905
1819
|
const target = Object.create(prototype);
|
|
1820
|
+
const handler = Object.create(attributeWrites);
|
|
1821
|
+
handler.view = view;
|
|
1822
|
+
handler.target = target;
|
|
1823
|
+
handler.generation = -1;
|
|
1824
|
+
handler.state = view[VIEW_STATE];
|
|
1825
|
+
handler.proxy = new Proxy(target, handler);
|
|
1826
|
+
return handler;
|
|
1827
|
+
}
|
|
1828
|
+
function syncAttributes(view, attributes) {
|
|
1829
|
+
const { target } = attributes;
|
|
1830
|
+
const state = view[VIEW_STATE];
|
|
1831
|
+
const local = view[VIEW_LOCAL];
|
|
1832
|
+
if (attributes.generation === -1) {
|
|
1833
|
+
const snapshot = plainSnapshot(state, local);
|
|
1834
|
+
if (snapshot) {
|
|
1835
|
+
snapshot.copyAttributes(local, target);
|
|
1836
|
+
attributes.generation = state.generation;
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
const values = viewRecord(view).attribs ?? {};
|
|
1841
|
+
const keys = Object.keys(target);
|
|
1842
|
+
const nextKeys = Object.keys(values);
|
|
1843
|
+
let isSameOrder = keys.length === nextKeys.length;
|
|
1844
|
+
for (let index = 0; isSameOrder && index < keys.length; index++) isSameOrder = keys[index] === nextKeys[index];
|
|
1845
|
+
if (!isSameOrder) for (const key of keys) delete target[key];
|
|
1846
|
+
for (const key of nextKeys) {
|
|
1847
|
+
if (isSameOrder && target[key] === values[key]) continue;
|
|
1848
|
+
if (key === "__proto__") Object.defineProperty(target, key, { value: values[key], writable: true, enumerable: true, configurable: true });
|
|
1849
|
+
else target[key] = values[key];
|
|
1850
|
+
}
|
|
1851
|
+
attributes.generation = view[VIEW_STATE].generation;
|
|
1852
|
+
attributes.state = view[VIEW_STATE];
|
|
1853
|
+
}
|
|
1854
|
+
function refreshAttributes(view) {
|
|
1855
|
+
const attributes = view[VIEW_ATTRIBUTES];
|
|
1856
|
+
if (attributes) syncAttributes(view, attributes);
|
|
1857
|
+
}
|
|
1858
|
+
onViewRefresh(refreshAttributes, fillChildren);
|
|
1859
|
+
var attributeWrites = {
|
|
1860
|
+
set(target, key, value) {
|
|
1861
|
+
if (typeof key === "symbol") return Reflect.set(target, key, value);
|
|
1862
|
+
const view = this.view;
|
|
1863
|
+
setField(view, "attribs", { ...viewRecord(view).attribs, [key]: String(value) });
|
|
1864
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1865
|
+
return true;
|
|
1866
|
+
},
|
|
1867
|
+
deleteProperty(target, key) {
|
|
1868
|
+
if (typeof key === "symbol") return Reflect.deleteProperty(target, key);
|
|
1869
|
+
const view = this.view;
|
|
1870
|
+
const values = { ...viewRecord(view).attribs };
|
|
1871
|
+
delete values[key];
|
|
1872
|
+
setField(view, "attribs", values);
|
|
1873
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1874
|
+
return true;
|
|
1875
|
+
},
|
|
1876
|
+
defineProperty(target, key, descriptor) {
|
|
1877
|
+
if (typeof key === "symbol") return Reflect.defineProperty(target, key, descriptor);
|
|
1878
|
+
const view = this.view;
|
|
1879
|
+
setField(view, "attribs", { ...viewRecord(view).attribs, [key]: String(descriptor.value) });
|
|
1880
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1881
|
+
return true;
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
function attributeMap(view, field) {
|
|
1885
|
+
const read = () => viewRecord(view)[field] ?? {};
|
|
1886
|
+
const target = Object.create(view[VIEW_STATE].options._useHtmlParser2 === false ? null : Object.prototype);
|
|
1887
|
+
const viewField = `x-${field}`;
|
|
906
1888
|
return new Proxy(target, {
|
|
907
1889
|
get(_target, key) {
|
|
908
|
-
|
|
1890
|
+
if (typeof key === "symbol") return Reflect.get(target, key);
|
|
1891
|
+
const values = read();
|
|
1892
|
+
return Object.hasOwn(values, key) ? values[key] : Reflect.get(target, key);
|
|
909
1893
|
},
|
|
910
1894
|
set(_target, key, value) {
|
|
911
|
-
setField(
|
|
1895
|
+
setField(view, viewField, { ...read(), [key]: String(value) });
|
|
912
1896
|
return true;
|
|
913
1897
|
},
|
|
914
1898
|
deleteProperty(_target, key) {
|
|
915
1899
|
const values = { ...read() };
|
|
916
1900
|
delete values[key];
|
|
917
|
-
setField(
|
|
1901
|
+
setField(view, viewField, values);
|
|
918
1902
|
return true;
|
|
919
1903
|
},
|
|
920
1904
|
ownKeys() {
|
|
@@ -924,247 +1908,358 @@ function attributes(document, id, field = "attribs", prototype = document.option
|
|
|
924
1908
|
return Object.hasOwn(read(), key) || key in target;
|
|
925
1909
|
},
|
|
926
1910
|
getOwnPropertyDescriptor(_target, key) {
|
|
927
|
-
|
|
1911
|
+
const values = read();
|
|
1912
|
+
return Object.hasOwn(values, key) ? { value: values[key], writable: true, enumerable: true, configurable: true } : void 0;
|
|
928
1913
|
},
|
|
929
1914
|
defineProperty(_target, key, descriptor) {
|
|
930
|
-
|
|
931
|
-
setField(document, id, field, values);
|
|
1915
|
+
setField(view, viewField, { ...read(), [key]: String(descriptor.value) });
|
|
932
1916
|
return true;
|
|
933
1917
|
}
|
|
934
1918
|
});
|
|
935
1919
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const values = snapshot();
|
|
959
|
-
if (key === "length") values.length = value;
|
|
960
|
-
else if (typeof key === "string" && arrayIndex.test(key)) values[Number(key)] = value;
|
|
961
|
-
else return Reflect.set(target, key, value);
|
|
962
|
-
save(values);
|
|
963
|
-
return true;
|
|
964
|
-
},
|
|
965
|
-
deleteProperty(_target, key) {
|
|
966
|
-
if (typeof key === "string" && arrayIndex.test(key)) {
|
|
967
|
-
const values = snapshot();
|
|
968
|
-
values.splice(Number(key), 1);
|
|
969
|
-
save(values);
|
|
970
|
-
return true;
|
|
971
|
-
}
|
|
972
|
-
return Reflect.deleteProperty(target, key);
|
|
973
|
-
},
|
|
974
|
-
has(_target, key) {
|
|
975
|
-
return typeof key === "string" && arrayIndex.test(key) ? Number(key) < read().length : Reflect.has(target, key);
|
|
976
|
-
},
|
|
977
|
-
ownKeys() {
|
|
978
|
-
return [...read().map((_child, i) => String(i)), "length"];
|
|
979
|
-
},
|
|
980
|
-
getOwnPropertyDescriptor(_target, key) {
|
|
981
|
-
if (key === "length") return { ...Reflect.getOwnPropertyDescriptor(target, "length"), value: read().length };
|
|
982
|
-
if (typeof key === "string" && arrayIndex.test(key) && Number(key) < read().length) return { value: getNode(document, read()[Number(key)]), writable: true, enumerable: true, configurable: true };
|
|
983
|
-
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
1920
|
+
var ChildArray = class _ChildArray extends Array {
|
|
1921
|
+
#view;
|
|
1922
|
+
constructor(view) {
|
|
1923
|
+
super();
|
|
1924
|
+
this.#view = view;
|
|
1925
|
+
}
|
|
1926
|
+
static viewOf(list) {
|
|
1927
|
+
return list instanceof _ChildArray ? list.#view : void 0;
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
Object.defineProperty(ChildArray.prototype, "constructor", { configurable: true, writable: true, value: Array });
|
|
1931
|
+
for (const method of ["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "copyWithin", "fill"]) {
|
|
1932
|
+
Object.defineProperty(ChildArray.prototype, method, {
|
|
1933
|
+
configurable: true,
|
|
1934
|
+
writable: true,
|
|
1935
|
+
value(...args) {
|
|
1936
|
+
const view = ChildArray.viewOf(this);
|
|
1937
|
+
if (!view) return Reflect.apply(Array.prototype[method], this, args);
|
|
1938
|
+
const values = Array.from(this);
|
|
1939
|
+
const result = Reflect.apply(Array.prototype[method], values, args);
|
|
1940
|
+
saveChildren(view, values);
|
|
1941
|
+
return result === values ? this : result;
|
|
984
1942
|
}
|
|
985
1943
|
});
|
|
986
1944
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
var tagTypes = /* @__PURE__ */ new Set(["tag", "script", "style"]);
|
|
990
|
-
var parentTypes = /* @__PURE__ */ new Set(["root", "tag", "script", "style", "cdata"]);
|
|
991
|
-
var dataTypes = /* @__PURE__ */ new Set(["text", "comment", "directive"]);
|
|
992
|
-
function viewKeys(record) {
|
|
993
|
-
const keys = ["parent", "prev", "next", "startIndex", "endIndex"];
|
|
994
|
-
if (parentTypes.has(record.type)) keys.push("children");
|
|
995
|
-
if (record.data !== void 0) keys.push("data");
|
|
996
|
-
if (record.name !== void 0) keys.push("name");
|
|
997
|
-
if (tagTypes.has(record.type)) keys.push("attribs");
|
|
998
|
-
keys.push("type");
|
|
999
|
-
for (const field of sourceFields) if (!keys.includes(field) && field in record) keys.push(field);
|
|
1000
|
-
if (tagTypes.has(record.type)) {
|
|
1001
|
-
if ("attribsNamespace" in record) keys.push("x-attribsNamespace");
|
|
1002
|
-
if ("attribsPrefix" in record) keys.push("x-attribsPrefix");
|
|
1003
|
-
}
|
|
1004
|
-
return keys;
|
|
1005
|
-
}
|
|
1006
|
-
function viewValue(state, key, receiver) {
|
|
1007
|
-
const { document, id } = state;
|
|
1008
|
-
const record = nodeRecord(document, id);
|
|
1009
|
-
if (key === "cloneNode") return cloneNode;
|
|
1010
|
-
if (key === "nodeType") return { root: 9, text: 3, comment: 8, cdata: 4 }[record.type] ?? 1;
|
|
1011
|
-
if (key === "tagName" && tagTypes.has(record.type)) return record.name;
|
|
1012
|
-
if (key === "nodeValue" && dataTypes.has(record.type)) return record.data;
|
|
1013
|
-
const pointer = parentAliases[key] ?? key;
|
|
1014
|
-
if (["parent", "prev", "next"].includes(pointer)) return record[pointer] == null ? null : getNode(document, record[pointer]);
|
|
1015
|
-
if (["children", "childNodes", "firstChild", "lastChild"].includes(key) && parentTypes.has(record.type)) {
|
|
1016
|
-
const list = state.children ??= children(document, id);
|
|
1017
|
-
return key === "firstChild" ? list[0] ?? null : key === "lastChild" ? list[list.length - 1] ?? null : list;
|
|
1018
|
-
}
|
|
1019
|
-
if (key === "attribs" && tagTypes.has(record.type)) return state.attributes ??= attributes(document, id);
|
|
1020
|
-
if ((key === "x-attribsNamespace" && "attribsNamespace" in record || key === "x-attribsPrefix" && "attribsPrefix" in record) && tagTypes.has(record.type)) {
|
|
1021
|
-
state.maps ??= {};
|
|
1022
|
-
return state.maps[key] ??= attributes(document, id, key === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
|
|
1023
|
-
}
|
|
1024
|
-
if (key === "attributes" && tagTypes.has(record.type)) {
|
|
1025
|
-
const attrs = state.attributes ??= attributes(document, id);
|
|
1026
|
-
return Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: record.attribsNamespace?.[name], prefix: record.attribsPrefix?.[name] }));
|
|
1027
|
-
}
|
|
1028
|
-
if (key === "sourceCodeLocation") return hydrateLocation(record[key]);
|
|
1029
|
-
if (sourceFields.has(key)) return record[key] ?? (key === "startIndex" || key === "endIndex" ? null : void 0);
|
|
1030
|
-
return void 0;
|
|
1945
|
+
function saveChildren(view, values) {
|
|
1946
|
+
setField(view, "children", importNodes(routedFor(view[VIEW_STATE]), values));
|
|
1031
1947
|
}
|
|
1032
|
-
function
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1948
|
+
function childList(view) {
|
|
1949
|
+
const existing = view[VIEW_CHILDREN];
|
|
1950
|
+
if (existing) return existing;
|
|
1951
|
+
const state = view[VIEW_STATE];
|
|
1952
|
+
if (!state.hasChildLists) {
|
|
1953
|
+
state.hasChildLists = true;
|
|
1954
|
+
state.raw.takeTouched?.();
|
|
1955
|
+
}
|
|
1956
|
+
const list = new ChildArray(view);
|
|
1957
|
+
view[VIEW_CHILD_TARGET] = list;
|
|
1958
|
+
view[VIEW_CHILDREN] = list;
|
|
1959
|
+
fillChildren(view);
|
|
1960
|
+
return list;
|
|
1961
|
+
}
|
|
1962
|
+
function fillChildren(view) {
|
|
1963
|
+
const target = view[VIEW_CHILD_TARGET];
|
|
1964
|
+
if (!target) return;
|
|
1965
|
+
const state = view[VIEW_STATE];
|
|
1966
|
+
const local = view[VIEW_LOCAL];
|
|
1967
|
+
const snapshot = plainSnapshot(state, local);
|
|
1968
|
+
if (snapshot && state.stale.size === 0) {
|
|
1969
|
+
fillFromSnapshot(state, snapshot, local, target);
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
const locals = viewRecord(view).children ?? [];
|
|
1973
|
+
target.length = locals.length;
|
|
1974
|
+
for (let index = 0; index < locals.length; index++) target[index] = viewAt(state, locals[index]);
|
|
1052
1975
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1976
|
+
function fillFromSnapshot(state, snapshot, local, target) {
|
|
1977
|
+
const count = snapshot.childCount(local);
|
|
1978
|
+
const first = snapshot.childStart(local);
|
|
1979
|
+
const childIds2 = snapshot.childIds;
|
|
1980
|
+
const views = state.views;
|
|
1981
|
+
const isStrong = !state.adapterNodes;
|
|
1982
|
+
const constructors = snapshotConstructors(snapshot);
|
|
1983
|
+
target.length = count;
|
|
1984
|
+
for (let index = 0; index < count; index++) {
|
|
1985
|
+
const child = childIds2[first + index];
|
|
1986
|
+
let node = views[child] ?? (state.weakViews.size ? cachedView(state, child) : void 0);
|
|
1987
|
+
if (node === void 0) {
|
|
1988
|
+
const constructor = isStrong && child < state.baseline && snapshot.isPlain(child) ? constructors(snapshot.typeReference(child)) : void 0;
|
|
1989
|
+
if (constructor) views[child] = node = new constructor(state, child);
|
|
1990
|
+
else node = viewAt(state, child);
|
|
1059
1991
|
}
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1992
|
+
target[index] = node;
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
function snapshotConstructors(snapshot) {
|
|
1996
|
+
let lookup = snapshot.viewConstructors;
|
|
1997
|
+
if (!lookup) {
|
|
1998
|
+
const byReference = [];
|
|
1999
|
+
lookup = (reference) => byReference[reference] ??= viewConstructor(snapshot.name(reference), false);
|
|
2000
|
+
snapshot.viewConstructors = lookup;
|
|
2001
|
+
}
|
|
2002
|
+
return lookup;
|
|
2003
|
+
}
|
|
2004
|
+
var recordField = (field, fallback) => ({
|
|
2005
|
+
get() {
|
|
2006
|
+
return viewRecord(this)[field] ?? fallback;
|
|
1066
2007
|
},
|
|
1067
|
-
|
|
1068
|
-
|
|
2008
|
+
set(value) {
|
|
2009
|
+
setField(this, field, value);
|
|
2010
|
+
}
|
|
2011
|
+
});
|
|
2012
|
+
var snapshotField = (field) => ({
|
|
2013
|
+
get() {
|
|
2014
|
+
const state = this[VIEW_STATE];
|
|
2015
|
+
const local = this[VIEW_LOCAL];
|
|
2016
|
+
const snapshot = plainSnapshot(state, local);
|
|
2017
|
+
if (snapshot) return field === "type" ? snapshot.typeOf(local) : field === "name" ? snapshot.nameOf(local) : snapshot.dataOf(local);
|
|
2018
|
+
return viewRecord(this)[field];
|
|
1069
2019
|
},
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
2020
|
+
set(value) {
|
|
2021
|
+
setField(this, field, value);
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
var linkOffsets = { parent: 1, prev: 2, next: 3 };
|
|
2025
|
+
var pointerField = (field) => ({
|
|
2026
|
+
get() {
|
|
2027
|
+
const state = this[VIEW_STATE];
|
|
2028
|
+
const local = this[VIEW_LOCAL];
|
|
2029
|
+
const snapshot = plainSnapshot(state, local);
|
|
2030
|
+
return linkedView(this, snapshot ? snapshot.linkOf(local, linkOffsets[field]) : viewRecord(this)[field]);
|
|
1073
2031
|
},
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
if (existing) return existing;
|
|
1077
|
-
const state = nodeState.views.get(target);
|
|
1078
|
-
if (typeof key === "string" && viewKeys(nodeRecord(state.document, state.id)).includes(key)) return { value: viewValue(state, key, void 0), configurable: true, enumerable: true, writable: true };
|
|
1079
|
-
return void 0;
|
|
2032
|
+
set(value) {
|
|
2033
|
+
setPointer(this, field, value);
|
|
1080
2034
|
}
|
|
2035
|
+
});
|
|
2036
|
+
var nodeAccessors = {
|
|
2037
|
+
type: snapshotField("type"),
|
|
2038
|
+
parent: pointerField("parent"),
|
|
2039
|
+
prev: pointerField("prev"),
|
|
2040
|
+
next: pointerField("next"),
|
|
2041
|
+
startIndex: recordField("startIndex", null),
|
|
2042
|
+
endIndex: recordField("endIndex", null)
|
|
1081
2043
|
};
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
2044
|
+
var locationAccessor = { get() {
|
|
2045
|
+
return hydrateLocation(viewRecord(this).sourceCodeLocation);
|
|
2046
|
+
}, set(value) {
|
|
2047
|
+
setField(this, "sourceCodeLocation", value);
|
|
2048
|
+
} };
|
|
2049
|
+
var childAccessors = {
|
|
2050
|
+
children: { get() {
|
|
2051
|
+
return childList(this);
|
|
2052
|
+
}, set(value) {
|
|
2053
|
+
setField(this, "children", importNodes(routedFor(this[VIEW_STATE]), value));
|
|
2054
|
+
} }
|
|
2055
|
+
};
|
|
2056
|
+
var elementAccessors = {
|
|
2057
|
+
name: snapshotField("name"),
|
|
2058
|
+
attribs: { get() {
|
|
2059
|
+
return attributesOf(this);
|
|
2060
|
+
}, set(value) {
|
|
2061
|
+
setField(this, "attribs", value);
|
|
2062
|
+
} },
|
|
2063
|
+
namespace: recordField("namespace"),
|
|
2064
|
+
prefix: recordField("prefix"),
|
|
2065
|
+
"x-attribsNamespace": { get() {
|
|
2066
|
+
return viewRecord(this).attribsNamespace !== void 0 ? attributeMap(this, "attribsNamespace") : void 0;
|
|
2067
|
+
}, set(value) {
|
|
2068
|
+
setField(this, "x-attribsNamespace", value);
|
|
2069
|
+
} },
|
|
2070
|
+
"x-attribsPrefix": { get() {
|
|
2071
|
+
return viewRecord(this).attribsPrefix !== void 0 ? attributeMap(this, "attribsPrefix") : void 0;
|
|
2072
|
+
}, set(value) {
|
|
2073
|
+
setField(this, "x-attribsPrefix", value);
|
|
2074
|
+
} }
|
|
2075
|
+
};
|
|
2076
|
+
var dataAccessors = { data: snapshotField("data") };
|
|
2077
|
+
var directiveAccessors = { name: recordField("name"), "x-name": recordField("x-name"), "x-publicId": recordField("x-publicId"), "x-systemId": recordField("x-systemId") };
|
|
2078
|
+
var documentAccessors = { "x-mode": recordField("x-mode") };
|
|
2079
|
+
function accessorsFor(type) {
|
|
2080
|
+
switch (type) {
|
|
2081
|
+
case "tag":
|
|
2082
|
+
case "script":
|
|
2083
|
+
case "style":
|
|
2084
|
+
return { ...nodeAccessors, ...childAccessors, ...elementAccessors };
|
|
2085
|
+
case "root":
|
|
2086
|
+
return { ...nodeAccessors, ...childAccessors, ...documentAccessors };
|
|
2087
|
+
case "cdata":
|
|
2088
|
+
return { ...nodeAccessors, ...childAccessors };
|
|
2089
|
+
case "directive":
|
|
2090
|
+
return { ...nodeAccessors, ...dataAccessors, ...directiveAccessors };
|
|
2091
|
+
case "text":
|
|
2092
|
+
case "comment":
|
|
2093
|
+
return { ...nodeAccessors, ...dataAccessors };
|
|
2094
|
+
default:
|
|
2095
|
+
return { ...nodeAccessors, ...childAccessors, ...dataAccessors, name: recordField("name") };
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
var viewConstructors = /* @__PURE__ */ new Map();
|
|
2099
|
+
var plainConstructors = /* @__PURE__ */ Object.create(null);
|
|
2100
|
+
function viewConstructor(type, hasLocation) {
|
|
2101
|
+
if (!hasLocation) {
|
|
2102
|
+
const plain = plainConstructors[type];
|
|
2103
|
+
if (plain) return plain;
|
|
2104
|
+
}
|
|
2105
|
+
const key = hasLocation ? `${type}:location` : type;
|
|
2106
|
+
let constructor = viewConstructors.get(key);
|
|
2107
|
+
if (constructor) return constructor;
|
|
2108
|
+
const prototype = Object.create(nodePrototype(type));
|
|
2109
|
+
const accessors = hasLocation ? { ...accessorsFor(type), sourceCodeLocation: locationAccessor } : accessorsFor(type);
|
|
2110
|
+
for (const [field, accessor] of Object.entries(accessors)) Object.defineProperty(prototype, field, { ...accessor, configurable: true, enumerable: false });
|
|
2111
|
+
constructor = function(state, local) {
|
|
2112
|
+
this[VIEW_STATE] = state;
|
|
2113
|
+
this[VIEW_LOCAL] = local;
|
|
2114
|
+
this[VIEW_SELF] = this;
|
|
2115
|
+
this[VIEW_ATTRIBUTES] = void 0;
|
|
2116
|
+
this[VIEW_CHILDREN] = void 0;
|
|
2117
|
+
this[VIEW_CHILD_TARGET] = void 0;
|
|
1108
2118
|
};
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
2119
|
+
Object.defineProperty(prototype, inspectSymbol, { configurable: true, writable: true, value: inspectNode });
|
|
2120
|
+
constructor.prototype = prototype;
|
|
2121
|
+
viewConstructors.set(key, constructor);
|
|
2122
|
+
if (!hasLocation) plainConstructors[type] = constructor;
|
|
2123
|
+
return constructor;
|
|
2124
|
+
}
|
|
2125
|
+
var inspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
2126
|
+
var inspectedFields = ["type", "name", "data", "attribs", "namespace", "startIndex", "endIndex"];
|
|
2127
|
+
function inspectNode(depth, options, inspect) {
|
|
2128
|
+
const fields = {};
|
|
2129
|
+
for (const field of inspectedFields) if (field in this && this[field] != null) fields[field] = field === "attribs" ? { ...this.attribs } : this[field];
|
|
2130
|
+
if ("children" in this) fields.children = `[${this.children.length} nodes]`;
|
|
2131
|
+
const name = Object.getPrototypeOf(Object.getPrototypeOf(this))?.constructor?.name ?? "Node";
|
|
2132
|
+
return depth < 0 ? `[${name}]` : `${name} ${inspect(fields, { ...options, depth: 1 })}`;
|
|
2133
|
+
}
|
|
2134
|
+
var adoptedAliases = {
|
|
2135
|
+
parentNode: { configurable: true, enumerable: false, get() {
|
|
2136
|
+
return this.parent;
|
|
2137
|
+
}, set(value) {
|
|
2138
|
+
this.parent = value;
|
|
2139
|
+
} },
|
|
2140
|
+
previousSibling: { configurable: true, enumerable: false, get() {
|
|
2141
|
+
return this.prev;
|
|
2142
|
+
}, set(value) {
|
|
2143
|
+
this.prev = value;
|
|
2144
|
+
} },
|
|
2145
|
+
nextSibling: { configurable: true, enumerable: false, get() {
|
|
2146
|
+
return this.next;
|
|
2147
|
+
}, set(value) {
|
|
2148
|
+
this.next = value;
|
|
2149
|
+
} },
|
|
2150
|
+
nodeType: { configurable: true, enumerable: false, get() {
|
|
2151
|
+
return { root: 9, text: 3, comment: 8, cdata: 4 }[viewRecord(this).type] ?? 1;
|
|
2152
|
+
} },
|
|
2153
|
+
cloneNode: { configurable: true, enumerable: false, writable: true, value: cloneNode }
|
|
2154
|
+
};
|
|
2155
|
+
var adoptedChildAliases = {
|
|
2156
|
+
childNodes: { configurable: true, enumerable: false, get() {
|
|
2157
|
+
return this.children;
|
|
2158
|
+
}, set(value) {
|
|
2159
|
+
this.children = value;
|
|
2160
|
+
} },
|
|
2161
|
+
firstChild: { configurable: true, enumerable: false, get() {
|
|
2162
|
+
return this.children[0] ?? null;
|
|
2163
|
+
} },
|
|
2164
|
+
lastChild: { configurable: true, enumerable: false, get() {
|
|
2165
|
+
return this.children[this.children.length - 1] ?? null;
|
|
2166
|
+
} }
|
|
2167
|
+
};
|
|
2168
|
+
var adoptedElementAliases = {
|
|
2169
|
+
tagName: { configurable: true, enumerable: false, get() {
|
|
2170
|
+
return this.name;
|
|
2171
|
+
}, set(value) {
|
|
2172
|
+
this.name = value;
|
|
2173
|
+
} },
|
|
2174
|
+
attributes: { configurable: true, enumerable: false, get() {
|
|
2175
|
+
const attributes = this.attribs;
|
|
2176
|
+
const record = viewRecord(this);
|
|
2177
|
+
return Object.keys(attributes).map((name) => ({ name, value: attributes[name], namespace: record.attribsNamespace?.[name], prefix: record.attribsPrefix?.[name] }));
|
|
2178
|
+
} }
|
|
2179
|
+
};
|
|
2180
|
+
var adoptedDataAliases = {
|
|
2181
|
+
nodeValue: { configurable: true, enumerable: false, get() {
|
|
2182
|
+
return this.data;
|
|
2183
|
+
}, set(value) {
|
|
2184
|
+
this.data = value;
|
|
2185
|
+
} }
|
|
2186
|
+
};
|
|
2187
|
+
var adoptedFields = /* @__PURE__ */ new Map();
|
|
2188
|
+
var optionalAdoptedKeys = ["name", "data", "namespace", "prefix", "sourceCodeLocation", "x-name", "x-publicId", "x-systemId", "x-mode", "x-attribsNamespace", "x-attribsPrefix"];
|
|
2189
|
+
var optionalAdoptedFields = new Set(optionalAdoptedKeys);
|
|
2190
|
+
var adoptedShapes = /* @__PURE__ */ new Map();
|
|
2191
|
+
function adoptObject(state, local, original) {
|
|
2192
|
+
const record = recordAt(state, local);
|
|
2193
|
+
if (!record) return void 0;
|
|
2194
|
+
const view = original;
|
|
2195
|
+
const attributesPrototype = original.attribs && typeof original.attribs === "object" ? Object.getPrototypeOf(original.attribs) : void 0;
|
|
2196
|
+
view[VIEW_STATE] = state;
|
|
2197
|
+
view[VIEW_LOCAL] = local;
|
|
2198
|
+
view[VIEW_SELF] = view;
|
|
2199
|
+
view[VIEW_ATTRIBUTES] = void 0;
|
|
2200
|
+
view[VIEW_CHILDREN] = void 0;
|
|
2201
|
+
view[VIEW_CHILD_TARGET] = void 0;
|
|
2202
|
+
let fields = adoptedFields.get(record.type);
|
|
2203
|
+
if (!fields) {
|
|
2204
|
+
fields = {};
|
|
2205
|
+
for (const [key, accessor] of Object.entries({ ...accessorsFor(record.type), sourceCodeLocation: locationAccessor })) fields[key] = { ...accessor, configurable: true, enumerable: true };
|
|
2206
|
+
adoptedFields.set(record.type, fields);
|
|
2207
|
+
}
|
|
2208
|
+
let shape = record.type;
|
|
2209
|
+
for (const key of optionalAdoptedKeys) {
|
|
2210
|
+
if (!(key in fields)) continue;
|
|
2211
|
+
const field = key === "x-attribsNamespace" ? "attribsNamespace" : key === "x-attribsPrefix" ? "attribsPrefix" : key;
|
|
2212
|
+
shape += record[field] !== void 0 || Object.hasOwn(original, key) ? "1" : "0";
|
|
2213
|
+
}
|
|
2214
|
+
let descriptors = adoptedShapes.get(shape);
|
|
2215
|
+
if (!descriptors) {
|
|
2216
|
+
const present = {};
|
|
2217
|
+
for (const key in fields) {
|
|
2218
|
+
const field = key === "x-attribsNamespace" ? "attribsNamespace" : key === "x-attribsPrefix" ? "attribsPrefix" : key;
|
|
2219
|
+
if (optionalAdoptedFields.has(key) && record[field] === void 0 && !Object.hasOwn(original, key)) continue;
|
|
2220
|
+
present[key] = fields[key];
|
|
1113
2221
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
define("tagName", () => node.name, (value) => {
|
|
1138
|
-
node.name = value;
|
|
1139
|
-
}, false);
|
|
1140
|
-
for (const field of ["x-attribsNamespace", "x-attribsPrefix"]) {
|
|
1141
|
-
if (!((field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix") in record) && !Object.hasOwn(original, field)) continue;
|
|
1142
|
-
const values = attributes(document, id, field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
|
|
1143
|
-
define(field, () => values, (value) => setField(document, id, field, value));
|
|
1144
|
-
}
|
|
1145
|
-
define("attributes", () => Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: read().attribsNamespace?.[name], prefix: read().attribsPrefix?.[name] })), void 0, false);
|
|
1146
|
-
}
|
|
1147
|
-
if (["text", "comment", "directive"].includes(record.type)) define("nodeValue", () => node.data, (value) => {
|
|
1148
|
-
node.data = value;
|
|
1149
|
-
}, false);
|
|
1150
|
-
define("nodeType", () => ({ root: 9, text: 3, comment: 8, cdata: 4 })[read().type] ?? 1, void 0, false);
|
|
1151
|
-
Object.defineProperty(node, "cloneNode", { configurable: true, enumerable: false, writable: true, value: cloneNode });
|
|
1152
|
-
return node;
|
|
2222
|
+
const isParent = "children" in present;
|
|
2223
|
+
const isData = record.type === "text" || record.type === "comment" || record.type === "directive";
|
|
2224
|
+
descriptors = { ...present, ...adoptedAliases, ...isParent ? adoptedChildAliases : {}, ...isElementType(record.type) ? adoptedElementAliases : {}, ...isData ? adoptedDataAliases : {} };
|
|
2225
|
+
adoptedShapes.set(shape, descriptors);
|
|
2226
|
+
}
|
|
2227
|
+
const isElement2 = isElementType(record.type);
|
|
2228
|
+
try {
|
|
2229
|
+
Object.defineProperties(view, descriptors);
|
|
2230
|
+
} catch {
|
|
2231
|
+
}
|
|
2232
|
+
if (isElement2 && attributesPrototype !== void 0) view[VIEW_ATTRIBUTES] = createAttributes(view, attributesPrototype);
|
|
2233
|
+
cacheView(state, local, view);
|
|
2234
|
+
return view;
|
|
2235
|
+
}
|
|
2236
|
+
function attachParsedNodes(state, nodes) {
|
|
2237
|
+
state.adapterNodes = nodes;
|
|
2238
|
+
for (let local = 0; local < nodes.length; local++) {
|
|
2239
|
+
const node = nodes[local];
|
|
2240
|
+
if (!node) continue;
|
|
2241
|
+
node[VIEW_STATE] = state;
|
|
2242
|
+
node[VIEW_LOCAL] = local;
|
|
2243
|
+
node[VIEW_SELF] = node;
|
|
2244
|
+
}
|
|
1153
2245
|
}
|
|
1154
2246
|
function cloneNode(recursive = false) {
|
|
1155
2247
|
const binding = nodeBinding(this);
|
|
1156
2248
|
if (!binding) throw new TypeError("cloneNode requires a native DOM node receiver");
|
|
1157
2249
|
return getNode(binding.document, operation(binding.document, "clone", { ids: [binding.id], deep: recursive })[0]);
|
|
1158
2250
|
}
|
|
2251
|
+
function childIds(document, id) {
|
|
2252
|
+
const state = stateIn(document, id);
|
|
2253
|
+
return (recordAt(state, id - state.base)?.children ?? []).map((child) => state.base + child);
|
|
2254
|
+
}
|
|
1159
2255
|
function importNodes(document, input) {
|
|
1160
2256
|
if (input == null || input === false) return [];
|
|
1161
2257
|
const values = Array.isArray(input) || typeof input === "object" && "length" in input && !("type" in input) ? Array.from(input) : [input];
|
|
1162
2258
|
const result = [];
|
|
1163
2259
|
for (const node of values) {
|
|
1164
2260
|
if (node == null) continue;
|
|
1165
|
-
const existing =
|
|
2261
|
+
const existing = node && typeof node === "object" ? viewIdIn(document, node) : void 0;
|
|
1166
2262
|
if (existing !== void 0) {
|
|
1167
|
-
document.retainNode?.(existing);
|
|
1168
2263
|
result.push(existing);
|
|
1169
2264
|
continue;
|
|
1170
2265
|
}
|
|
@@ -1189,8 +2284,8 @@ function importNodes(document, input) {
|
|
|
1189
2284
|
const adopt = (oldId, newId) => {
|
|
1190
2285
|
const source = originals.get(oldId);
|
|
1191
2286
|
const oldChildren = records[oldId].children;
|
|
1192
|
-
const newChildren =
|
|
1193
|
-
getNode(document, newId,
|
|
2287
|
+
const newChildren = childIds(document, newId);
|
|
2288
|
+
getNode(document, newId, isNativeNode(source) ? void 0 : source);
|
|
1194
2289
|
for (let i = 0; i < oldChildren.length; i++) if (newChildren[i] !== void 0) adopt(oldChildren[i], newChildren[i]);
|
|
1195
2290
|
};
|
|
1196
2291
|
adopt(root, imported[0]);
|
|
@@ -1201,10 +2296,10 @@ function importNodes(document, input) {
|
|
|
1201
2296
|
|
|
1202
2297
|
// src/dom.ts
|
|
1203
2298
|
var ElementType = Object.freeze({ Root: "root", Text: "text", Directive: "directive", Comment: "comment", Script: "script", Style: "style", Tag: "tag", CDATA: "cdata", Doctype: "doctype" });
|
|
1204
|
-
function initialize(node, type, fields,
|
|
2299
|
+
function initialize(node, type, fields, children = []) {
|
|
1205
2300
|
const document = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
1206
2301
|
const id = operation(document, "createNode", { type, ...fields });
|
|
1207
|
-
if (
|
|
2302
|
+
if (children.length) operation(document, "setNode", { id, field: "children", value: importNodes(document, children) });
|
|
1208
2303
|
return getNode(document, id, node);
|
|
1209
2304
|
}
|
|
1210
2305
|
var Node = class {
|
|
@@ -1259,21 +2354,21 @@ var ProcessingInstruction = class extends DataNode {
|
|
|
1259
2354
|
}
|
|
1260
2355
|
};
|
|
1261
2356
|
var Document = class extends NodeWithChildren {
|
|
1262
|
-
constructor(
|
|
2357
|
+
constructor(children) {
|
|
1263
2358
|
super();
|
|
1264
|
-
return initialize(this, "root", {},
|
|
2359
|
+
return initialize(this, "root", {}, children);
|
|
1265
2360
|
}
|
|
1266
2361
|
};
|
|
1267
2362
|
var CDATA = class extends NodeWithChildren {
|
|
1268
|
-
constructor(
|
|
2363
|
+
constructor(children) {
|
|
1269
2364
|
super();
|
|
1270
|
-
return initialize(this, "cdata", {},
|
|
2365
|
+
return initialize(this, "cdata", {}, children);
|
|
1271
2366
|
}
|
|
1272
2367
|
};
|
|
1273
2368
|
var Element = class extends NodeWithChildren {
|
|
1274
|
-
constructor(name, attribs,
|
|
2369
|
+
constructor(name, attribs, children = [], type) {
|
|
1275
2370
|
super();
|
|
1276
|
-
return initialize(this, type ?? (name === "script" || name === "style" ? name : "tag"), { name, attribs },
|
|
2371
|
+
return initialize(this, type ?? (name === "script" || name === "style" ? name : "tag"), { name, attribs }, children);
|
|
1277
2372
|
}
|
|
1278
2373
|
};
|
|
1279
2374
|
function nodePrototype(type) {
|
|
@@ -1380,7 +2475,7 @@ function dataValue(object, key) {
|
|
|
1380
2475
|
function compileExtractPlan(map, options) {
|
|
1381
2476
|
if (options.pseudos || options.treeAdapter || options.Tokenizer || options.xml && typeof options.xml === "object" && options.xml.Tokenizer) return void 0;
|
|
1382
2477
|
const ancestors = /* @__PURE__ */ new Set();
|
|
1383
|
-
const
|
|
2478
|
+
const compile2 = (input) => {
|
|
1384
2479
|
if (!input || typeof input !== "object" || types.isProxy(input) || ancestors.has(input) || ancestors.size >= 64) return void 0;
|
|
1385
2480
|
for (let current = Object.getPrototypeOf(input); current; current = Object.getPrototypeOf(current)) {
|
|
1386
2481
|
if (types.isProxy(current)) return void 0;
|
|
@@ -1417,7 +2512,7 @@ function compileExtractPlan(map, options) {
|
|
|
1417
2512
|
if (!scalarProperties.has(value) && !/^(?:data-|aria-).+/.test(value)) return void 0;
|
|
1418
2513
|
entries2.push({ key, selector, all, value: { kind: "property", name: value } });
|
|
1419
2514
|
} else {
|
|
1420
|
-
const nested =
|
|
2515
|
+
const nested = compile2(value);
|
|
1421
2516
|
if (!nested) return void 0;
|
|
1422
2517
|
entries2.push({ key, selector, all, value: { kind: "map", entries: nested } });
|
|
1423
2518
|
}
|
|
@@ -1427,7 +2522,7 @@ function compileExtractPlan(map, options) {
|
|
|
1427
2522
|
ancestors.delete(input);
|
|
1428
2523
|
}
|
|
1429
2524
|
};
|
|
1430
|
-
const entries =
|
|
2525
|
+
const entries = compile2(map);
|
|
1431
2526
|
return entries && { version: 1, entries };
|
|
1432
2527
|
}
|
|
1433
2528
|
function hydrateExtractResult(result, entries) {
|
|
@@ -1445,13 +2540,37 @@ function hydrateExtractResult(result, entries) {
|
|
|
1445
2540
|
}
|
|
1446
2541
|
|
|
1447
2542
|
// src/attributes.ts
|
|
1448
|
-
var
|
|
1449
|
-
var
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
2543
|
+
var elementTypes = /* @__PURE__ */ new Set(["tag", "script", "style"]);
|
|
2544
|
+
var booleanAttribute = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i;
|
|
2545
|
+
var absent = /* @__PURE__ */ Symbol("absent");
|
|
2546
|
+
var deferred = /* @__PURE__ */ Symbol("deferred");
|
|
2547
|
+
function readAttribute(selection, name) {
|
|
2548
|
+
const node = selection[0];
|
|
2549
|
+
if (typeof node !== "object" || node === null) return absent;
|
|
2550
|
+
const state = node[VIEW_STATE];
|
|
2551
|
+
if (state === void 0 || node[VIEW_SELF] !== node) return typeof node.type === "string" ? deferred : absent;
|
|
2552
|
+
const local = node[VIEW_LOCAL];
|
|
2553
|
+
const snapshot = plainSnapshot(state, local);
|
|
2554
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
2555
|
+
const type = snapshot ? snapshot.typeOf(local) : record?.type;
|
|
2556
|
+
if (type === void 0 || !elementTypes.has(type)) return absent;
|
|
2557
|
+
const value = attributeAt(state, local, name);
|
|
2558
|
+
if (value === void 0) {
|
|
2559
|
+
const attributes = record?.attribs;
|
|
2560
|
+
if (attributes && Object.hasOwn(attributes, name)) return deferred;
|
|
2561
|
+
return name === "value" ? deferred : absent;
|
|
2562
|
+
}
|
|
2563
|
+
const options = selection.options ?? {};
|
|
2564
|
+
const isXml = options.xmlMode ?? (options.xml === true || typeof options.xml === "object" && options.xml !== null);
|
|
2565
|
+
return !isXml && booleanAttribute.test(name) ? name : value;
|
|
2566
|
+
}
|
|
2567
|
+
function setAttribute(selection, ids, name, value) {
|
|
2568
|
+
const document = selection[DOCUMENT];
|
|
2569
|
+
if (document.setAttribute) document.setAttribute(ids, name, value);
|
|
2570
|
+
else selection.op("attr", { ids, name, value });
|
|
2571
|
+
}
|
|
1453
2572
|
function isElement(selection, id) {
|
|
1454
|
-
return ["tag", "script", "style"].includes(nodeRecord(selection
|
|
2573
|
+
return ["tag", "script", "style"].includes(nodeRecord(selection[DOCUMENT], id)?.type);
|
|
1455
2574
|
}
|
|
1456
2575
|
function nativeValue(value) {
|
|
1457
2576
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
@@ -1474,18 +2593,10 @@ function hydrateValue(value) {
|
|
|
1474
2593
|
return value;
|
|
1475
2594
|
}
|
|
1476
2595
|
function dataObject(selection, id) {
|
|
1477
|
-
const document = selection
|
|
1478
|
-
|
|
1479
|
-
let documents = dataObjects.get(cacheKey);
|
|
1480
|
-
if (!documents) dataObjects.set(cacheKey, documents = /* @__PURE__ */ new Map());
|
|
1481
|
-
const existingReference = documents.get(id);
|
|
1482
|
-
let data2 = existingReference?.deref() ?? document.nodeData?.(id);
|
|
2596
|
+
const document = selection[DOCUMENT];
|
|
2597
|
+
let data2 = document.nodeData?.(id);
|
|
1483
2598
|
if (!data2) {
|
|
1484
|
-
const
|
|
1485
|
-
const dispatch = document.nodeDataOperation?.(id) ?? ((command, args) => {
|
|
1486
|
-
const document2 = documentReference.deref();
|
|
1487
|
-
return document2 ? JSON.parse(document2.op(command, JSON.stringify(args))) : void 0;
|
|
1488
|
-
});
|
|
2599
|
+
const dispatch = document.nodeDataOperation?.(id) ?? ((command, args) => JSON.parse(document.op(command, JSON.stringify(args))));
|
|
1489
2600
|
const target = {};
|
|
1490
2601
|
data2 = new Proxy(target, {
|
|
1491
2602
|
set(object, name, value) {
|
|
@@ -1504,28 +2615,26 @@ function dataObject(selection, id) {
|
|
|
1504
2615
|
return true;
|
|
1505
2616
|
}
|
|
1506
2617
|
});
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
2618
|
+
document.retainNodeData?.(id, data2);
|
|
2619
|
+
}
|
|
2620
|
+
const node = getNode(selection[DOCUMENT], id);
|
|
2621
|
+
if (!Object.hasOwn(node, "data")) {
|
|
2622
|
+
const values = data2;
|
|
2623
|
+
Object.defineProperty(node, "data", { configurable: true, enumerable: true, get: () => values, set: (value) => {
|
|
2624
|
+
for (const key of Object.keys(values)) delete values[key];
|
|
2625
|
+
for (const key of Object.keys(value ?? {})) values[key] = value[key];
|
|
1511
2626
|
} });
|
|
1512
2627
|
}
|
|
1513
|
-
if (existingReference?.deref() !== data2) {
|
|
1514
|
-
const reference = new WeakRef(data2);
|
|
1515
|
-
documents.set(id, reference);
|
|
1516
|
-
dataFinalizer.register(data2, { cache: new WeakRef(documents), id, reference });
|
|
1517
|
-
}
|
|
1518
|
-
document.retainNodeData?.(id, data2);
|
|
1519
2628
|
return data2;
|
|
1520
2629
|
}
|
|
1521
2630
|
function property(selection, id, name, raw = false) {
|
|
1522
2631
|
const result = selection.op("prop", { ids: [id], name, ...raw ? { raw: true } : {} });
|
|
1523
2632
|
if (name === "sourceCodeLocation") return hydrateLocation(result);
|
|
1524
|
-
return result?.__nativeNodeProperty ? getNode(selection
|
|
2633
|
+
return result?.__nativeNodeProperty ? getNode(selection[DOCUMENT], id)[result.__nativeNodeProperty] : result === null ? void 0 : result;
|
|
1525
2634
|
}
|
|
1526
2635
|
function propertyValue(selection, name, value) {
|
|
1527
|
-
if (name === "children" || name === "childNodes") return importNodes(selection
|
|
1528
|
-
if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(name)) return value == null ? null : importNodes(selection
|
|
2636
|
+
if (name === "children" || name === "childNodes") return importNodes(selection[DOCUMENT], value);
|
|
2637
|
+
if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(name)) return value == null ? null : importNodes(selection[DOCUMENT], [value])[0] ?? null;
|
|
1529
2638
|
return value;
|
|
1530
2639
|
}
|
|
1531
2640
|
function attr(name, value) {
|
|
@@ -1534,22 +2643,27 @@ function attr(name, value) {
|
|
|
1534
2643
|
if (typeof name !== "string") throw new Error("Bad combination of arguments.");
|
|
1535
2644
|
this.ids.forEach((id, index) => {
|
|
1536
2645
|
if (!isElement(this, id)) return;
|
|
1537
|
-
const node = getNode(this
|
|
2646
|
+
const node = getNode(this[DOCUMENT], id);
|
|
1538
2647
|
const current = node.attribs[name];
|
|
1539
2648
|
const next = value.call(node, index, current);
|
|
1540
|
-
this
|
|
2649
|
+
setAttribute(this, [id], name, next === null ? null : String(next));
|
|
1541
2650
|
});
|
|
1542
2651
|
} else if (typeof name === "object") {
|
|
1543
|
-
for (const key of Object.keys(name)) this
|
|
2652
|
+
for (const key of Object.keys(name)) setAttribute(this, this.ids, key, name[key] === null ? null : String(name[key]));
|
|
1544
2653
|
} else {
|
|
1545
|
-
this
|
|
2654
|
+
setAttribute(this, this.ids, name, value === null ? null : String(value));
|
|
1546
2655
|
}
|
|
1547
2656
|
return this;
|
|
1548
2657
|
}
|
|
1549
2658
|
if (arguments.length > 1) return this;
|
|
2659
|
+
if (typeof name === "string") {
|
|
2660
|
+
const cached2 = readAttribute(this, name);
|
|
2661
|
+
if (cached2 === absent) return void 0;
|
|
2662
|
+
if (cached2 !== deferred) return cached2;
|
|
2663
|
+
}
|
|
1550
2664
|
const result = this.op("attr", { ids: this.ids, ...typeof name === "string" ? { name } : {} });
|
|
1551
2665
|
if (result === null) return void 0;
|
|
1552
|
-
return !name && this.ids.length ? getNode(this
|
|
2666
|
+
return !name && this.ids.length ? getNode(this[DOCUMENT], this.ids[0]).attribs : result;
|
|
1553
2667
|
}
|
|
1554
2668
|
function prop(name, value) {
|
|
1555
2669
|
if (typeof name === "string" && value === void 0) return this.ids.length ? property(this, this.ids[0], name) : void 0;
|
|
@@ -1558,7 +2672,7 @@ function prop(name, value) {
|
|
|
1558
2672
|
if (typeof name === "object") throw new TypeError("Bad combination of arguments.");
|
|
1559
2673
|
this.ids.forEach((id, index) => {
|
|
1560
2674
|
if (!isElement(this, id)) return;
|
|
1561
|
-
const next = value.call(getNode(this
|
|
2675
|
+
const next = value.call(getNode(this[DOCUMENT], id), index, property(this, id, name, true));
|
|
1562
2676
|
this.op("prop", { ids: [id], name, value: propertyValue(this, name, next) });
|
|
1563
2677
|
});
|
|
1564
2678
|
} else if (typeof name === "object") {
|
|
@@ -1601,7 +2715,7 @@ function css(name, value) {
|
|
|
1601
2715
|
for (const id of this.ids) {
|
|
1602
2716
|
if (!isElement(this, id)) continue;
|
|
1603
2717
|
const current = this.op("css", { ids: [id], name: key }) ?? void 0;
|
|
1604
|
-
const next = name[key].call(getNode(this
|
|
2718
|
+
const next = name[key].call(getNode(this[DOCUMENT], id), propertyIndex, current);
|
|
1605
2719
|
this.op("css", { ids: [id], name: key, value: next == null ? null : String(next) });
|
|
1606
2720
|
}
|
|
1607
2721
|
} else this.op("css", { ids: this.ids, name: key, value: name[key] == null ? null : String(name[key]) });
|
|
@@ -1610,7 +2724,7 @@ function css(name, value) {
|
|
|
1610
2724
|
this.ids.forEach((id, index) => {
|
|
1611
2725
|
if (!isElement(this, id)) return;
|
|
1612
2726
|
const current = this.op("css", { ids: [id], name }) ?? void 0;
|
|
1613
|
-
const next = value.call(getNode(this
|
|
2727
|
+
const next = value.call(getNode(this[DOCUMENT], id), index, current);
|
|
1614
2728
|
this.op("css", { ids: [id], name, value: next == null ? null : String(next) });
|
|
1615
2729
|
});
|
|
1616
2730
|
} else if (typeof name === "string") this.op("css", { ids: this.ids, name, value: value == null ? null : String(value) });
|
|
@@ -1623,7 +2737,7 @@ function classMethod(command) {
|
|
|
1623
2737
|
if (typeof name === "function") {
|
|
1624
2738
|
this.ids.forEach((id, index) => {
|
|
1625
2739
|
if (!isElement(this, id)) return;
|
|
1626
|
-
const node = getNode(this
|
|
2740
|
+
const node = getNode(this[DOCUMENT], id);
|
|
1627
2741
|
const next = command === "toggleClass" ? name.call(node, index, node.attribs.class ?? "", state) : name.call(node, index, node.attribs.class ?? "");
|
|
1628
2742
|
if (typeof next === "string") this.op(command, { ids: [id], name: next, ...typeof state === "boolean" ? { state } : {} });
|
|
1629
2743
|
});
|
|
@@ -1640,7 +2754,8 @@ function installAttributes(CheerioClass) {
|
|
|
1640
2754
|
data,
|
|
1641
2755
|
css,
|
|
1642
2756
|
removeAttr(name) {
|
|
1643
|
-
|
|
2757
|
+
const ids = this.ids;
|
|
2758
|
+
for (const single of String(name).split(/\s+/)) if (single) setAttribute(this, ids, single, null);
|
|
1644
2759
|
return this;
|
|
1645
2760
|
},
|
|
1646
2761
|
hasClass(name) {
|
|
@@ -1668,9 +2783,9 @@ function parseWithNative(content, options, isDocument2, context) {
|
|
|
1668
2783
|
if (!isDocument2 && context) {
|
|
1669
2784
|
const document2 = nodeBinding(context)?.document ?? routeDocument(new (requireNative()).NativeDocument("", false, JSON.stringify(cleanParserOptions(options))), options);
|
|
1670
2785
|
const contextId = importNodes(document2, [context])[0];
|
|
1671
|
-
const
|
|
2786
|
+
const children = operation(document2, "create", { html: content, contextId, options });
|
|
1672
2787
|
const root = operation(document2, "createNode", { type: "root", options });
|
|
1673
|
-
operation(document2, "setNode", { id: root, field: "children", value:
|
|
2788
|
+
operation(document2, "setNode", { id: root, field: "children", value: children, options });
|
|
1674
2789
|
return getNode(document2, root);
|
|
1675
2790
|
}
|
|
1676
2791
|
const document = parseNativeDocument(content, options, isDocument2);
|
|
@@ -1683,7 +2798,7 @@ function parseWithHtmlparser2(content, options) {
|
|
|
1683
2798
|
return parseWithNative(content, { ...options, _useHtmlParser2: true }, false, null);
|
|
1684
2799
|
}
|
|
1685
2800
|
function getParse(parser) {
|
|
1686
|
-
return function
|
|
2801
|
+
return function parse3(content, options, isDocument2, context) {
|
|
1687
2802
|
if (Buffer.isBuffer(content)) content = content.toString();
|
|
1688
2803
|
if (typeof content === "string") return parser(content, options, isDocument2, context);
|
|
1689
2804
|
if (!Array.isArray(content) && content.type === "root" && nodeBinding(content)) return content;
|
|
@@ -1696,6 +2811,183 @@ function getParse(parser) {
|
|
|
1696
2811
|
}
|
|
1697
2812
|
var parse = getParse((content, options, isDocument2, context) => options._useHtmlParser2 ? parseWithHtmlparser2(content, options) : parseWithParse5(content, options, isDocument2, context));
|
|
1698
2813
|
|
|
2814
|
+
// src/match.ts
|
|
2815
|
+
var compiled = /* @__PURE__ */ new Map();
|
|
2816
|
+
var compiledLimit = 512;
|
|
2817
|
+
function matchSimpleSelector(document, ids, selector, options) {
|
|
2818
|
+
if (!isRouted(document)) return void 0;
|
|
2819
|
+
const compounds = compile(selector);
|
|
2820
|
+
if (!compounds) return void 0;
|
|
2821
|
+
const isXml = isXmlMode(options);
|
|
2822
|
+
const isLowerCaseTags = options.lowerCaseTags ?? !isXml;
|
|
2823
|
+
const isLowerCaseAttributes = options.lowerCaseAttributeNames ?? !isXml;
|
|
2824
|
+
const result = [];
|
|
2825
|
+
for (const id of ids) {
|
|
2826
|
+
const state = stateIn(document, id);
|
|
2827
|
+
if (!sameMatchOptions(state.options, isXml, isLowerCaseTags, isLowerCaseAttributes)) return void 0;
|
|
2828
|
+
const local = id - state.base;
|
|
2829
|
+
for (const compound of compounds) {
|
|
2830
|
+
if (matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes)) {
|
|
2831
|
+
result.push(id);
|
|
2832
|
+
break;
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
return result;
|
|
2837
|
+
}
|
|
2838
|
+
var walkBudget = 4096;
|
|
2839
|
+
var smallDocumentNodes = 512;
|
|
2840
|
+
var tinyDocumentNodes = 64;
|
|
2841
|
+
function selectSimpleWithin(document, contexts, selector, options) {
|
|
2842
|
+
if (contexts.length !== 1 || !isRouted(document)) return void 0;
|
|
2843
|
+
const compounds = compile(selector);
|
|
2844
|
+
if (!compounds) return void 0;
|
|
2845
|
+
const isXml = isXmlMode(options);
|
|
2846
|
+
const isLowerCaseTags = options.lowerCaseTags ?? !isXml;
|
|
2847
|
+
const isLowerCaseAttributes = options.lowerCaseAttributeNames ?? !isXml;
|
|
2848
|
+
const state = stateIn(document, contexts[0]);
|
|
2849
|
+
if (!sameMatchOptions(state.options, isXml, isLowerCaseTags, isLowerCaseAttributes)) return void 0;
|
|
2850
|
+
const context = contexts[0] - state.base;
|
|
2851
|
+
const size = Math.max(state.baseline, state.snapshotSize);
|
|
2852
|
+
const isDocumentRoot = context === (state.rootLocal ??= state.raw.rootId());
|
|
2853
|
+
const contextType = isDocumentRoot ? "root" : typeAt(state, context);
|
|
2854
|
+
const isReadable = state.bulk instanceof NodeSnapshot ? size <= smallDocumentNodes : state.generation === 0 && size <= tinyDocumentNodes;
|
|
2855
|
+
const isSmallRoot = contextType === "root" && isReadable;
|
|
2856
|
+
if (!isElementType2(contextType) && !isSmallRoot) return void 0;
|
|
2857
|
+
const result = [];
|
|
2858
|
+
const stack = [];
|
|
2859
|
+
pushChildren(state, context, stack);
|
|
2860
|
+
for (let visited = 0; stack.length; visited++) {
|
|
2861
|
+
if (visited === walkBudget) return void 0;
|
|
2862
|
+
const local = stack.pop();
|
|
2863
|
+
const type = typeAt(state, local);
|
|
2864
|
+
if (type === "root") {
|
|
2865
|
+
if (isSmallRoot) return void 0;
|
|
2866
|
+
continue;
|
|
2867
|
+
}
|
|
2868
|
+
if (isElementType2(type)) {
|
|
2869
|
+
for (const compound of compounds) {
|
|
2870
|
+
if (matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes)) {
|
|
2871
|
+
result.push(state.base + local);
|
|
2872
|
+
break;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
pushChildren(state, local, stack);
|
|
2877
|
+
}
|
|
2878
|
+
return result;
|
|
2879
|
+
}
|
|
2880
|
+
var isElementType2 = (type) => type === "tag" || type === "script" || type === "style";
|
|
2881
|
+
function typeAt(state, local) {
|
|
2882
|
+
const snapshot = plainSnapshot(state, local);
|
|
2883
|
+
return snapshot ? snapshot.typeOf(local) : recordAt(state, local)?.type;
|
|
2884
|
+
}
|
|
2885
|
+
function pushChildren(state, local, stack) {
|
|
2886
|
+
const snapshot = plainSnapshot(state, local);
|
|
2887
|
+
if (snapshot) {
|
|
2888
|
+
for (let index = snapshot.childCount(local) - 1; index >= 0; index--) stack.push(snapshot.childAt(local, index));
|
|
2889
|
+
return;
|
|
2890
|
+
}
|
|
2891
|
+
const children = recordAt(state, local)?.children ?? [];
|
|
2892
|
+
for (let index = children.length - 1; index >= 0; index--) stack.push(children[index]);
|
|
2893
|
+
}
|
|
2894
|
+
function isXmlMode(options) {
|
|
2895
|
+
return options.xmlMode ?? (options.xml === true || typeof options.xml === "object" && options.xml !== null);
|
|
2896
|
+
}
|
|
2897
|
+
function sameMatchOptions(documentOptions, isXml, isLowerCaseTags, isLowerCaseAttributes) {
|
|
2898
|
+
const isDocumentXml = isXmlMode(documentOptions);
|
|
2899
|
+
return isDocumentXml === isXml && (documentOptions.lowerCaseTags ?? !isDocumentXml) === isLowerCaseTags && (documentOptions.lowerCaseAttributeNames ?? !isDocumentXml) === isLowerCaseAttributes;
|
|
2900
|
+
}
|
|
2901
|
+
function matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes) {
|
|
2902
|
+
const snapshot = plainSnapshot(state, local);
|
|
2903
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
2904
|
+
if (!snapshot && !record) return false;
|
|
2905
|
+
if (!isElementType2(snapshot ? snapshot.typeOf(local) : record.type)) return false;
|
|
2906
|
+
if (compound.tag !== void 0 && (snapshot ? snapshot.nameOf(local) : record.name) !== (isLowerCaseTags ? compound.lowerTag : compound.tag)) return false;
|
|
2907
|
+
for (const id of compound.ids) if (attributeAt(state, local, "id") !== id) return false;
|
|
2908
|
+
if (compound.classes.length) {
|
|
2909
|
+
const classes = attributeAt(state, local, "class");
|
|
2910
|
+
if (classes === void 0) return false;
|
|
2911
|
+
for (const name of compound.classes) if (!hasClass(classes, name)) return false;
|
|
2912
|
+
}
|
|
2913
|
+
for (const name of isLowerCaseAttributes ? compound.lowerAttributes : compound.attributes) if (attributeAt(state, local, name) === void 0) return false;
|
|
2914
|
+
return true;
|
|
2915
|
+
}
|
|
2916
|
+
var isAsciiWhitespace = (code) => code === 32 || code === 9 || code === 10 || code === 12 || code === 13;
|
|
2917
|
+
function hasClass(classes, name) {
|
|
2918
|
+
for (let start = classes.indexOf(name); start !== -1; start = classes.indexOf(name, start + 1)) {
|
|
2919
|
+
const end = start + name.length;
|
|
2920
|
+
if ((start === 0 || isAsciiWhitespace(classes.charCodeAt(start - 1))) && (end === classes.length || isAsciiWhitespace(classes.charCodeAt(end)))) return true;
|
|
2921
|
+
}
|
|
2922
|
+
return false;
|
|
2923
|
+
}
|
|
2924
|
+
function asciiLowerCase(value) {
|
|
2925
|
+
return /[A-Z]/.test(value) ? value.replace(/[A-Z]/g, (letter) => letter.toLowerCase()) : value;
|
|
2926
|
+
}
|
|
2927
|
+
function compile(selector) {
|
|
2928
|
+
const cached2 = compiled.get(selector);
|
|
2929
|
+
if (cached2 !== void 0) return cached2;
|
|
2930
|
+
const result = parse2(selector);
|
|
2931
|
+
if (compiled.size >= compiledLimit) compiled.clear();
|
|
2932
|
+
compiled.set(selector, result);
|
|
2933
|
+
return result;
|
|
2934
|
+
}
|
|
2935
|
+
var identifierStart = /[A-Za-z_]/;
|
|
2936
|
+
var identifierPart = /[A-Za-z0-9_-]/;
|
|
2937
|
+
function parse2(selector) {
|
|
2938
|
+
const compounds = [];
|
|
2939
|
+
let index = 0;
|
|
2940
|
+
const skipSpace = () => {
|
|
2941
|
+
while (index < selector.length && isAsciiWhitespace(selector.charCodeAt(index))) index++;
|
|
2942
|
+
};
|
|
2943
|
+
const identifier = () => {
|
|
2944
|
+
const start = index;
|
|
2945
|
+
if (selector[index] === "-") index++;
|
|
2946
|
+
if (!identifierStart.test(selector[index] ?? "")) return null;
|
|
2947
|
+
while (index < selector.length && identifierPart.test(selector[index])) index++;
|
|
2948
|
+
return selector.slice(start, index);
|
|
2949
|
+
};
|
|
2950
|
+
for (; ; ) {
|
|
2951
|
+
skipSpace();
|
|
2952
|
+
const compound = { tag: void 0, lowerTag: void 0, ids: [], classes: [], attributes: [], lowerAttributes: [] };
|
|
2953
|
+
let hasPart = false;
|
|
2954
|
+
if (selector[index] === "*") {
|
|
2955
|
+
index++;
|
|
2956
|
+
hasPart = true;
|
|
2957
|
+
} else if (/[A-Za-z]/.test(selector[index] ?? "")) {
|
|
2958
|
+
compound.tag = identifier();
|
|
2959
|
+
hasPart = true;
|
|
2960
|
+
}
|
|
2961
|
+
for (; ; ) {
|
|
2962
|
+
const character = selector[index];
|
|
2963
|
+
if (character === "#" || character === ".") {
|
|
2964
|
+
index++;
|
|
2965
|
+
const name = identifier();
|
|
2966
|
+
if (name === null) return null;
|
|
2967
|
+
(character === "#" ? compound.ids : compound.classes).push(name);
|
|
2968
|
+
} else if (character === "[") {
|
|
2969
|
+
index++;
|
|
2970
|
+
skipSpace();
|
|
2971
|
+
const name = identifier();
|
|
2972
|
+
if (name === null) return null;
|
|
2973
|
+
skipSpace();
|
|
2974
|
+
if (selector[index] !== "]") return null;
|
|
2975
|
+
index++;
|
|
2976
|
+
compound.attributes.push(name);
|
|
2977
|
+
} else break;
|
|
2978
|
+
hasPart = true;
|
|
2979
|
+
}
|
|
2980
|
+
if (!hasPart) return null;
|
|
2981
|
+
compound.lowerTag = compound.tag === void 0 ? void 0 : asciiLowerCase(compound.tag);
|
|
2982
|
+
compound.lowerAttributes = compound.attributes.map(asciiLowerCase);
|
|
2983
|
+
compounds.push(compound);
|
|
2984
|
+
skipSpace();
|
|
2985
|
+
if (index === selector.length) return compounds;
|
|
2986
|
+
if (selector[index] !== ",") return null;
|
|
2987
|
+
index++;
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
|
|
1699
2991
|
// src/selection.ts
|
|
1700
2992
|
var numeric = /^(?:0|[1-9]\d*)$/;
|
|
1701
2993
|
var isMarkup = (value) => /<[a-zA-Z!/?]/.test(value);
|
|
@@ -1767,103 +3059,166 @@ function* customPseudoArguments(selector, name) {
|
|
|
1767
3059
|
index = end;
|
|
1768
3060
|
}
|
|
1769
3061
|
}
|
|
3062
|
+
var isIndex = (property2) => {
|
|
3063
|
+
if (typeof property2 !== "string") return false;
|
|
3064
|
+
const first = property2.charCodeAt(0);
|
|
3065
|
+
return first >= 48 && first <= 57 && numeric.test(property2);
|
|
3066
|
+
};
|
|
3067
|
+
var plainSelectionLimit = 16;
|
|
3068
|
+
var lengthOf = (target) => target[VALUES]?.length ?? target[IDS].length;
|
|
3069
|
+
function nodeAt(target, index) {
|
|
3070
|
+
if (target[VALUES]) return target[VALUES][index];
|
|
3071
|
+
const id = target[IDS][index];
|
|
3072
|
+
return id === void 0 ? void 0 : getNode(target[DOCUMENT], id);
|
|
3073
|
+
}
|
|
3074
|
+
function releaseIds(target) {
|
|
3075
|
+
if (target[LEASE]) updateLease(target[DOCUMENT], target[LEASE], target[VALUES] ? [] : target[IDS]);
|
|
3076
|
+
}
|
|
3077
|
+
function writeIndex(target, index, value) {
|
|
3078
|
+
if (target[VALUES]) target[VALUES][index] = value;
|
|
3079
|
+
else {
|
|
3080
|
+
const id = importNodes(target[DOCUMENT], [value])[0];
|
|
3081
|
+
if (id === void 0) {
|
|
3082
|
+
target[VALUES] = target[IDS].map((existing) => getNode(target[DOCUMENT], existing));
|
|
3083
|
+
target[VALUES][index] = value;
|
|
3084
|
+
} else target[IDS][index] = id;
|
|
3085
|
+
}
|
|
3086
|
+
releaseIds(target);
|
|
3087
|
+
}
|
|
3088
|
+
var selectionHandler = {
|
|
3089
|
+
get: (target, property2) => isIndex(property2) ? nodeAt(target, Number(property2)) : property2 === "length" ? lengthOf(target) : Reflect.get(target, property2),
|
|
3090
|
+
set: (target, property2, value) => {
|
|
3091
|
+
if (isIndex(property2)) {
|
|
3092
|
+
writeIndex(target, Number(property2), value);
|
|
3093
|
+
return true;
|
|
3094
|
+
}
|
|
3095
|
+
if (property2 === "length") {
|
|
3096
|
+
if (target[VALUES]) target[VALUES].length = value;
|
|
3097
|
+
else target[IDS].length = value;
|
|
3098
|
+
releaseIds(target);
|
|
3099
|
+
return true;
|
|
3100
|
+
}
|
|
3101
|
+
return Reflect.set(target, property2, value);
|
|
3102
|
+
},
|
|
3103
|
+
has: (target, property2) => isIndex(property2) ? Number(property2) < lengthOf(target) : property2 === "length" || Reflect.has(target, property2),
|
|
3104
|
+
ownKeys: (target) => [...Array.from({ length: lengthOf(target) }, (_, i) => String(i)), "length", ...Reflect.ownKeys(target)],
|
|
3105
|
+
getOwnPropertyDescriptor: (target, property2) => {
|
|
3106
|
+
if (isIndex(property2) && Number(property2) < lengthOf(target))
|
|
3107
|
+
return { value: nodeAt(target, Number(property2)), writable: true, configurable: true, enumerable: true };
|
|
3108
|
+
if (property2 === "length") return { value: lengthOf(target), writable: true, configurable: true, enumerable: true };
|
|
3109
|
+
return Reflect.getOwnPropertyDescriptor(target, property2);
|
|
3110
|
+
},
|
|
3111
|
+
deleteProperty: (target, property2) => {
|
|
3112
|
+
if (isIndex(property2)) {
|
|
3113
|
+
if (target[VALUES])
|
|
3114
|
+
delete target[VALUES][Number(property2)];
|
|
3115
|
+
else
|
|
3116
|
+
delete target[IDS][Number(property2)];
|
|
3117
|
+
releaseIds(target);
|
|
3118
|
+
return true;
|
|
3119
|
+
}
|
|
3120
|
+
return Reflect.deleteProperty(target, property2);
|
|
3121
|
+
}
|
|
3122
|
+
};
|
|
1770
3123
|
var Cheerio = class {
|
|
1771
|
-
|
|
3124
|
+
/** @internal */
|
|
3125
|
+
get _document() {
|
|
3126
|
+
return this[DOCUMENT];
|
|
3127
|
+
}
|
|
3128
|
+
/** @internal */
|
|
3129
|
+
get _api() {
|
|
3130
|
+
return this[API];
|
|
3131
|
+
}
|
|
3132
|
+
/** @internal */
|
|
3133
|
+
get _ids() {
|
|
3134
|
+
return this[IDS];
|
|
3135
|
+
}
|
|
1772
3136
|
constructor(api, document, ids = [], root = null, options = {}, values) {
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
return new Proxy(this,
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
1805
|
-
return true;
|
|
1806
|
-
}
|
|
1807
|
-
return Reflect.set(target, property2, value, receiver);
|
|
1808
|
-
},
|
|
1809
|
-
has: (target, property2) => typeof property2 === "string" && numeric.test(property2) ? Number(property2) < target.length : Reflect.has(target, property2),
|
|
1810
|
-
ownKeys: (target) => [...Array.from({ length: target.length }, (_, i) => String(i)), ...Reflect.ownKeys(target)],
|
|
1811
|
-
getOwnPropertyDescriptor: (target, property2) => typeof property2 === "string" && numeric.test(property2) && Number(property2) < target.length ? { value: target._values ? target._values[Number(property2)] : getNode(document, target._ids[Number(property2)]), writable: true, configurable: true, enumerable: true } : Reflect.getOwnPropertyDescriptor(target, property2),
|
|
1812
|
-
deleteProperty: (target, property2) => {
|
|
1813
|
-
if (typeof property2 === "string" && numeric.test(property2)) {
|
|
1814
|
-
if (target._values)
|
|
1815
|
-
delete target._values[Number(property2)];
|
|
1816
|
-
else
|
|
1817
|
-
delete target._ids[Number(property2)];
|
|
1818
|
-
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
1819
|
-
return true;
|
|
1820
|
-
}
|
|
1821
|
-
return Reflect.deleteProperty(target, property2);
|
|
1822
|
-
}
|
|
1823
|
-
});
|
|
3137
|
+
this[DOCUMENT] = document;
|
|
3138
|
+
this[API] = api;
|
|
3139
|
+
this[IDS] = ids;
|
|
3140
|
+
this[VALUES] = values;
|
|
3141
|
+
this[LEASE] = void 0;
|
|
3142
|
+
const count = values ? values.length : ids.length;
|
|
3143
|
+
const isPlain = count <= plainSelectionLimit;
|
|
3144
|
+
this[IS_PLAIN] = isPlain;
|
|
3145
|
+
if (isPlain) this.length = count;
|
|
3146
|
+
this.options = options;
|
|
3147
|
+
this._root = root;
|
|
3148
|
+
if (isPlain) {
|
|
3149
|
+
if (values) for (let index = 0; index < count; index++) this[index] = values[index];
|
|
3150
|
+
else for (let index = 0; index < count; index++) this[index] = getNode(document, ids[index]);
|
|
3151
|
+
return;
|
|
3152
|
+
}
|
|
3153
|
+
if (!values) this[LEASE] = leaseNodes(document, this, ids);
|
|
3154
|
+
return new Proxy(this, selectionHandler);
|
|
3155
|
+
}
|
|
3156
|
+
/** @internal Re-reads a plain selection after direct index writes or after its nodes moved documents. */
|
|
3157
|
+
_syncIndices() {
|
|
3158
|
+
const length = this.length;
|
|
3159
|
+
const values = this[VALUES];
|
|
3160
|
+
const ids = this[IDS];
|
|
3161
|
+
let isChanged = (values ?? ids).length !== length;
|
|
3162
|
+
for (let index = 0; !isChanged && index < length; index++) isChanged = values ? this[index] !== values[index] : viewId(this[index]) !== ids[index];
|
|
3163
|
+
if (!isChanged) return;
|
|
3164
|
+
const items = Array.from({ length }, (_unused, index) => this[index]);
|
|
3165
|
+
const isAllNodes = items.every((value) => value && typeof value === "object" && typeof value.type === "string");
|
|
3166
|
+
this[VALUES] = isAllNodes ? void 0 : items;
|
|
3167
|
+
this[IDS] = isAllNodes ? importNodes(this[DOCUMENT], items) : [];
|
|
1824
3168
|
}
|
|
1825
3169
|
/** @internal */
|
|
1826
3170
|
get ids() {
|
|
1827
|
-
|
|
3171
|
+
if (this[IS_PLAIN]) this._syncIndices();
|
|
3172
|
+
return this[VALUES] ? importNodes(this[DOCUMENT], this[VALUES]) : this[IDS];
|
|
1828
3173
|
}
|
|
1829
3174
|
/** @internal */
|
|
1830
3175
|
op(command, args = {}) {
|
|
1831
3176
|
const values = args;
|
|
1832
|
-
return operation(this
|
|
3177
|
+
return operation(this[DOCUMENT], command, { ...values, options: values.options ?? this.options });
|
|
1833
3178
|
}
|
|
1834
3179
|
/** @internal */
|
|
1835
3180
|
_query(command, args) {
|
|
1836
|
-
const
|
|
1837
|
-
|
|
1838
|
-
|
|
3181
|
+
const pseudos = this.options.pseudos;
|
|
3182
|
+
const callbacks = pseudos ? Object.entries(pseudos).filter((entry) => typeof entry[1] === "function") : [];
|
|
3183
|
+
if (!callbacks.length) {
|
|
3184
|
+
if (command === "matches" && args.ids) {
|
|
3185
|
+
const matched = matchSimpleSelector(this[DOCUMENT], args.ids, args.selector, args.options ?? this.options);
|
|
3186
|
+
if (matched) return matched;
|
|
3187
|
+
}
|
|
3188
|
+
if (command === "select" && args.contexts) {
|
|
3189
|
+
const found = selectSimpleWithin(this[DOCUMENT], args.contexts, args.selector, args.options ?? this.options);
|
|
3190
|
+
if (found) return found;
|
|
3191
|
+
}
|
|
3192
|
+
return command === "select" && !args.options ? this[DOCUMENT].select(args.selector, args.contexts) : this.op(command, args);
|
|
3193
|
+
}
|
|
1839
3194
|
const pseudoMatches = {};
|
|
1840
|
-
const candidates = [.../* @__PURE__ */ new Set([...this.
|
|
3195
|
+
const candidates = [.../* @__PURE__ */ new Set([...this[DOCUMENT].select("*"), ...args.ids ?? [], ...args.contexts ? this[DOCUMENT].select("*", args.contexts) : []])];
|
|
1841
3196
|
for (const [name, callback] of callbacks) {
|
|
1842
3197
|
for (const argument of customPseudoArguments(args.selector, name)) {
|
|
1843
3198
|
if (argument !== void 0 && callback.length < 2)
|
|
1844
3199
|
throw new Error(`Pseudo-class :${name} doesn't have any arguments`);
|
|
1845
3200
|
if (argument === void 0 && callback.length >= 2)
|
|
1846
3201
|
throw new Error(`Pseudo-class :${name} requires an argument`);
|
|
1847
|
-
pseudoMatches[`${name}(${argument ?? ""})`] = candidates.filter((id) => callback(getNode(this
|
|
3202
|
+
pseudoMatches[`${name}(${argument ?? ""})`] = candidates.filter((id) => callback(getNode(this[DOCUMENT], id), argument ?? null));
|
|
1848
3203
|
}
|
|
1849
3204
|
}
|
|
1850
3205
|
return this.op(command, { ...args, pseudoMatches });
|
|
1851
3206
|
}
|
|
1852
3207
|
/** @internal */
|
|
1853
3208
|
_fromIds(ids) {
|
|
1854
|
-
const result = new this.
|
|
3209
|
+
const result = new this[API].fn.constructor(this[API], this[DOCUMENT], ids, this._root, this.options);
|
|
1855
3210
|
result.prevObject = this;
|
|
1856
3211
|
return result;
|
|
1857
3212
|
}
|
|
1858
3213
|
/** @internal */
|
|
1859
3214
|
_fromValues(values) {
|
|
1860
3215
|
const allNodes = values.every((value) => value && typeof value === "object" && typeof value.type === "string");
|
|
1861
|
-
const result = new this.
|
|
3216
|
+
const result = new this[API].fn.constructor(this[API], this[DOCUMENT], allNodes ? importNodes(this[DOCUMENT], values) : [], this._root, this.options, allNodes ? void 0 : values);
|
|
1862
3217
|
result.prevObject = this;
|
|
1863
3218
|
return result;
|
|
1864
3219
|
}
|
|
1865
3220
|
_make(value, context) {
|
|
1866
|
-
const result = typeof value === "string" || value?.cheerio ? this
|
|
3221
|
+
const result = typeof value === "string" || value?.cheerio ? this[API](value, context) : this._fromValues(value == null ? [] : typeof value === "object" && "length" in value && !value.type ? Array.from(value) : [value]);
|
|
1867
3222
|
result.prevObject = this;
|
|
1868
3223
|
return result;
|
|
1869
3224
|
}
|
|
@@ -1871,7 +3226,7 @@ var Cheerio = class {
|
|
|
1871
3226
|
return parse(content, options, isDocument2, context);
|
|
1872
3227
|
}
|
|
1873
3228
|
_render(content) {
|
|
1874
|
-
return this.
|
|
3229
|
+
return this[DOCUMENT].outerHtml(importNodes(this[DOCUMENT], content));
|
|
1875
3230
|
}
|
|
1876
3231
|
/** @internal */
|
|
1877
3232
|
_domIds(content, contextId) {
|
|
@@ -1879,22 +3234,26 @@ var Cheerio = class {
|
|
|
1879
3234
|
return [];
|
|
1880
3235
|
if (typeof content === "string")
|
|
1881
3236
|
return this.op("create", { html: content, contextId, options: this.options });
|
|
1882
|
-
if (content?.cheerio)
|
|
1883
|
-
|
|
3237
|
+
if (content?.cheerio) {
|
|
3238
|
+
if (!content[DOCUMENT] || !sameNodeSpace(this[DOCUMENT], content[DOCUMENT]))
|
|
3239
|
+
return importNodes(this[DOCUMENT], content.toArray());
|
|
3240
|
+
exposeDocumentTo(this[DOCUMENT], content[DOCUMENT]);
|
|
3241
|
+
return content.ids;
|
|
3242
|
+
}
|
|
1884
3243
|
if (typeof content === "object" && "length" in content && !content.type)
|
|
1885
3244
|
return Array.from(content).flatMap((item) => this._domIds(item, contextId));
|
|
1886
|
-
return importNodes(this
|
|
3245
|
+
return importNodes(this[DOCUMENT], [content]);
|
|
1887
3246
|
}
|
|
1888
3247
|
_makeDomArray(content, clone = false) {
|
|
1889
3248
|
const ids = this._domIds(content);
|
|
1890
|
-
return (clone ? this.op("clone", { ids, deep: true }) : ids).map((id) => getNode(this
|
|
3249
|
+
return (clone ? this.op("clone", { ids, deep: true }) : ids).map((id) => getNode(this[DOCUMENT], id));
|
|
1891
3250
|
}
|
|
1892
3251
|
find(selector) {
|
|
1893
3252
|
if (!selector)
|
|
1894
3253
|
return this._fromIds([]);
|
|
1895
3254
|
if (typeof selector === "string")
|
|
1896
3255
|
return this._findBySelector(selector, Infinity);
|
|
1897
|
-
const ids = importNodes(this
|
|
3256
|
+
const ids = importNodes(this[DOCUMENT], selector);
|
|
1898
3257
|
return this._fromIds(ids.filter((id) => this.ids.some((container) => this.op("contains", { container, contained: id }))));
|
|
1899
3258
|
}
|
|
1900
3259
|
_findBySelector(selector, limit) {
|
|
@@ -1907,21 +3266,21 @@ var Cheerio = class {
|
|
|
1907
3266
|
return ids;
|
|
1908
3267
|
if (typeof selector === "string")
|
|
1909
3268
|
return this._query("matches", { ids, selector, options: this.options });
|
|
1910
|
-
return ids.filter((id, index) => this._predicate(selector, getNode(this
|
|
3269
|
+
return ids.filter((id, index) => this._predicate(selector, getNode(this[DOCUMENT], id), index));
|
|
1911
3270
|
}
|
|
1912
3271
|
/** @internal */
|
|
1913
3272
|
_predicate(selector, node, index) {
|
|
1914
3273
|
if (typeof selector === "function")
|
|
1915
3274
|
return !!selector.call(node, index, node);
|
|
1916
3275
|
if (typeof selector === "string")
|
|
1917
|
-
return this._query("matches", { ids: importNodes(this
|
|
3276
|
+
return this._query("matches", { ids: importNodes(this[DOCUMENT], [node]), selector, options: this.options }).length > 0;
|
|
1918
3277
|
if (selector?.cheerio)
|
|
1919
3278
|
return selector.toArray().includes(node);
|
|
1920
3279
|
return node === selector;
|
|
1921
3280
|
}
|
|
1922
3281
|
/** @internal */
|
|
1923
3282
|
_traverse(kind, selector) {
|
|
1924
|
-
let ids = this.op("traverse", { ids: this.ids, kind });
|
|
3283
|
+
let ids = traverseRecords(this[DOCUMENT], this.ids, kind) ?? this.op("traverse", { ids: this.ids, kind });
|
|
1925
3284
|
ids = this._filterIds(ids, selector);
|
|
1926
3285
|
if (this.length > 1 && ids.length > 1) {
|
|
1927
3286
|
if (kind === "parents" || kind === "siblings")
|
|
@@ -1964,8 +3323,8 @@ var Cheerio = class {
|
|
|
1964
3323
|
_until(kind, until, filter) {
|
|
1965
3324
|
let ids = [];
|
|
1966
3325
|
for (const id of this.ids)
|
|
1967
|
-
for (const candidate of this.op("traverse", { ids: [id], kind })) {
|
|
1968
|
-
if (until && this._predicate(until, getNode(this
|
|
3326
|
+
for (const candidate of traverseRecords(this[DOCUMENT], [id], kind) ?? this.op("traverse", { ids: [id], kind })) {
|
|
3327
|
+
if (until && this._predicate(until, getNode(this[DOCUMENT], candidate), ids.length))
|
|
1969
3328
|
break;
|
|
1970
3329
|
ids.push(candidate);
|
|
1971
3330
|
}
|
|
@@ -1988,25 +3347,37 @@ var Cheerio = class {
|
|
|
1988
3347
|
return this._fromIds([]);
|
|
1989
3348
|
const result = [];
|
|
1990
3349
|
for (const id of this.ids) {
|
|
1991
|
-
const record = nodeRecord(this
|
|
1992
|
-
const candidates = [...["tag", "script", "style"].includes(record.type) ? [id] : [], ...this.op("traverse", { ids: [id], kind: "parents" })];
|
|
1993
|
-
const
|
|
3350
|
+
const record = nodeRecord(this[DOCUMENT], id);
|
|
3351
|
+
const candidates = [...["tag", "script", "style"].includes(record.type) ? [id] : [], ...traverseRecords(this[DOCUMENT], [id], "parents") ?? this.op("traverse", { ids: [id], kind: "parents" })];
|
|
3352
|
+
const matched = typeof selector === "string" ? new Set(this._filterIds(candidates, selector)) : void 0;
|
|
3353
|
+
const match = matched ? candidates.find((candidate) => matched.has(candidate)) : candidates.find((candidate) => this._predicate(selector, getNode(this[DOCUMENT], candidate), 0));
|
|
1994
3354
|
if (match !== void 0 && !result.includes(match))
|
|
1995
3355
|
result.push(match);
|
|
1996
3356
|
}
|
|
1997
3357
|
return this._fromIds(result);
|
|
1998
3358
|
}
|
|
1999
3359
|
each(callback) {
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
3360
|
+
if (this[IS_PLAIN]) {
|
|
3361
|
+
const length2 = this.length;
|
|
3362
|
+
for (let i = 0; i < length2; i++)
|
|
3363
|
+
if (callback.call(this[i], i, this[i]) === false)
|
|
3364
|
+
break;
|
|
3365
|
+
return this;
|
|
3366
|
+
}
|
|
3367
|
+
const values = this[VALUES], ids = this[IDS], document = this[DOCUMENT];
|
|
3368
|
+
const length = values ? values.length : ids.length;
|
|
3369
|
+
for (let i = 0; i < length; i++) {
|
|
3370
|
+
const node = values ? values[i] : getNode(document, ids[i]);
|
|
3371
|
+
if (callback.call(node, i, node) === false)
|
|
2003
3372
|
break;
|
|
3373
|
+
}
|
|
2004
3374
|
return this;
|
|
2005
3375
|
}
|
|
2006
3376
|
map(callback) {
|
|
2007
3377
|
const result = [];
|
|
2008
|
-
|
|
2009
|
-
|
|
3378
|
+
const items = this._items();
|
|
3379
|
+
for (let i = 0; i < items.length; i++) {
|
|
3380
|
+
const value = callback.call(items[i], i, items[i]);
|
|
2010
3381
|
if (value != null)
|
|
2011
3382
|
result.push(...Array.isArray(value) ? value : [value]);
|
|
2012
3383
|
}
|
|
@@ -2019,7 +3390,7 @@ var Cheerio = class {
|
|
|
2019
3390
|
const matcher = match;
|
|
2020
3391
|
if (typeof match !== "string")
|
|
2021
3392
|
return nodes.filter((node, index) => typeof matcher === "function" ? matcher.call(node, index, node) : matcher?.cheerio ? matcher.toArray().includes(node) : matcher === node);
|
|
2022
|
-
const document = this?.
|
|
3393
|
+
const document = this?.[DOCUMENT] ?? nodeBinding(root)?.document ?? nodeBinding(nodes[0])?.document ?? routeDocument(new (requireNative()).NativeDocument("", false));
|
|
2023
3394
|
const ids = importNodes(document, nodes);
|
|
2024
3395
|
const selected = new Set(operation(document, "matches", { ids, selector: match, options: { xmlMode } }));
|
|
2025
3396
|
return nodes.filter((node) => {
|
|
@@ -2052,50 +3423,72 @@ var Cheerio = class {
|
|
|
2052
3423
|
return this;
|
|
2053
3424
|
if (index < 0)
|
|
2054
3425
|
index += this.length;
|
|
2055
|
-
|
|
3426
|
+
const item = this._itemAt(index);
|
|
3427
|
+
return this._fromValues(item === void 0 ? [] : [item]);
|
|
2056
3428
|
}
|
|
2057
3429
|
get(index) {
|
|
2058
|
-
return index == null ? this.toArray() : this
|
|
3430
|
+
return index == null ? this.toArray() : this._itemAt(index < 0 ? this.length + index : index);
|
|
2059
3431
|
}
|
|
2060
3432
|
toArray() {
|
|
2061
|
-
return
|
|
3433
|
+
return this._items();
|
|
3434
|
+
}
|
|
3435
|
+
/** @internal Every item, read without a proxy trap per index. */
|
|
3436
|
+
_items() {
|
|
3437
|
+
if (this[IS_PLAIN]) {
|
|
3438
|
+
const length = this.length;
|
|
3439
|
+
const items = new Array(length);
|
|
3440
|
+
for (let i = 0; i < length; i++) items[i] = this[i];
|
|
3441
|
+
return items;
|
|
3442
|
+
}
|
|
3443
|
+
const values = this[VALUES], ids = this[IDS], document = this[DOCUMENT];
|
|
3444
|
+
return values ? values.slice() : ids.map((id) => getNode(document, id));
|
|
3445
|
+
}
|
|
3446
|
+
/** @internal */
|
|
3447
|
+
_itemAt(index) {
|
|
3448
|
+
if (this[IS_PLAIN]) return this[index];
|
|
3449
|
+
const values = this[VALUES];
|
|
3450
|
+
if (values) return values[index];
|
|
3451
|
+
const id = this[IDS][index];
|
|
3452
|
+
return id === void 0 ? void 0 : getNode(this[DOCUMENT], id);
|
|
2062
3453
|
}
|
|
2063
3454
|
slice(start, end) {
|
|
2064
|
-
|
|
3455
|
+
const ids = this.ids;
|
|
3456
|
+
return this[VALUES] ? this._fromValues(this[VALUES].slice(start, end)) : this._fromIds(ids.slice(start, end));
|
|
2065
3457
|
}
|
|
2066
3458
|
end() {
|
|
2067
3459
|
return this.prevObject ?? this._make([]);
|
|
2068
3460
|
}
|
|
2069
3461
|
add(other, context) {
|
|
2070
|
-
|
|
3462
|
+
const added = this[API](other, context);
|
|
3463
|
+
const addedIds = added[DOCUMENT] && sameNodeSpace(this[DOCUMENT], added[DOCUMENT]) ? added.ids : importNodes(this[DOCUMENT], added.toArray());
|
|
3464
|
+
return this._fromIds(this.op("uniqueSort", { ids: [...this.ids, ...addedIds] }));
|
|
2071
3465
|
}
|
|
2072
3466
|
addBack(selector) {
|
|
2073
3467
|
return this.prevObject ? this.add(selector ? this.prevObject.filter(selector) : this.prevObject) : this;
|
|
2074
3468
|
}
|
|
2075
3469
|
index(selector) {
|
|
2076
|
-
const haystack = selector == null ? this.parent().children() : typeof selector === "string" ? this
|
|
3470
|
+
const haystack = selector == null ? this.parent().children() : typeof selector === "string" ? this[API](selector) : this;
|
|
2077
3471
|
const needle = selector == null || typeof selector === "string" ? this[0] : selector?.cheerio ? selector[0] : selector;
|
|
2078
3472
|
return haystack.toArray().indexOf(needle);
|
|
2079
3473
|
}
|
|
2080
3474
|
splice(...args) {
|
|
2081
3475
|
return Reflect.apply(Array.prototype.splice, this, args);
|
|
2082
3476
|
}
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
yield this[i];
|
|
3477
|
+
[Symbol.iterator]() {
|
|
3478
|
+
return this._items()[Symbol.iterator]();
|
|
2086
3479
|
}
|
|
2087
3480
|
/** @internal */
|
|
2088
3481
|
_insert(position, content) {
|
|
2089
|
-
const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3482
|
+
const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], id).type));
|
|
2090
3483
|
if (!targets.length)
|
|
2091
3484
|
return this;
|
|
2092
3485
|
if (typeof content[0] === "function")
|
|
2093
3486
|
return this.each((index, node) => {
|
|
2094
3487
|
if (!targets.includes(this.ids[index]))
|
|
2095
3488
|
return;
|
|
2096
|
-
if ((position === "before" || position === "after") && nodeRecord(this
|
|
3489
|
+
if ((position === "before" || position === "after") && nodeRecord(this[DOCUMENT], this.ids[index]).parent == null)
|
|
2097
3490
|
return;
|
|
2098
|
-
const value = content[0].call(node, index, this.
|
|
3491
|
+
const value = content[0].call(node, index, this[DOCUMENT].innerHtml(this.ids[index]));
|
|
2099
3492
|
let nodes2 = this._domIds(value);
|
|
2100
3493
|
if (index < this.length - 1)
|
|
2101
3494
|
nodes2 = this.op("clone", { ids: nodes2, deep: true });
|
|
@@ -2120,20 +3513,20 @@ var Cheerio = class {
|
|
|
2120
3513
|
return this._insert("after", content);
|
|
2121
3514
|
}
|
|
2122
3515
|
appendTo(target) {
|
|
2123
|
-
this
|
|
3516
|
+
this[API](target).append(this);
|
|
2124
3517
|
return this;
|
|
2125
3518
|
}
|
|
2126
3519
|
prependTo(target) {
|
|
2127
|
-
this
|
|
3520
|
+
this[API](target).prepend(this);
|
|
2128
3521
|
return this;
|
|
2129
3522
|
}
|
|
2130
3523
|
/** @internal */
|
|
2131
3524
|
_insertRelative(target, position) {
|
|
2132
|
-
const targets = this
|
|
3525
|
+
const targets = this[API](target).ids;
|
|
2133
3526
|
this.remove();
|
|
2134
3527
|
const inserted = [];
|
|
2135
3528
|
for (const id of targets) {
|
|
2136
|
-
if (nodeRecord(this
|
|
3529
|
+
if (nodeRecord(this[DOCUMENT], id).parent == null)
|
|
2137
3530
|
continue;
|
|
2138
3531
|
const clones = this.op("clone", { ids: this.ids, deep: true });
|
|
2139
3532
|
this.op("insert", { targetIds: [id], nodeIds: clones, position });
|
|
@@ -2153,7 +3546,7 @@ var Cheerio = class {
|
|
|
2153
3546
|
}
|
|
2154
3547
|
replaceWith(content) {
|
|
2155
3548
|
return this.each((index, node) => {
|
|
2156
|
-
if (nodeRecord(this
|
|
3549
|
+
if (nodeRecord(this[DOCUMENT], this.ids[index]).parent == null)
|
|
2157
3550
|
return;
|
|
2158
3551
|
const value = typeof content === "function" ? content.call(node, index, node) : content;
|
|
2159
3552
|
this.op("insert", { targetIds: [this.ids[index]], nodeIds: this._domIds(value), position: "replace" });
|
|
@@ -2166,33 +3559,33 @@ var Cheerio = class {
|
|
|
2166
3559
|
}
|
|
2167
3560
|
html(content) {
|
|
2168
3561
|
if (content === void 0)
|
|
2169
|
-
return this.length && ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3562
|
+
return this.length && ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], this.ids[0]).type) ? this[DOCUMENT].innerHtml(this.ids[0]) : null;
|
|
2170
3563
|
if (!content?.cheerio) {
|
|
2171
3564
|
this.op("html", { ids: this.ids, value: String(content) });
|
|
2172
3565
|
return this;
|
|
2173
3566
|
}
|
|
2174
3567
|
for (const id of this.ids) {
|
|
2175
|
-
const nodes = content?.cheerio ? importNodes(this
|
|
3568
|
+
const nodes = content?.cheerio ? importNodes(this[DOCUMENT], content.toArray()) : this._domIds(String(content), id);
|
|
2176
3569
|
this.op("setNode", { id, field: "children", value: nodes });
|
|
2177
3570
|
}
|
|
2178
3571
|
return this;
|
|
2179
3572
|
}
|
|
2180
3573
|
text(content) {
|
|
2181
3574
|
if (content === void 0)
|
|
2182
|
-
return this.
|
|
3575
|
+
return this[DOCUMENT].text(this.ids);
|
|
2183
3576
|
if (typeof content !== "function") {
|
|
2184
3577
|
this.op("text", { ids: this.ids, value: String(content) });
|
|
2185
3578
|
return this;
|
|
2186
3579
|
}
|
|
2187
3580
|
for (let i = 0; i < this.ids.length; i++) {
|
|
2188
3581
|
const id = this.ids[i];
|
|
2189
|
-
const value = typeof content === "function" ? content.call(getNode(this
|
|
3582
|
+
const value = typeof content === "function" ? content.call(getNode(this[DOCUMENT], id), i, this[DOCUMENT].text([id])) : content;
|
|
2190
3583
|
this.op("text", { ids: [id], value: String(value) });
|
|
2191
3584
|
}
|
|
2192
3585
|
return this;
|
|
2193
3586
|
}
|
|
2194
3587
|
toString() {
|
|
2195
|
-
return this.
|
|
3588
|
+
return this[DOCUMENT].outerHtml(this.ids);
|
|
2196
3589
|
}
|
|
2197
3590
|
clone() {
|
|
2198
3591
|
return this._fromIds(this.op("clone", { ids: this.ids, deep: true }));
|
|
@@ -2200,8 +3593,8 @@ var Cheerio = class {
|
|
|
2200
3593
|
/** @internal */
|
|
2201
3594
|
_deepest(id, tagsOnly = false) {
|
|
2202
3595
|
for (; ; ) {
|
|
2203
|
-
const
|
|
2204
|
-
const child = tagsOnly ?
|
|
3596
|
+
const children = this.op("traverse", { ids: [id], kind: "children" });
|
|
3597
|
+
const child = tagsOnly ? children.find((candidate) => nodeRecord(this[DOCUMENT], candidate).type === "tag") : children[0];
|
|
2205
3598
|
if (child === void 0)
|
|
2206
3599
|
return id;
|
|
2207
3600
|
id = child;
|
|
@@ -2212,24 +3605,23 @@ var Cheerio = class {
|
|
|
2212
3605
|
const lastParent = this.parents().last();
|
|
2213
3606
|
for (let i = 0; i < this.length; i++) {
|
|
2214
3607
|
const id = this.ids[i];
|
|
2215
|
-
const node = getNode(this
|
|
3608
|
+
const node = getNode(this[DOCUMENT], id);
|
|
2216
3609
|
const value = typeof content === "function" ? content.call(node, i, node) : typeof content === "string" && !isMarkup(content) ? lastParent.find(content).clone() : content;
|
|
2217
3610
|
let wrappers = this._domIds(value);
|
|
2218
3611
|
if (i < this.length - 1)
|
|
2219
3612
|
wrappers = this.op("clone", { ids: wrappers, deep: true });
|
|
2220
3613
|
const wrapper = wrappers[0];
|
|
2221
|
-
if (wrapper === void 0 || !["root", "tag", "script", "style"].includes(nodeRecord(this
|
|
3614
|
+
if (wrapper === void 0 || !["root", "tag", "script", "style"].includes(nodeRecord(this[DOCUMENT], wrapper).type))
|
|
2222
3615
|
continue;
|
|
2223
|
-
const deepest = this._deepest(wrapper);
|
|
2224
3616
|
if (inner) {
|
|
2225
|
-
if (!["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3617
|
+
if (!["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], id).type))
|
|
2226
3618
|
continue;
|
|
2227
3619
|
const contents = this.op("traverse", { ids: [id], kind: "contents" });
|
|
2228
|
-
this.op("setNode", { id:
|
|
3620
|
+
this.op("setNode", { id: this._deepest(wrapper), field: "children", value: contents });
|
|
2229
3621
|
this.op("setNode", { id, field: "children", value: [wrapper] });
|
|
2230
|
-
} else if (nodeRecord(this
|
|
2231
|
-
this.op("insert", { targetIds: [id], nodeIds: [wrapper], position: "before" });
|
|
2232
|
-
this.op("setNode", { id:
|
|
3622
|
+
} else if (nodeRecord(this[DOCUMENT], id).parent != null) {
|
|
3623
|
+
const [inserted = wrapper] = this.op("insert", { targetIds: [id], nodeIds: [wrapper], position: "before" });
|
|
3624
|
+
this.op("setNode", { id: this._deepest(inserted), field: "children", value: [id] });
|
|
2233
3625
|
}
|
|
2234
3626
|
}
|
|
2235
3627
|
return this;
|
|
@@ -2249,7 +3641,7 @@ var Cheerio = class {
|
|
|
2249
3641
|
return this;
|
|
2250
3642
|
const first = this[0];
|
|
2251
3643
|
const wrappers = this._make(typeof content === "function" ? content.call(first, 0, first) : content).insertBefore(first);
|
|
2252
|
-
const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this
|
|
3644
|
+
const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this[DOCUMENT], id).type === "tag");
|
|
2253
3645
|
if (root !== void 0)
|
|
2254
3646
|
this.op("insert", { targetIds: [this._deepest(root, true)], nodeIds: this.ids, position: "append" });
|
|
2255
3647
|
return this;
|
|
@@ -2259,6 +3651,19 @@ var Cheerio = class {
|
|
|
2259
3651
|
}
|
|
2260
3652
|
};
|
|
2261
3653
|
Object.defineProperty(Cheerio.prototype, "cheerio", { value: "[cheerio object]", writable: true, configurable: true });
|
|
3654
|
+
var inspectCustom = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
3655
|
+
Object.defineProperty(Cheerio.prototype, inspectCustom, {
|
|
3656
|
+
configurable: true,
|
|
3657
|
+
writable: true,
|
|
3658
|
+
value(depth, options, inspect) {
|
|
3659
|
+
const prototype = Object.getPrototypeOf(this);
|
|
3660
|
+
if (depth < 0) return options.stylize(`[${prototype.constructor.name}]`, "special");
|
|
3661
|
+
const shown = Object.create(prototype);
|
|
3662
|
+
Object.defineProperty(shown, inspectCustom, { value: void 0 });
|
|
3663
|
+
for (const key of Object.keys(this)) shown[key] = this[key];
|
|
3664
|
+
return inspect(shown, { ...options, depth });
|
|
3665
|
+
}
|
|
3666
|
+
});
|
|
2262
3667
|
installAttributes(Cheerio);
|
|
2263
3668
|
var nativeExtractionMethods = Object.freeze({
|
|
2264
3669
|
make: Cheerio.prototype._make,
|
|
@@ -2283,12 +3688,12 @@ function nativePrefix(scope, map, keys, key) {
|
|
|
2283
3688
|
const slot = Object.getOwnPropertyDescriptor(map, name);
|
|
2284
3689
|
if (!slot || !slot.enumerable || !("value" in slot)) break;
|
|
2285
3690
|
Object.defineProperty(prefix, name, { value: slot.value, enumerable: true, configurable: true });
|
|
2286
|
-
const
|
|
2287
|
-
if (!
|
|
3691
|
+
const compiled2 = compileExtractPlan(prefix, scope.options);
|
|
3692
|
+
if (!compiled2) {
|
|
2288
3693
|
delete prefix[name];
|
|
2289
3694
|
break;
|
|
2290
3695
|
}
|
|
2291
|
-
plan =
|
|
3696
|
+
plan = compiled2;
|
|
2292
3697
|
count++;
|
|
2293
3698
|
}
|
|
2294
3699
|
if (!plan || !count) return void 0;
|
|
@@ -2316,10 +3721,12 @@ function extract(map) {
|
|
|
2316
3721
|
const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
|
|
2317
3722
|
const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
|
|
2318
3723
|
const selection = this._findBySelector(selector, all ? Infinity : 1);
|
|
3724
|
+
const rows = typeof value === "object" ? nativeRows(this, key, all, selector, value) : void 0;
|
|
2319
3725
|
const read = (index) => {
|
|
2320
3726
|
if (typeof value === "function") return value(selection[index], key, result);
|
|
2321
3727
|
const scope = this._make === nativeExtractionMethods.make ? this._fromIds([selection.ids[index]]) : this._make(selection[index]);
|
|
2322
|
-
|
|
3728
|
+
if (typeof value === "string") return scope.prop(value);
|
|
3729
|
+
return rows ? completeRow(scope, value, rows, index) : scope.extract(value);
|
|
2323
3730
|
};
|
|
2324
3731
|
let extracted;
|
|
2325
3732
|
if (all) {
|
|
@@ -2336,6 +3743,69 @@ function extract(map) {
|
|
|
2336
3743
|
}
|
|
2337
3744
|
return result;
|
|
2338
3745
|
}
|
|
3746
|
+
function nativeRows(scope, key, all, selector, map) {
|
|
3747
|
+
const keys = plainKeys(map);
|
|
3748
|
+
if (!keys || scope._make !== nativeExtractionMethods.make || scope._findBySelector !== nativeExtractionMethods.find || scope.prop !== nativeExtractionMethods.prop || scope.extract !== nativeExtractionMethods.extract) return void 0;
|
|
3749
|
+
const subset = /* @__PURE__ */ Object.create(null);
|
|
3750
|
+
const nativeKeys = /* @__PURE__ */ new Set();
|
|
3751
|
+
for (const name of keys) {
|
|
3752
|
+
const slot = Object.getOwnPropertyDescriptor(map, name);
|
|
3753
|
+
if (!slot || !slot.enumerable || !("value" in slot)) continue;
|
|
3754
|
+
const single = /* @__PURE__ */ Object.create(null);
|
|
3755
|
+
Object.defineProperty(single, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3756
|
+
if (!compileExtractPlan(single, scope.options)) continue;
|
|
3757
|
+
Object.defineProperty(subset, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3758
|
+
nativeKeys.add(name);
|
|
3759
|
+
}
|
|
3760
|
+
if (!nativeKeys.size || nativeKeys.size === keys.length) return void 0;
|
|
3761
|
+
const outer = /* @__PURE__ */ Object.create(null);
|
|
3762
|
+
Object.defineProperty(outer, key, { value: all ? [{ selector, value: subset }] : { selector, value: subset }, enumerable: true, configurable: true });
|
|
3763
|
+
const plan = compileExtractPlan(outer, scope.options);
|
|
3764
|
+
if (!plan) return void 0;
|
|
3765
|
+
const writes = writeCount();
|
|
3766
|
+
const values = scope.op("extractPlan", { ids: scope.ids, plan });
|
|
3767
|
+
hydrateExtractResult(values, plan.entries);
|
|
3768
|
+
const extracted = values[key];
|
|
3769
|
+
const rows = all ? extracted : extracted === void 0 ? [] : [extracted];
|
|
3770
|
+
return Array.isArray(rows) ? { keys: nativeKeys, rows, writes } : void 0;
|
|
3771
|
+
}
|
|
3772
|
+
function completeRow(scope, map, rows, index) {
|
|
3773
|
+
const row = {};
|
|
3774
|
+
const native = rows.rows[index] ?? {};
|
|
3775
|
+
for (const name in map) {
|
|
3776
|
+
if (rows.keys.has(name) && writeCount() === rows.writes) {
|
|
3777
|
+
row[name] = native[name];
|
|
3778
|
+
continue;
|
|
3779
|
+
}
|
|
3780
|
+
const entry = /* @__PURE__ */ Object.create(null);
|
|
3781
|
+
Object.defineProperty(entry, name, { value: map[name], enumerable: true, configurable: true });
|
|
3782
|
+
fillEntries(scope, entry, row);
|
|
3783
|
+
}
|
|
3784
|
+
return row;
|
|
3785
|
+
}
|
|
3786
|
+
function fillEntries(scope, map, result) {
|
|
3787
|
+
for (const key in map) {
|
|
3788
|
+
const entry = map[key];
|
|
3789
|
+
const all = Array.isArray(entry);
|
|
3790
|
+
const descriptor = all ? entry[0] : entry;
|
|
3791
|
+
const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
|
|
3792
|
+
const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
|
|
3793
|
+
const selection = scope._findBySelector(selector, all ? Infinity : 1);
|
|
3794
|
+
const read = (index) => {
|
|
3795
|
+
if (typeof value === "function") return value(selection[index], key, result);
|
|
3796
|
+
const child = scope._make === nativeExtractionMethods.make ? scope._fromIds([selection.ids[index]]) : scope._make(selection[index]);
|
|
3797
|
+
return typeof value === "string" ? child.prop(value) : child.extract(value);
|
|
3798
|
+
};
|
|
3799
|
+
if (all) {
|
|
3800
|
+
const values = [];
|
|
3801
|
+
for (let index = 0; index < selection.length; index += 1) {
|
|
3802
|
+
const extracted = read(index);
|
|
3803
|
+
if (extracted != null) values.push(...Array.isArray(extracted) ? extracted : [extracted]);
|
|
3804
|
+
}
|
|
3805
|
+
result[key] = values;
|
|
3806
|
+
} else result[key] = selection.length ? read(0) : void 0;
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
2339
3809
|
async function extractCooperatively(selection, map) {
|
|
2340
3810
|
let deadline = performance.now() + 4;
|
|
2341
3811
|
let visits = 0;
|
|
@@ -2364,6 +3834,7 @@ async function extractCooperatively(selection, map) {
|
|
|
2364
3834
|
const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
|
|
2365
3835
|
const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
|
|
2366
3836
|
const found = scope._findBySelector(selector, all ? Infinity : 1);
|
|
3837
|
+
const rows = typeof value === "object" ? nativeRows(scope, key, all, selector, value) : void 0;
|
|
2367
3838
|
const output = [];
|
|
2368
3839
|
let single;
|
|
2369
3840
|
const count = all ? found.length : Math.min(found.length, 1);
|
|
@@ -2373,7 +3844,7 @@ async function extractCooperatively(selection, map) {
|
|
|
2373
3844
|
if (typeof value === "function") extracted = value(found[index], key, result);
|
|
2374
3845
|
else {
|
|
2375
3846
|
const child = scope._make === nativeExtractionMethods.make ? scope._fromIds([found.ids[index]]) : scope._make(found[index]);
|
|
2376
|
-
extracted = typeof value === "string" ? child.prop(value) : child.extract === nativeExtractionMethods.extract ? (await walk(child, value)).value : child.extract(value);
|
|
3847
|
+
extracted = typeof value === "string" ? child.prop(value) : rows ? completeRow(child, value, rows, index) : child.extract === nativeExtractionMethods.extract ? (await walk(child, value)).value : child.extract(value);
|
|
2377
3848
|
}
|
|
2378
3849
|
if (all) {
|
|
2379
3850
|
if (extracted != null) output.push(...Array.isArray(extracted) ? extracted : [extracted]);
|
|
@@ -2432,12 +3903,12 @@ function sniffEncoding(buffer, options = {}) {
|
|
|
2432
3903
|
if (!label) {
|
|
2433
3904
|
const prefix = Buffer.from(buffer.subarray(0, options.maxBytes ?? 1024)).toString("latin1").replace(/<!--[\s\S]*?(?:-->|$)/g, "");
|
|
2434
3905
|
for (const token of prefix.matchAll(/<meta\b([^>]*)>/gi)) {
|
|
2435
|
-
const
|
|
3906
|
+
const attributes = {};
|
|
2436
3907
|
for (const attribute of token[1].matchAll(/([^\s=/'">]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g)) {
|
|
2437
3908
|
const key = attribute[1].toLowerCase();
|
|
2438
|
-
if (!(key in
|
|
3909
|
+
if (!(key in attributes)) attributes[key] = attribute[2] ?? attribute[3] ?? attribute[4] ?? "";
|
|
2439
3910
|
}
|
|
2440
|
-
const declared =
|
|
3911
|
+
const declared = attributes.charset ?? (attributes["http-equiv"]?.toLowerCase() === "content-type" ? /\bcharset\s*=\s*["']?([^\s;"']+)/i.exec(attributes.content ?? "")?.[1] : void 0);
|
|
2441
3912
|
label = encodingLabel(declared);
|
|
2442
3913
|
if (label) {
|
|
2443
3914
|
if (label === "utf-16le" || label === "utf-16be") label = "utf-8";
|
|
@@ -2974,13 +4445,22 @@ function createAPI(document, options, initialRoot = document.rootId()) {
|
|
|
2974
4445
|
class LoadedCheerio extends Cheerio {
|
|
2975
4446
|
}
|
|
2976
4447
|
let api;
|
|
2977
|
-
const
|
|
2978
|
-
if (selector?.cheerio) return selector;
|
|
2979
|
-
const opts = flattenOptions(override, internal);
|
|
2980
|
-
const rootIds = root === void 0 ? [initialRoot] : typeof root === "string" ? [makeRoot(document, operation(document, "create", { html: root, options: opts }))] : root?.cheerio ? importNodes(document, root.toArray()) : importNodes(document, root);
|
|
4448
|
+
const createRoot = (rootIds, opts) => {
|
|
2981
4449
|
const rootInstance = new LoadedCheerio(api, document, rootIds, null, opts);
|
|
2982
4450
|
rootInstance._root = rootInstance;
|
|
4451
|
+
return rootInstance;
|
|
4452
|
+
};
|
|
4453
|
+
const initialize2 = function(selector, context, root, override) {
|
|
4454
|
+
resumeCollection(document);
|
|
4455
|
+
if (selector?.cheerio) {
|
|
4456
|
+
exposeDocumentTo(document, selector[DOCUMENT]);
|
|
4457
|
+
return selector;
|
|
4458
|
+
}
|
|
4459
|
+
const opts = flattenOptions(override, internal);
|
|
4460
|
+
const rootInstance = createRoot(root === void 0 ? [initialRoot] : typeof root === "string" ? [makeRoot(document, operation(document, "create", { html: root, options: opts }))] : root?.cheerio ? importNodes(document, root.toArray()) : importNodes(document, root), opts);
|
|
2983
4461
|
if (!selector) return new LoadedCheerio(api, document, [], rootInstance, opts);
|
|
4462
|
+
const id = viewIdIn(document, selector);
|
|
4463
|
+
if (id !== void 0) return new LoadedCheerio(api, document, [id], rootInstance, opts);
|
|
2984
4464
|
if (typeof selector === "string" && isHtml(selector)) return new LoadedCheerio(api, document, operation(document, "create", { html: selector, options: opts }), rootInstance, opts);
|
|
2985
4465
|
if (typeof selector === "object") {
|
|
2986
4466
|
const values = "length" in selector && !selector.type ? Array.from(selector) : [selector];
|
|
@@ -2999,55 +4479,57 @@ function createAPI(document, options, initialRoot = document.rootId()) {
|
|
|
2999
4479
|
}
|
|
3000
4480
|
return searchContext.find(search);
|
|
3001
4481
|
};
|
|
3002
|
-
api = Object.assign(initialize2, {
|
|
4482
|
+
api = Object.assign(initialize2, staticMethods, {
|
|
3003
4483
|
load,
|
|
3004
|
-
_root:
|
|
4484
|
+
_root: rootNode(document, initialRoot),
|
|
3005
4485
|
_options: internal,
|
|
3006
4486
|
fn: LoadedCheerio.prototype,
|
|
3007
|
-
prototype: LoadedCheerio.prototype
|
|
3008
|
-
root() {
|
|
3009
|
-
return this(this._root);
|
|
3010
|
-
},
|
|
3011
|
-
html(dom2, renderOptions) {
|
|
3012
|
-
if (!this) return "";
|
|
3013
|
-
if (dom2 && typeof dom2 === "object" && !("length" in dom2) && !("type" in dom2)) {
|
|
3014
|
-
renderOptions = dom2;
|
|
3015
|
-
dom2 = void 0;
|
|
3016
|
-
}
|
|
3017
|
-
const nodes = dom2 === void 0 ? [this._root] : this(dom2).toArray();
|
|
3018
|
-
const binding = nodeBinding(this._root);
|
|
3019
|
-
return operation(binding.document, "render", { ids: importNodes(binding.document, nodes), options: flattenOptions(renderOptions, this._options) });
|
|
3020
|
-
},
|
|
3021
|
-
xml(dom2) {
|
|
3022
|
-
const binding = nodeBinding(this._root);
|
|
3023
|
-
return operation(binding.document, "render", { ids: importNodes(binding.document, dom2 === void 0 ? [this._root] : this(dom2).toArray()), options: { ...this._options, xmlMode: true, _useHtmlParser2: true } });
|
|
3024
|
-
},
|
|
3025
|
-
text(elements) {
|
|
3026
|
-
if (!elements && !this) return "";
|
|
3027
|
-
const nodes = elements ?? [this._root];
|
|
3028
|
-
const binding = this ? nodeBinding(this._root) : nodeBinding(nodes[0]);
|
|
3029
|
-
if (binding) return binding.document.text(importNodes(binding.document, nodes));
|
|
3030
|
-
const doc = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
3031
|
-
return doc.text(importNodes(doc, nodes));
|
|
3032
|
-
},
|
|
3033
|
-
parseHTML(data2, context, keepScripts = typeof context === "boolean" ? context : false) {
|
|
3034
|
-
if (!data2 || typeof data2 !== "string") return null;
|
|
3035
|
-
if (typeof context === "boolean") keepScripts = context;
|
|
3036
|
-
const parsed = this.load(data2, this._options, false);
|
|
3037
|
-
if (!keepScripts) parsed("script").remove();
|
|
3038
|
-
return parsed._root.children.slice();
|
|
3039
|
-
},
|
|
3040
|
-
extract(map) {
|
|
3041
|
-
return this.root().extract(map);
|
|
3042
|
-
},
|
|
3043
|
-
contains,
|
|
3044
|
-
merge
|
|
4487
|
+
prototype: LoadedCheerio.prototype
|
|
3045
4488
|
});
|
|
3046
4489
|
return api;
|
|
3047
4490
|
}
|
|
3048
|
-
|
|
4491
|
+
var staticMethods = {
|
|
4492
|
+
root() {
|
|
4493
|
+
return this(this._root);
|
|
4494
|
+
},
|
|
4495
|
+
html(dom2, renderOptions) {
|
|
4496
|
+
if (!this) return "";
|
|
4497
|
+
if (dom2 && typeof dom2 === "object" && !("length" in dom2) && !("type" in dom2)) {
|
|
4498
|
+
renderOptions = dom2;
|
|
4499
|
+
dom2 = void 0;
|
|
4500
|
+
}
|
|
4501
|
+
const nodes = dom2 === void 0 ? [this._root] : this(dom2).toArray();
|
|
4502
|
+
const binding = nodeBinding(this._root);
|
|
4503
|
+
return operation(binding.document, "render", { ids: importNodes(binding.document, nodes), options: flattenOptions(renderOptions, this._options) });
|
|
4504
|
+
},
|
|
4505
|
+
xml(dom2) {
|
|
4506
|
+
const binding = nodeBinding(this._root);
|
|
4507
|
+
return operation(binding.document, "render", { ids: importNodes(binding.document, dom2 === void 0 ? [this._root] : this(dom2).toArray()), options: { ...this._options, xmlMode: true, _useHtmlParser2: true } });
|
|
4508
|
+
},
|
|
4509
|
+
text(elements) {
|
|
4510
|
+
if (!elements && !this) return "";
|
|
4511
|
+
const nodes = elements ?? [this._root];
|
|
4512
|
+
const binding = this ? nodeBinding(this._root) : nodeBinding(nodes[0]);
|
|
4513
|
+
if (binding) return binding.document.text(importNodes(binding.document, nodes));
|
|
4514
|
+
const doc = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
4515
|
+
return doc.text(importNodes(doc, nodes));
|
|
4516
|
+
},
|
|
4517
|
+
parseHTML(data2, context, keepScripts = typeof context === "boolean" ? context : false) {
|
|
4518
|
+
if (!data2 || typeof data2 !== "string") return null;
|
|
4519
|
+
if (typeof context === "boolean") keepScripts = context;
|
|
4520
|
+
const parsed = this.load(data2, this._options, false);
|
|
4521
|
+
if (!keepScripts) parsed("script").remove();
|
|
4522
|
+
return parsed._root.children.slice();
|
|
4523
|
+
},
|
|
4524
|
+
extract(map) {
|
|
4525
|
+
return this.root().extract(map);
|
|
4526
|
+
},
|
|
4527
|
+
contains,
|
|
4528
|
+
merge
|
|
4529
|
+
};
|
|
4530
|
+
function makeRoot(document, children) {
|
|
3049
4531
|
const id = operation(document, "createNode", { type: "root" });
|
|
3050
|
-
operation(document, "setNode", { id, field: "children", value:
|
|
4532
|
+
operation(document, "setNode", { id, field: "children", value: children });
|
|
3051
4533
|
return id;
|
|
3052
4534
|
}
|
|
3053
4535
|
function load(content, options, isDocument2 = true) {
|
|
@@ -3182,4 +4664,4 @@ export {
|
|
|
3182
4664
|
loadAll,
|
|
3183
4665
|
extractAll
|
|
3184
4666
|
};
|
|
3185
|
-
//# sourceMappingURL=chunk-
|
|
4667
|
+
//# sourceMappingURL=chunk-FPRP6UIX.mjs.map
|