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