rusteerio 1.0.1 → 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 +107 -2
- package/dist/{chunk-DMRD3FGC.mjs → chunk-FPRP6UIX.mjs} +2233 -751
- package/dist/chunk-FPRP6UIX.mjs.map +1 -0
- package/dist/index.cjs +2232 -750
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/slim.cjs +2226 -745
- package/dist/slim.cjs.map +1 -1
- package/dist/slim.d.mts +2 -2
- package/dist/slim.d.ts +2 -2
- package/dist/slim.mjs +1 -1
- package/dist/{types-BP6TpxE5.d.mts → types-Cs9UP1Vv.d.mts} +3 -3
- package/dist/{types-BP6TpxE5.d.ts → types-Cs9UP1Vv.d.ts} +3 -3
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/native/src/arena.rs +219 -80
- package/native/src/attributes.rs +11 -5
- package/native/src/document_order.rs +711 -0
- package/native/src/extraction.rs +15 -3
- package/native/src/gc.rs +12 -3
- package/native/src/id_hash.rs +42 -0
- package/native/src/immutable.rs +256 -0
- package/native/src/lib.rs +1039 -171
- package/native/src/runtime.rs +189 -33
- package/native/src/selector.rs +346 -44
- package/native/src/sink.rs +14 -1
- package/native/src/snapshot.rs +509 -0
- package/native/src/stream.rs +2 -2
- package/native/src/tokenizer.rs +29 -12
- package/native/vendor/html5ever-0.35.0/src/tokenizer/char_ref/mod.rs +79 -0
- package/package.json +3 -1
- package/rusteerio.darwin-arm64.node +0 -0
- package/rusteerio.darwin-x64.node +0 -0
- package/rusteerio.linux-arm64-gnu.node +0 -0
- package/rusteerio.linux-arm64-musl.node +0 -0
- package/rusteerio.linux-x64-gnu.node +0 -0
- package/rusteerio.linux-x64-musl.node +0 -0
- package/rusteerio.win32-arm64-msvc.node +0 -0
- package/rusteerio.win32-x64-msvc.node +0 -0
- package/src/attributes.ts +78 -44
- package/src/codec.ts +22 -3
- package/src/extract.ts +86 -2
- package/src/hooks.ts +148 -2
- package/src/index.ts +51 -40
- package/src/match.ts +207 -0
- package/src/native.ts +9 -1
- package/src/nodes.ts +531 -183
- package/src/router.ts +792 -229
- package/src/selection.ts +239 -125
- package/src/snapshot.ts +255 -0
- package/src/transport.ts +51 -42
- package/dist/chunk-DMRD3FGC.mjs.map +0 -1
package/dist/slim.cjs
CHANGED
|
@@ -77,17 +77,30 @@ function decodeString(value) {
|
|
|
77
77
|
}
|
|
78
78
|
return start === 0 ? value : parts.join("") + value.slice(start);
|
|
79
79
|
}
|
|
80
|
-
var stringToken = /"(?:[^"\\]|\\[\s\S])*"/g;
|
|
81
80
|
var encodeJsonCandidate = /[\ud800-\ue800]|\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
|
|
82
81
|
var escapedJsonCandidate = /\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
|
|
83
82
|
var decodeJsonCandidate = /[\ue000-\ue800]|\\ue[0-8][\da-f]{2}/i;
|
|
84
83
|
function encodeJson(value) {
|
|
85
84
|
if (!encodeJsonCandidate.test(value)) return value;
|
|
86
85
|
if (isWellFormed?.call(value) && !encoded.test(value) && !escapedJsonCandidate.test(value)) return value;
|
|
87
|
-
return value
|
|
86
|
+
return mapJsonStrings(value, encodeString);
|
|
88
87
|
}
|
|
89
88
|
function decodeJson(value) {
|
|
90
|
-
return decodeJsonCandidate.test(value) ? value
|
|
89
|
+
return decodeJsonCandidate.test(value) ? mapJsonStrings(value, decodeString) : value;
|
|
90
|
+
}
|
|
91
|
+
function mapJsonStrings(json, transform) {
|
|
92
|
+
const parts = [];
|
|
93
|
+
let copied = 0;
|
|
94
|
+
let quote = json.indexOf('"');
|
|
95
|
+
while (quote !== -1) {
|
|
96
|
+
let end = quote + 1;
|
|
97
|
+
while (end < json.length && json.charCodeAt(end) !== 34) end += json.charCodeAt(end) === 92 ? 2 : 1;
|
|
98
|
+
if (end >= json.length) break;
|
|
99
|
+
parts.push(json.slice(copied, quote), JSON.stringify(transform(JSON.parse(json.slice(quote, end + 1)))));
|
|
100
|
+
copied = end + 1;
|
|
101
|
+
quote = json.indexOf('"', copied);
|
|
102
|
+
}
|
|
103
|
+
return copied === 0 ? json : parts.join("") + json.slice(copied);
|
|
91
104
|
}
|
|
92
105
|
function encodeOptions(value) {
|
|
93
106
|
if (value === void 0) return '{"__utf16Codec":true}';
|
|
@@ -99,12 +112,39 @@ function encodeOptions(value) {
|
|
|
99
112
|
}
|
|
100
113
|
|
|
101
114
|
// src/transport.ts
|
|
102
|
-
var registryKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.
|
|
115
|
+
var registryKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.v2");
|
|
103
116
|
var globals = globalThis;
|
|
104
|
-
var registry = globals[registryKey] ??= {
|
|
117
|
+
var registry = globals[registryKey] ??= { userErrors: /* @__PURE__ */ new WeakSet() };
|
|
118
|
+
var transportedKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.prototype");
|
|
119
|
+
var jsonMethods = /* @__PURE__ */ new Set(["op", "node", "exportTree", "parserDiagnostics", "adopt"]);
|
|
120
|
+
var argumentEncoders = {
|
|
121
|
+
op: (args) => {
|
|
122
|
+
args[1] = encodeJson(args[1]);
|
|
123
|
+
},
|
|
124
|
+
create: (args) => {
|
|
125
|
+
args[0] = encodeString(args[0]);
|
|
126
|
+
if (typeof args[2] === "string") args[2] = encodeOptions(args[2]);
|
|
127
|
+
},
|
|
128
|
+
select: (args) => {
|
|
129
|
+
args[0] = encodeString(args[0]);
|
|
130
|
+
},
|
|
131
|
+
matches: (args) => {
|
|
132
|
+
args[0] = encodeString(args[0]);
|
|
133
|
+
},
|
|
134
|
+
attr: (args) => {
|
|
135
|
+
args[1] = encodeString(args[1]);
|
|
136
|
+
},
|
|
137
|
+
setAttribute: (args) => {
|
|
138
|
+
args[1] = encodeString(args[1]);
|
|
139
|
+
if (typeof args[2] === "string") args[2] = encodeString(args[2]);
|
|
140
|
+
},
|
|
141
|
+
render: (args) => {
|
|
142
|
+
if (typeof args[1] === "string") args[1] = encodeJson(args[1]);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
105
145
|
function wrapNativeBinding(binding) {
|
|
106
146
|
const raw = binding;
|
|
107
|
-
const {
|
|
147
|
+
const { userErrors } = registry;
|
|
108
148
|
const restoreError = (error) => {
|
|
109
149
|
if (error instanceof Error && !userErrors.has(error)) {
|
|
110
150
|
const message = decodeString(error.message);
|
|
@@ -132,41 +172,33 @@ function wrapNativeBinding(binding) {
|
|
|
132
172
|
throw error;
|
|
133
173
|
}
|
|
134
174
|
};
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
if (typeof
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (typeof args[2] === "string") args[2] = encodeOptions(args[2]);
|
|
152
|
-
} else if (property2 === "select" || property2 === "matches") args[0] = encodeString(args[0]);
|
|
153
|
-
else if (property2 === "attr") args[1] = encodeString(args[1]);
|
|
154
|
-
else if (property2 === "adopt") args[0] = originals.get(args[0]) ?? args[0];
|
|
155
|
-
const result = Reflect.apply(value, target, args);
|
|
156
|
-
if (property2 === "op" && args[0] === "serialize" && typeof result === "string" && result.startsWith("{")) {
|
|
157
|
-
const error = JSON.parse(result).__nativeError;
|
|
158
|
-
if (error?.name === "URIError") throw new URIError(error.message);
|
|
159
|
-
}
|
|
160
|
-
return typeof result === "string" ? jsonMethods.has(String(property2)) ? decodeJson(result) : decodeString(result) : result;
|
|
161
|
-
});
|
|
162
|
-
methods.set(property2, method);
|
|
163
|
-
return method;
|
|
175
|
+
const transportMethod = (name, method) => {
|
|
176
|
+
const encodeArguments = argumentEncoders[name];
|
|
177
|
+
const decode = jsonMethods.has(name) ? decodeJson : decodeString;
|
|
178
|
+
const isOperation = name === "op";
|
|
179
|
+
return function transported(...args) {
|
|
180
|
+
try {
|
|
181
|
+
if (encodeArguments) encodeArguments(args);
|
|
182
|
+
const result = method.apply(this, args);
|
|
183
|
+
if (typeof result !== "string") return result;
|
|
184
|
+
if (isOperation && args[0] === "serialize" && result.startsWith("{")) {
|
|
185
|
+
const error = JSON.parse(result).__nativeError;
|
|
186
|
+
if (error?.name === "URIError") throw new URIError(error.message);
|
|
187
|
+
}
|
|
188
|
+
return decode(result);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
return restoreError(error);
|
|
164
191
|
}
|
|
165
|
-
}
|
|
166
|
-
documents.set(document, wrapped2);
|
|
167
|
-
originals.set(wrapped2, document);
|
|
168
|
-
return wrapped2;
|
|
192
|
+
};
|
|
169
193
|
};
|
|
194
|
+
const prototype = raw.NativeDocument.prototype;
|
|
195
|
+
if (!Object.hasOwn(prototype, transportedKey)) {
|
|
196
|
+
for (const name of Object.getOwnPropertyNames(prototype)) {
|
|
197
|
+
const method = prototype[name];
|
|
198
|
+
if (name !== "constructor" && typeof method === "function") prototype[name] = transportMethod(name, method);
|
|
199
|
+
}
|
|
200
|
+
Object.defineProperty(prototype, transportedKey, { value: true });
|
|
201
|
+
}
|
|
170
202
|
const wrapStream = (stream) => {
|
|
171
203
|
let carry = "";
|
|
172
204
|
return {
|
|
@@ -186,7 +218,7 @@ function wrapNativeBinding(binding) {
|
|
|
186
218
|
carry = "";
|
|
187
219
|
await invoke(() => stream.write(encodeString(final)));
|
|
188
220
|
}
|
|
189
|
-
return
|
|
221
|
+
return invoke(() => stream.finish());
|
|
190
222
|
},
|
|
191
223
|
abort() {
|
|
192
224
|
carry = "";
|
|
@@ -200,12 +232,19 @@ function wrapNativeBinding(binding) {
|
|
|
200
232
|
}
|
|
201
233
|
});
|
|
202
234
|
const wrapped = { ...raw };
|
|
203
|
-
|
|
235
|
+
const Document2 = raw.NativeDocument;
|
|
236
|
+
wrapped.NativeDocument = function NativeDocument(html, isDocument2, options) {
|
|
237
|
+
try {
|
|
238
|
+
return new Document2(encodeString(html), isDocument2, encodeOptions(options));
|
|
239
|
+
} catch (error) {
|
|
240
|
+
return restoreError(error);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
204
243
|
if (raw.NativeStream) wrapped.NativeStream = wrapConstructor(raw.NativeStream, ([options, isDocument2, bridge]) => [encodeOptions(options), isDocument2, bridge && wrapBridge(bridge)], wrapStream);
|
|
205
244
|
if (raw.NativeHookStream) wrapped.NativeHookStream = wrapConstructor(raw.NativeHookStream, ([isDocument2, options, bridge]) => [isDocument2, encodeOptions(options), wrapBridge(bridge)], wrapStream);
|
|
206
|
-
if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) =>
|
|
207
|
-
if (raw.parseAsync) wrapped.parseAsync =
|
|
208
|
-
if (raw.parseManyAsync) wrapped.parseManyAsync =
|
|
245
|
+
if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) => invoke(() => raw.parseWithTreeAdapter(encodeString(source), isDocument2, encodeOptions(options), wrapBridge(bridge)));
|
|
246
|
+
if (raw.parseAsync) wrapped.parseAsync = (source, isDocument2, options) => invoke(() => raw.parseAsync(encodeString(source), isDocument2, encodeOptions(options)));
|
|
247
|
+
if (raw.parseManyAsync) wrapped.parseManyAsync = (sources, isDocument2, threads, options) => invoke(() => raw.parseManyAsync(sources.map(encodeString), isDocument2, threads, encodeOptions(options)));
|
|
209
248
|
if (raw.extractPlanManyAsync) wrapped.extractPlanManyAsync = async (sources, plan, threads, options) => decodeJson(await invoke(() => raw.extractPlanManyAsync(sources.map(encodeString), encodeJson(plan), threads, encodeOptions(options))));
|
|
210
249
|
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))));
|
|
211
250
|
return wrapped;
|
|
@@ -216,10 +255,13 @@ var import_meta = {};
|
|
|
216
255
|
var cached;
|
|
217
256
|
var attempted = false;
|
|
218
257
|
var bindingError;
|
|
258
|
+
function packageDirectory() {
|
|
259
|
+
return typeof __dirname === "string" ? __dirname : (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
260
|
+
}
|
|
219
261
|
function nativeBinding() {
|
|
220
262
|
if (attempted) return cached;
|
|
221
263
|
attempted = true;
|
|
222
|
-
const moduleDirectory =
|
|
264
|
+
const moduleDirectory = packageDirectory();
|
|
223
265
|
const require2 = (0, import_node_module.createRequire)((0, import_node_path.join)(moduleDirectory, "rusteerio-loader.cjs"));
|
|
224
266
|
const directories = [moduleDirectory, (0, import_node_path.dirname)(moduleDirectory)];
|
|
225
267
|
const libc = process.platform === "linux" ? process.report?.getReport()?.header?.glibcVersionRuntime ? "gnu" : "musl" : void 0;
|
|
@@ -368,8 +410,8 @@ function treeAdapterBridge(adapter, options) {
|
|
|
368
410
|
const doctype = invoke("isDocumentTypeNode", [node]);
|
|
369
411
|
const name = element ? invoke("getTagName", [node]) : doctype ? "!doctype" : node.name;
|
|
370
412
|
const type = element ? name === "script" || name === "style" ? name : "tag" : text ? "text" : comment ? "comment" : doctype ? "directive" : node.type ?? "root";
|
|
371
|
-
const
|
|
372
|
-
const record = { id, type, children: Array.from(
|
|
413
|
+
const children = element || type === "root" || type === "cdata" ? invoke("getChildNodes", [node]) ?? [] : [];
|
|
414
|
+
const record = { id, type, children: Array.from(children, identify), parent: identify(invoke("getParentNode", [node])) };
|
|
373
415
|
if (name !== void 0) record.name = name;
|
|
374
416
|
if (element) {
|
|
375
417
|
record.namespace = invoke("getNamespaceURI", [node]);
|
|
@@ -425,215 +467,851 @@ function bindAdapterDocument(document, options, adapter) {
|
|
|
425
467
|
function parseNativeDocument(source, options, isDocument2) {
|
|
426
468
|
const binding = requireNative();
|
|
427
469
|
const nativeOptions = parserOptions(source, options);
|
|
470
|
+
if (!options._useHtmlParser2 && options.treeAdapter && canReplay(options)) {
|
|
471
|
+
const document2 = routeDocument(new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions)), options);
|
|
472
|
+
const nodes = replayIntoAdapter(document2, options.treeAdapter, isDocument2);
|
|
473
|
+
if (nodes) {
|
|
474
|
+
attachParsedNodes(document2.state, nodes);
|
|
475
|
+
return document2;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
428
478
|
if (!options._useHtmlParser2 && options.treeAdapter) {
|
|
429
|
-
const
|
|
430
|
-
if (!
|
|
479
|
+
const parse3 = binding.parseWithTreeAdapter;
|
|
480
|
+
if (!parse3) throw new Error("This native addon does not support treeAdapter hooks; rebuild the Rust addon.");
|
|
431
481
|
const adapter = treeAdapterBridge(options.treeAdapter, options);
|
|
432
|
-
return bindAdapterDocument(
|
|
482
|
+
return bindAdapterDocument(parse3(source, isDocument2, JSON.stringify(nativeOptions), adapter.bridge), options, adapter);
|
|
433
483
|
}
|
|
434
484
|
const document = new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions));
|
|
435
485
|
deliverParseErrors(document, options);
|
|
436
486
|
return routeDocument(document, options);
|
|
437
487
|
}
|
|
488
|
+
function canReplay(options) {
|
|
489
|
+
const adapter = options.treeAdapter;
|
|
490
|
+
return !options.onParseError && !options.sourceCodeLocationInfo && adapter.onItemPush === void 0 && adapter.onItemPop === void 0;
|
|
491
|
+
}
|
|
492
|
+
function replayIntoAdapter(document, adapter, isDocument2) {
|
|
493
|
+
const state = document.state;
|
|
494
|
+
const root = document.rootId() - state.base;
|
|
495
|
+
const size = state.baseline;
|
|
496
|
+
const nodes = new Array(size);
|
|
497
|
+
for (let local = 0; local < Math.min(size, 65); local++) recordAt(state, local);
|
|
498
|
+
for (let local = 0; local < size; local++) {
|
|
499
|
+
const snapshot = plainSnapshot(state, local);
|
|
500
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
501
|
+
if (!snapshot && !record) continue;
|
|
502
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
503
|
+
if (local === root) {
|
|
504
|
+
nodes[local] = isDocument2 ? adapter.createDocument() : adapter.createDocumentFragment();
|
|
505
|
+
const mode = record?.["x-mode"];
|
|
506
|
+
if (isDocument2 && mode !== void 0) adapter.setDocumentMode(nodes[local], mode);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
const parentLocal = snapshot ? snapshot.linkOf(local, 1) : record.parent;
|
|
510
|
+
const parent = parentLocal == null ? void 0 : nodes[parentLocal];
|
|
511
|
+
if (parent === void 0) return void 0;
|
|
512
|
+
switch (type) {
|
|
513
|
+
case "tag":
|
|
514
|
+
case "script":
|
|
515
|
+
case "style": {
|
|
516
|
+
const element = snapshot ? adapter.createElement(snapshot.nameOf(local), snapshot.namespaceOf(local), snapshot.attributeObjects(local)) : adapter.createElement(record.name, record.namespace, attributeList(record));
|
|
517
|
+
adapter.appendChild(parent, element);
|
|
518
|
+
nodes[local] = element;
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
521
|
+
case "root": {
|
|
522
|
+
const content = adapter.createDocumentFragment();
|
|
523
|
+
adapter.setTemplateContent(parent, content);
|
|
524
|
+
nodes[local] = content;
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
case "text": {
|
|
528
|
+
adapter.insertText(parent, (snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
529
|
+
const children = adapter.getChildNodes(parent);
|
|
530
|
+
nodes[local] = children[children.length - 1];
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
case "comment": {
|
|
534
|
+
const comment = adapter.createCommentNode((snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
535
|
+
adapter.appendChild(parent, comment);
|
|
536
|
+
nodes[local] = comment;
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
case "directive": {
|
|
540
|
+
if (!record || record.name !== "!doctype" || !isDocument2) return void 0;
|
|
541
|
+
adapter.setDocumentType(parent, record["x-name"] ?? "", record["x-publicId"] ?? "", record["x-systemId"] ?? "");
|
|
542
|
+
nodes[local] = Array.from(adapter.getChildNodes(parent) ?? []).find((child) => adapter.isDocumentTypeNode(child));
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
default:
|
|
546
|
+
return void 0;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const changes = differencesFromParse(adapter, nodes, state, root);
|
|
550
|
+
if (!changes) return void 0;
|
|
551
|
+
for (const change of changes) operation(document, "setNode", { id: state.base + change.local, field: change.field, value: change.value });
|
|
552
|
+
return nodes;
|
|
553
|
+
}
|
|
554
|
+
function attributeList(record) {
|
|
555
|
+
const attributes = record.attribs ?? {};
|
|
556
|
+
return Object.keys(attributes).map((name) => {
|
|
557
|
+
const namespace = record.attribsNamespace?.[name];
|
|
558
|
+
const prefix = record.attribsPrefix?.[name];
|
|
559
|
+
return { name, value: attributes[name], ...namespace === void 0 ? {} : { namespace }, ...prefix === void 0 ? {} : { prefix } };
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
function differencesFromParse(adapter, nodes, state, root) {
|
|
563
|
+
const changes = [];
|
|
564
|
+
for (let local = 0; local < nodes.length; local++) {
|
|
565
|
+
const node = nodes[local];
|
|
566
|
+
const snapshot = plainSnapshot(state, local);
|
|
567
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
568
|
+
if (!snapshot && !record) continue;
|
|
569
|
+
if (!node) return void 0;
|
|
570
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
571
|
+
if (local !== root && adapter.getParentNode(node) !== nodes[snapshot ? snapshot.linkOf(local, 1) : record.parent]) return void 0;
|
|
572
|
+
if (type !== "text" && type !== "comment" && type !== "directive") {
|
|
573
|
+
const children = adapter.getChildNodes(node) ?? [];
|
|
574
|
+
const count = snapshot ? snapshot.childCount(local) : record.children.length;
|
|
575
|
+
if (children.length !== count) return void 0;
|
|
576
|
+
for (let index = 0; index < count; index++) if (children[index] !== nodes[snapshot ? snapshot.childAt(local, index) : record.children[index]]) return void 0;
|
|
577
|
+
}
|
|
578
|
+
if (type === "tag" || type === "script" || type === "style") {
|
|
579
|
+
const name = snapshot ? snapshot.nameOf(local) : record.name;
|
|
580
|
+
const namespace = snapshot ? snapshot.namespaceOf(local) : record.namespace;
|
|
581
|
+
if (!adapter.isElementNode(node) || adapter.getTagName(node) !== name || adapter.getNamespaceURI(node) !== namespace) return void 0;
|
|
582
|
+
const attributes = adapter.getAttrList(node) ?? [];
|
|
583
|
+
const expected = snapshot ? snapshot.attributeObjects(local) : attributeList(record);
|
|
584
|
+
const isSame = attributes.length === expected.length && attributes.every((attribute, index) => attribute.name === expected[index].name && attribute.value === expected[index].value);
|
|
585
|
+
if (!isSame) {
|
|
586
|
+
const values = /* @__PURE__ */ Object.create(null);
|
|
587
|
+
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
588
|
+
const prefixes = /* @__PURE__ */ Object.create(null);
|
|
589
|
+
for (const attribute of attributes) {
|
|
590
|
+
values[attribute.name] = attribute.value;
|
|
591
|
+
if (attribute.namespace !== void 0) namespaces[attribute.name] = attribute.namespace;
|
|
592
|
+
if (attribute.prefix !== void 0) prefixes[attribute.name] = attribute.prefix;
|
|
593
|
+
}
|
|
594
|
+
changes.push({ local, field: "attribs", value: values }, { local, field: "attribsNamespace", value: namespaces }, { local, field: "attribsPrefix", value: prefixes });
|
|
595
|
+
}
|
|
596
|
+
} else if (type === "text" || type === "comment") {
|
|
597
|
+
if (type === "text" ? !adapter.isTextNode(node) : !adapter.isCommentNode(node)) return void 0;
|
|
598
|
+
const data2 = type === "text" ? adapter.getTextNodeContent(node) : adapter.getCommentNodeContent(node);
|
|
599
|
+
if (data2 !== (snapshot ? snapshot.dataOf(local) : record.data)) changes.push({ local, field: "data", value: data2 });
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return changes;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/snapshot.ts
|
|
606
|
+
var HEADER = 5;
|
|
607
|
+
var STRIDE = 15;
|
|
608
|
+
var ABSENT = 4294967295;
|
|
609
|
+
var HAS_START_INDEX = 1;
|
|
610
|
+
var HAS_END_INDEX = 2;
|
|
611
|
+
var HAS_NAMESPACE = 4;
|
|
612
|
+
var EMPTY_ATTRIBUTE_MAPS = 8;
|
|
613
|
+
var OPAQUE = 16;
|
|
614
|
+
var RELEASED = 32;
|
|
615
|
+
var noChildren = Object.freeze([]);
|
|
616
|
+
var noAttributes = Object.freeze({});
|
|
617
|
+
var SnapshotRecord = class {
|
|
618
|
+
constructor(snapshot, id, base) {
|
|
619
|
+
this.snapshot = snapshot;
|
|
620
|
+
this.id = id;
|
|
621
|
+
this.base = base;
|
|
622
|
+
this.decodedData = void 0;
|
|
623
|
+
this.decodedAttributes = void 0;
|
|
624
|
+
this.decodedChildren = void 0;
|
|
625
|
+
}
|
|
626
|
+
snapshot;
|
|
627
|
+
id;
|
|
628
|
+
base;
|
|
629
|
+
decodedData;
|
|
630
|
+
decodedAttributes;
|
|
631
|
+
decodedChildren;
|
|
632
|
+
get type() {
|
|
633
|
+
return this.snapshot.name(this.snapshot.nodes[this.base]);
|
|
634
|
+
}
|
|
635
|
+
get name() {
|
|
636
|
+
const name = this.snapshot.nodes[this.base + 6];
|
|
637
|
+
return name ? this.snapshot.name(name - 1) : void 0;
|
|
638
|
+
}
|
|
639
|
+
get data() {
|
|
640
|
+
if (this.decodedData !== void 0) return this.decodedData;
|
|
641
|
+
const data2 = this.snapshot.nodes[this.base + 7];
|
|
642
|
+
return data2 ? this.decodedData = this.snapshot.string(data2 - 1) : void 0;
|
|
643
|
+
}
|
|
644
|
+
get parent() {
|
|
645
|
+
const parent = this.snapshot.nodes[this.base + 1];
|
|
646
|
+
return parent ? parent - 1 : null;
|
|
647
|
+
}
|
|
648
|
+
get prev() {
|
|
649
|
+
const prev = this.snapshot.nodes[this.base + 2];
|
|
650
|
+
return prev ? prev - 1 : null;
|
|
651
|
+
}
|
|
652
|
+
get next() {
|
|
653
|
+
const next = this.snapshot.nodes[this.base + 3];
|
|
654
|
+
return next ? next - 1 : null;
|
|
655
|
+
}
|
|
656
|
+
get startIndex() {
|
|
657
|
+
return this.index(HAS_START_INDEX, 11);
|
|
658
|
+
}
|
|
659
|
+
get endIndex() {
|
|
660
|
+
return this.index(HAS_END_INDEX, 12);
|
|
661
|
+
}
|
|
662
|
+
get namespace() {
|
|
663
|
+
const nodes = this.snapshot.nodes;
|
|
664
|
+
return nodes[this.base + 10] & HAS_NAMESPACE ? this.snapshot.name(nodes[this.base + 13]) : void 0;
|
|
665
|
+
}
|
|
666
|
+
get attribsNamespace() {
|
|
667
|
+
return this.snapshot.nodes[this.base + 10] & EMPTY_ATTRIBUTE_MAPS ? {} : void 0;
|
|
668
|
+
}
|
|
669
|
+
get attribsPrefix() {
|
|
670
|
+
return this.snapshot.nodes[this.base + 10] & EMPTY_ATTRIBUTE_MAPS ? {} : void 0;
|
|
671
|
+
}
|
|
672
|
+
get attribs() {
|
|
673
|
+
return this.decodedAttributes ??= this.snapshot.attributesOf(this.id);
|
|
674
|
+
}
|
|
675
|
+
get children() {
|
|
676
|
+
return this.decodedChildren ??= this.snapshot.childrenOf(this.id);
|
|
677
|
+
}
|
|
678
|
+
index(flag, offset) {
|
|
679
|
+
const nodes = this.snapshot.nodes;
|
|
680
|
+
if (!(nodes[this.base + 10] & flag)) return void 0;
|
|
681
|
+
const value = nodes[this.base + offset];
|
|
682
|
+
return value === ABSENT ? null : value;
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
var recordFields = ["type", "name", "data", "parent", "prev", "next", "startIndex", "endIndex", "namespace", "attribsNamespace", "attribsPrefix", "attribs", "children"];
|
|
686
|
+
function plainRecord(record) {
|
|
687
|
+
if (!(record instanceof SnapshotRecord)) return record;
|
|
688
|
+
const copy = { id: record.id };
|
|
689
|
+
for (const field of recordFields) {
|
|
690
|
+
const value = record[field];
|
|
691
|
+
if (value !== void 0) copy[field] = value;
|
|
692
|
+
}
|
|
693
|
+
for (const key of Object.keys(record)) if (!key.startsWith("decoded") && key !== "snapshot" && key !== "base" && key !== "id") copy[key] = record[key];
|
|
694
|
+
return copy;
|
|
695
|
+
}
|
|
696
|
+
var NodeSnapshot = class {
|
|
697
|
+
size;
|
|
698
|
+
nodes;
|
|
699
|
+
children;
|
|
700
|
+
attributes;
|
|
701
|
+
strings;
|
|
702
|
+
text;
|
|
703
|
+
isEncoded;
|
|
704
|
+
names = [];
|
|
705
|
+
/** Node object constructors by interned type, resolved once per snapshot. */
|
|
706
|
+
viewConstructors = void 0;
|
|
707
|
+
constructor(raw) {
|
|
708
|
+
const { data: data2 } = raw;
|
|
709
|
+
const childrenStart = HEADER + data2[0];
|
|
710
|
+
const attributesStart = childrenStart + data2[1];
|
|
711
|
+
const stringsStart = attributesStart + data2[2];
|
|
712
|
+
this.text = raw.text;
|
|
713
|
+
this.isEncoded = data2[4] === 1;
|
|
714
|
+
this.nodes = data2.subarray(HEADER, childrenStart);
|
|
715
|
+
this.children = data2.subarray(childrenStart, attributesStart);
|
|
716
|
+
this.attributes = data2.subarray(attributesStart, stringsStart);
|
|
717
|
+
this.strings = data2.subarray(stringsStart, stringsStart + data2[3]);
|
|
718
|
+
this.size = this.nodes.length / STRIDE;
|
|
719
|
+
}
|
|
720
|
+
/** The record, `null` for a released node, or `undefined` when it must be read individually. */
|
|
721
|
+
record(local) {
|
|
722
|
+
if (local >= this.size) return void 0;
|
|
723
|
+
const base = local * STRIDE;
|
|
724
|
+
const flags = this.nodes[base + 10];
|
|
725
|
+
if (flags & RELEASED) return null;
|
|
726
|
+
if (flags & OPAQUE) return void 0;
|
|
727
|
+
const record = new SnapshotRecord(this, local, base);
|
|
728
|
+
const extras = this.nodes[base + 14];
|
|
729
|
+
if (extras) {
|
|
730
|
+
const fields = JSON.parse(this.string(extras - 1));
|
|
731
|
+
for (const key of Object.keys(fields)) Object.defineProperty(record, key, { value: fields[key], writable: true, enumerable: true, configurable: true });
|
|
732
|
+
}
|
|
733
|
+
return record;
|
|
734
|
+
}
|
|
735
|
+
/** Whether a node's fields all live in the arrays, so callers may read them without a record. */
|
|
736
|
+
isPlain(local) {
|
|
737
|
+
if (local >= this.size) return false;
|
|
738
|
+
const base = local * STRIDE;
|
|
739
|
+
return (this.nodes[base + 10] & (OPAQUE | RELEASED)) === 0 && this.nodes[base + 14] === 0;
|
|
740
|
+
}
|
|
741
|
+
typeOf(local) {
|
|
742
|
+
return this.name(this.nodes[local * STRIDE]);
|
|
743
|
+
}
|
|
744
|
+
nameOf(local) {
|
|
745
|
+
const name = this.nodes[local * STRIDE + 6];
|
|
746
|
+
return name ? this.name(name - 1) : void 0;
|
|
747
|
+
}
|
|
748
|
+
dataOf(local) {
|
|
749
|
+
const data2 = this.nodes[local * STRIDE + 7];
|
|
750
|
+
return data2 ? this.string(data2 - 1) : void 0;
|
|
751
|
+
}
|
|
752
|
+
/** The parent, previous or next sibling (`offset` 1, 2 or 3), or `null`. */
|
|
753
|
+
linkOf(local, offset) {
|
|
754
|
+
const link = this.nodes[local * STRIDE + offset];
|
|
755
|
+
return link ? link - 1 : null;
|
|
756
|
+
}
|
|
757
|
+
namespaceOf(local) {
|
|
758
|
+
const base = local * STRIDE;
|
|
759
|
+
return this.nodes[base + 10] & HAS_NAMESPACE ? this.name(this.nodes[base + 13]) : void 0;
|
|
760
|
+
}
|
|
761
|
+
/** A node's attributes as parse5 attribute objects; plain nodes have no namespaced ones. */
|
|
762
|
+
attributeObjects(local) {
|
|
763
|
+
const base = local * STRIDE;
|
|
764
|
+
const count = this.nodes[base + 9];
|
|
765
|
+
const first = this.nodes[base + 8];
|
|
766
|
+
const attributes = this.attributes;
|
|
767
|
+
const result = new Array(count);
|
|
768
|
+
for (let index = 0; index < count; index++) {
|
|
769
|
+
const pair = (first + index) * 2;
|
|
770
|
+
result[index] = { name: this.name(attributes[pair]), value: this.string(attributes[pair + 1]) };
|
|
771
|
+
}
|
|
772
|
+
return result;
|
|
773
|
+
}
|
|
774
|
+
/** Copies a node's attributes onto `target`, in order. */
|
|
775
|
+
copyAttributes(local, target) {
|
|
776
|
+
const base = local * STRIDE;
|
|
777
|
+
const count = this.nodes[base + 9];
|
|
778
|
+
const first = this.nodes[base + 8];
|
|
779
|
+
const attributes = this.attributes;
|
|
780
|
+
for (let index = 0; index < count; index++) {
|
|
781
|
+
const pair = (first + index) * 2;
|
|
782
|
+
const name = this.name(attributes[pair]);
|
|
783
|
+
const value = this.string(attributes[pair + 1]);
|
|
784
|
+
if (name === "__proto__") Object.defineProperty(target, name, { value, writable: true, enumerable: true, configurable: true });
|
|
785
|
+
else target[name] = value;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
/** The flat child id list; a node's children start at `childStart(local)`. */
|
|
789
|
+
get childIds() {
|
|
790
|
+
return this.children;
|
|
791
|
+
}
|
|
792
|
+
childStart(local) {
|
|
793
|
+
return this.nodes[local * STRIDE + 4];
|
|
794
|
+
}
|
|
795
|
+
/** The interned reference of a node's type, comparable across nodes of this snapshot. */
|
|
796
|
+
typeReference(local) {
|
|
797
|
+
return this.nodes[local * STRIDE];
|
|
798
|
+
}
|
|
799
|
+
/** Child ids without materializing the record. */
|
|
800
|
+
childCount(local) {
|
|
801
|
+
return this.nodes[local * STRIDE + 5];
|
|
802
|
+
}
|
|
803
|
+
childAt(local, index) {
|
|
804
|
+
return this.children[this.nodes[local * STRIDE + 4] + index];
|
|
805
|
+
}
|
|
806
|
+
childrenOf(local) {
|
|
807
|
+
const base = local * STRIDE;
|
|
808
|
+
const count = this.nodes[base + 5];
|
|
809
|
+
if (count === 0) return noChildren;
|
|
810
|
+
const first = this.nodes[base + 4];
|
|
811
|
+
return Array.from(this.children.subarray(first, first + count));
|
|
812
|
+
}
|
|
813
|
+
attributesOf(local) {
|
|
814
|
+
const base = local * STRIDE;
|
|
815
|
+
const count = this.nodes[base + 9];
|
|
816
|
+
if (count === 0) return noAttributes;
|
|
817
|
+
const first = this.nodes[base + 8];
|
|
818
|
+
const attributes = this.attributes;
|
|
819
|
+
const result = {};
|
|
820
|
+
for (let index = 0; index < count; index++) {
|
|
821
|
+
const pair = (first + index) * 2;
|
|
822
|
+
const name = this.name(attributes[pair]);
|
|
823
|
+
const value = this.string(attributes[pair + 1]);
|
|
824
|
+
if (name === "__proto__") Object.defineProperty(result, name, { value, writable: true, enumerable: true, configurable: true });
|
|
825
|
+
else result[name] = value;
|
|
826
|
+
}
|
|
827
|
+
return result;
|
|
828
|
+
}
|
|
829
|
+
/** One attribute's value, without decoding the rest. */
|
|
830
|
+
attributeValue(local, name) {
|
|
831
|
+
const base = local * STRIDE;
|
|
832
|
+
const count = this.nodes[base + 9];
|
|
833
|
+
const first = this.nodes[base + 8];
|
|
834
|
+
const attributes = this.attributes;
|
|
835
|
+
for (let index = count - 1; index >= 0; index--) {
|
|
836
|
+
const pair = (first + index) * 2;
|
|
837
|
+
if (this.name(attributes[pair]) === name) return this.string(attributes[pair + 1]);
|
|
838
|
+
}
|
|
839
|
+
return void 0;
|
|
840
|
+
}
|
|
841
|
+
string(reference) {
|
|
842
|
+
const strings = this.strings;
|
|
843
|
+
const value = this.text.slice(strings[reference * 2], strings[reference * 2 + 1]);
|
|
844
|
+
return this.isEncoded ? decodeString(value) : value;
|
|
845
|
+
}
|
|
846
|
+
/** Names repeat across nodes, so each decodes once. */
|
|
847
|
+
name(reference) {
|
|
848
|
+
return this.names[reference] ??= this.string(reference);
|
|
849
|
+
}
|
|
850
|
+
};
|
|
438
851
|
|
|
439
852
|
// src/router.ts
|
|
440
|
-
var
|
|
853
|
+
var STRIDE2 = 2 ** 32;
|
|
854
|
+
var maximumDocuments = 2 ** 21;
|
|
855
|
+
var rootSlots = 1;
|
|
856
|
+
var VIEW_STATE = /* @__PURE__ */ Symbol.for("rusteerio.node.state");
|
|
857
|
+
var VIEW_LOCAL = /* @__PURE__ */ Symbol.for("rusteerio.node.local");
|
|
858
|
+
var VIEW_ATTRIBUTES = /* @__PURE__ */ Symbol.for("rusteerio.node.attributes");
|
|
859
|
+
var VIEW_SELF = /* @__PURE__ */ Symbol.for("rusteerio.node.self");
|
|
860
|
+
var DOCUMENT = /* @__PURE__ */ Symbol.for("rusteerio.selection.document");
|
|
861
|
+
var API = /* @__PURE__ */ Symbol.for("rusteerio.selection.api");
|
|
862
|
+
var IDS = /* @__PURE__ */ Symbol.for("rusteerio.selection.ids");
|
|
863
|
+
var VALUES = /* @__PURE__ */ Symbol.for("rusteerio.selection.values");
|
|
864
|
+
var LEASE = /* @__PURE__ */ Symbol.for("rusteerio.selection.lease");
|
|
865
|
+
var IS_PLAIN = /* @__PURE__ */ Symbol.for("rusteerio.selection.is-plain");
|
|
866
|
+
var VIEW_CHILD_TARGET = /* @__PURE__ */ Symbol.for("rusteerio.node.child-target");
|
|
867
|
+
var registryKey2 = /* @__PURE__ */ Symbol.for(`rusteerio.native-documents.v5:${packageDirectory()}`);
|
|
868
|
+
var stateKey = /* @__PURE__ */ Symbol.for("rusteerio.native-documents.state");
|
|
441
869
|
var globals2 = globalThis;
|
|
442
870
|
var registry2 = globals2[registryKey2] ??= (() => {
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const document = pin.document.deref();
|
|
453
|
-
if (!document) continue;
|
|
454
|
-
const entries = byDocument.get(document);
|
|
455
|
-
if (entries?.get(pin.local)?.pin === pin) entries.delete(pin.local);
|
|
456
|
-
const ids = batches.get(document) ?? [];
|
|
457
|
-
ids.push(pin.local);
|
|
458
|
-
batches.set(document, ids);
|
|
459
|
-
}
|
|
460
|
-
for (const [document, ids] of batches) {
|
|
461
|
-
snapshots.delete(document);
|
|
462
|
-
document.release?.(ids);
|
|
463
|
-
document.collectGarbage?.();
|
|
464
|
-
}
|
|
871
|
+
const created = {
|
|
872
|
+
space: {},
|
|
873
|
+
writes: 0,
|
|
874
|
+
states: [],
|
|
875
|
+
pending: /* @__PURE__ */ new Set(),
|
|
876
|
+
isScheduled: false,
|
|
877
|
+
leaseFinalizer: new FinalizationRegistry((token) => {
|
|
878
|
+
token.isReleased = true;
|
|
879
|
+
})
|
|
465
880
|
};
|
|
466
|
-
return
|
|
467
|
-
if (!handles.get(pin.global)?.deref()) handles.delete(pin.global);
|
|
468
|
-
pending.push(pin);
|
|
469
|
-
if (!scheduled) {
|
|
470
|
-
scheduled = true;
|
|
471
|
-
queueMicrotask(flush);
|
|
472
|
-
}
|
|
473
|
-
}) };
|
|
881
|
+
return created;
|
|
474
882
|
})();
|
|
883
|
+
function statesOf(document, ids) {
|
|
884
|
+
const states = [];
|
|
885
|
+
let previous;
|
|
886
|
+
for (const id of ids) {
|
|
887
|
+
if (id === void 0) continue;
|
|
888
|
+
if (previous && id >= previous.base && id < previous.base + STRIDE2) continue;
|
|
889
|
+
const state = stateIn(document, id);
|
|
890
|
+
if (!states.includes(state)) states.push(state);
|
|
891
|
+
previous = state;
|
|
892
|
+
}
|
|
893
|
+
return states;
|
|
894
|
+
}
|
|
895
|
+
function scheduleCollectionIfDue(state) {
|
|
896
|
+
if (state.raw.isCollectionDue?.()) scheduleCollection(state);
|
|
897
|
+
}
|
|
898
|
+
function scheduleCollection(state) {
|
|
899
|
+
registry2.pending.add(state);
|
|
900
|
+
if (registry2.pending.size > maximumPendingCollections) {
|
|
901
|
+
const evicted = registry2.pending.values().next().value;
|
|
902
|
+
registry2.pending.delete(evicted);
|
|
903
|
+
evicted.isCollectionEvicted = true;
|
|
904
|
+
}
|
|
905
|
+
if (registry2.isScheduled) return;
|
|
906
|
+
registry2.isScheduled = true;
|
|
907
|
+
setImmediate(() => {
|
|
908
|
+
registry2.isScheduled = false;
|
|
909
|
+
const states = [...registry2.pending];
|
|
910
|
+
registry2.pending.clear();
|
|
911
|
+
for (const pending of states) collectState(pending);
|
|
912
|
+
}).unref();
|
|
913
|
+
}
|
|
914
|
+
var maximumPendingCollections = 4;
|
|
915
|
+
function writeCount() {
|
|
916
|
+
return registry2.writes;
|
|
917
|
+
}
|
|
918
|
+
function stateFor(raw, options = {}) {
|
|
919
|
+
const holder = raw;
|
|
920
|
+
const existing = holder[stateKey];
|
|
921
|
+
if (existing) return existing;
|
|
922
|
+
const index = raw.routingIndex();
|
|
923
|
+
if (index >= maximumDocuments) throw new RangeError("Too many documents are alive at once.");
|
|
924
|
+
const baseline = raw.slotCount?.() ?? 0;
|
|
925
|
+
const state = {
|
|
926
|
+
raw,
|
|
927
|
+
base: index * STRIDE2,
|
|
928
|
+
space: registry2.space,
|
|
929
|
+
options,
|
|
930
|
+
rootLocal: void 0,
|
|
931
|
+
routed: void 0,
|
|
932
|
+
// Sized up front: node objects are cached out of order, and regrowing a holey array is costly.
|
|
933
|
+
generation: 0,
|
|
934
|
+
records: [],
|
|
935
|
+
bulk: 0,
|
|
936
|
+
snapshotSize: 0,
|
|
937
|
+
stale: /* @__PURE__ */ new Set(),
|
|
938
|
+
views: new Array(baseline),
|
|
939
|
+
looseViews: /* @__PURE__ */ new Map(),
|
|
940
|
+
looseViewLimit: minimumLooseViewLimit,
|
|
941
|
+
weakViews: /* @__PURE__ */ new Map(),
|
|
942
|
+
baseline,
|
|
943
|
+
leases: /* @__PURE__ */ new Set(),
|
|
944
|
+
leaseSweepSize: 64,
|
|
945
|
+
data: /* @__PURE__ */ new Map(),
|
|
946
|
+
isExposed: false,
|
|
947
|
+
hasChildLists: false,
|
|
948
|
+
collectionRetries: 0,
|
|
949
|
+
isCollectionEvicted: false
|
|
950
|
+
};
|
|
951
|
+
holder[stateKey] = state;
|
|
952
|
+
return state;
|
|
953
|
+
}
|
|
954
|
+
function exposeState(state) {
|
|
955
|
+
if (state.isExposed) return;
|
|
956
|
+
state.isExposed = true;
|
|
957
|
+
registry2.states[state.base / STRIDE2] = new WeakRef(state);
|
|
958
|
+
}
|
|
959
|
+
function exposeTo(document, state) {
|
|
960
|
+
if (document.state === state) return;
|
|
961
|
+
exposeState(state);
|
|
962
|
+
}
|
|
963
|
+
function exposeDocumentTo(document, source) {
|
|
964
|
+
const state = source?.state;
|
|
965
|
+
if (state) exposeTo(document, state);
|
|
966
|
+
}
|
|
967
|
+
function cachedView(state, local) {
|
|
968
|
+
const view = local < state.baseline ? state.views[local] : state.looseViews.get(local);
|
|
969
|
+
return view ?? (state.weakViews.size ? state.weakViews.get(local)?.deref() : void 0);
|
|
970
|
+
}
|
|
971
|
+
var minimumLooseViewLimit = 1024;
|
|
972
|
+
function cacheView(state, local, view) {
|
|
973
|
+
if (local < state.baseline) {
|
|
974
|
+
state.views[local] = view;
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
state.looseViews.set(local, view);
|
|
978
|
+
if (state.looseViews.size >= state.looseViewLimit) {
|
|
979
|
+
state.looseViewLimit = state.looseViews.size * 2;
|
|
980
|
+
scheduleCollection(state);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function uncacheView(state, local) {
|
|
984
|
+
const view = cachedView(state, local);
|
|
985
|
+
if (local < state.baseline) state.views[local] = void 0;
|
|
986
|
+
state.looseViews.delete(local);
|
|
987
|
+
state.weakViews.delete(local);
|
|
988
|
+
return view;
|
|
989
|
+
}
|
|
990
|
+
function releaseSlotsFrom(state, end) {
|
|
991
|
+
for (const local of state.data.keys()) if (local >= end) releaseSlot(state, local);
|
|
992
|
+
for (const local of state.weakViews.keys()) if (local >= end) state.weakViews.delete(local);
|
|
993
|
+
if (state.adapterNodes && state.adapterNodes.length > end) {
|
|
994
|
+
for (let local = end; local < state.adapterNodes.length; local++) releaseAdapterNode(state, local);
|
|
995
|
+
state.adapterNodes.length = end;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
function releaseSlot(state, local) {
|
|
999
|
+
uncacheView(state, local);
|
|
1000
|
+
const entry = state.data.get(local);
|
|
1001
|
+
if (entry) {
|
|
1002
|
+
entry.isReleased = true;
|
|
1003
|
+
state.data.delete(local);
|
|
1004
|
+
}
|
|
1005
|
+
releaseAdapterNode(state, local);
|
|
1006
|
+
}
|
|
1007
|
+
function releaseAdapterNode(state, local) {
|
|
1008
|
+
const adapterNode = state.adapterNodes?.[local];
|
|
1009
|
+
if (!adapterNode) return;
|
|
1010
|
+
adapterNode[VIEW_SELF] = void 0;
|
|
1011
|
+
state.adapterNodes[local] = void 0;
|
|
1012
|
+
}
|
|
1013
|
+
function hasViews(state) {
|
|
1014
|
+
return state.views.length > 0 || state.looseViews.size > 0 || state.weakViews.size > 0;
|
|
1015
|
+
}
|
|
1016
|
+
function forEachView(state, visit) {
|
|
1017
|
+
state.views.forEach((view, local) => {
|
|
1018
|
+
if (view) visit(view, local);
|
|
1019
|
+
});
|
|
1020
|
+
for (const [local, view] of state.looseViews) visit(view, local);
|
|
1021
|
+
for (const [local, reference] of state.weakViews) {
|
|
1022
|
+
const view = reference.deref();
|
|
1023
|
+
if (view) visit(view, local);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
function weakenDetachedViews(state) {
|
|
1027
|
+
if (!state.raw.detachedSlots) return false;
|
|
1028
|
+
let isWeakened = false;
|
|
1029
|
+
for (const local of state.raw.detachedSlots(state.rootLocal ??= state.raw.rootId())) {
|
|
1030
|
+
const view = local < state.baseline ? state.views[local] : state.looseViews.get(local);
|
|
1031
|
+
if (!view) continue;
|
|
1032
|
+
if (local < state.baseline) state.views[local] = void 0;
|
|
1033
|
+
else state.looseViews.delete(local);
|
|
1034
|
+
state.weakViews.set(local, new WeakRef(view));
|
|
1035
|
+
isWeakened = true;
|
|
1036
|
+
}
|
|
1037
|
+
return isWeakened;
|
|
1038
|
+
}
|
|
1039
|
+
function exposedStateOf(id) {
|
|
1040
|
+
const state = registry2.states[Math.floor(id / STRIDE2)]?.deref();
|
|
1041
|
+
if (!state || !(id >= 0)) throw new RangeError(`Unknown native node handle ${id}`);
|
|
1042
|
+
return state;
|
|
1043
|
+
}
|
|
1044
|
+
function stateIn(document, id) {
|
|
1045
|
+
const own = document.state;
|
|
1046
|
+
if (own === void 0 || id < own.base || id >= own.base + STRIDE2) return exposedStateOf(id);
|
|
1047
|
+
if (own.isCollectionEvicted) resumeCollection(document);
|
|
1048
|
+
return own;
|
|
1049
|
+
}
|
|
1050
|
+
function resumeCollection(document) {
|
|
1051
|
+
const state = document.state;
|
|
1052
|
+
if (!state?.isCollectionEvicted) return;
|
|
1053
|
+
state.isCollectionEvicted = false;
|
|
1054
|
+
scheduleCollection(state);
|
|
1055
|
+
}
|
|
1056
|
+
function recordAt(state, local) {
|
|
1057
|
+
const cached2 = state.records[local];
|
|
1058
|
+
if (cached2 !== void 0) return cached2;
|
|
1059
|
+
const record = readRecord(state, local);
|
|
1060
|
+
state.records[local] = record;
|
|
1061
|
+
return record;
|
|
1062
|
+
}
|
|
1063
|
+
var minimumReadsBeforeSnapshot = 64;
|
|
1064
|
+
function readRecord(state, local) {
|
|
1065
|
+
const bulk = state.bulk;
|
|
1066
|
+
if (bulk instanceof NodeSnapshot) {
|
|
1067
|
+
const record = state.stale.size && state.stale.has(local) ? void 0 : bulk.record(local);
|
|
1068
|
+
if (record !== void 0) return record;
|
|
1069
|
+
} else if (state.raw.snapshot) {
|
|
1070
|
+
const reads = bulk + 1;
|
|
1071
|
+
const size = Math.max(state.snapshotSize, state.baseline);
|
|
1072
|
+
const firstSnapshotRead = state.generation === 0 ? size / 100 : 1 + size / 100;
|
|
1073
|
+
if (reads >= Math.min(minimumReadsBeforeSnapshot, firstSnapshotRead)) {
|
|
1074
|
+
const snapshot = new NodeSnapshot(state.raw.snapshot());
|
|
1075
|
+
state.snapshotSize = snapshot.size;
|
|
1076
|
+
state.bulk = snapshot;
|
|
1077
|
+
const record = snapshot.record(local);
|
|
1078
|
+
if (record !== void 0) return record;
|
|
1079
|
+
} else state.bulk = reads;
|
|
1080
|
+
}
|
|
1081
|
+
return rawOperation(state.raw, "node", { id: local });
|
|
1082
|
+
}
|
|
1083
|
+
function plainSnapshot(state, local) {
|
|
1084
|
+
const bulk = state.bulk;
|
|
1085
|
+
return bulk instanceof NodeSnapshot && !(state.stale.size && state.stale.has(local)) && bulk.isPlain(local) ? bulk : void 0;
|
|
1086
|
+
}
|
|
1087
|
+
function attributeAt(state, local, name) {
|
|
1088
|
+
const snapshot = plainSnapshot(state, local);
|
|
1089
|
+
if (snapshot) return snapshot.attributeValue(local, name);
|
|
1090
|
+
const attributes = recordAt(state, local)?.attribs;
|
|
1091
|
+
const value = attributes && Object.hasOwn(attributes, name) ? attributes[name] : void 0;
|
|
1092
|
+
return typeof value === "string" ? value : void 0;
|
|
1093
|
+
}
|
|
1094
|
+
function invalidate(state) {
|
|
1095
|
+
state.generation++;
|
|
1096
|
+
state.records = [];
|
|
1097
|
+
state.bulk = 0;
|
|
1098
|
+
state.stale.clear();
|
|
1099
|
+
}
|
|
1100
|
+
function invalidateNodes(state, locals) {
|
|
1101
|
+
const isSnapshot = state.bulk instanceof NodeSnapshot;
|
|
1102
|
+
for (const local of locals) {
|
|
1103
|
+
state.records[local] = void 0;
|
|
1104
|
+
if (isSnapshot) state.stale.add(local);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function leaseNodes(document, owner, ids) {
|
|
1108
|
+
const token = { isReleased: false };
|
|
1109
|
+
const states = statesOf(document, ids);
|
|
1110
|
+
const lease = { ids, token, states };
|
|
1111
|
+
for (const state of states) addLease(state, lease);
|
|
1112
|
+
registry2.leaseFinalizer.register(owner, token);
|
|
1113
|
+
return lease;
|
|
1114
|
+
}
|
|
1115
|
+
function updateLease(document, lease, ids) {
|
|
1116
|
+
lease.ids = ids;
|
|
1117
|
+
lease.states = statesOf(document, ids);
|
|
1118
|
+
for (const state of lease.states) addLease(state, lease);
|
|
1119
|
+
}
|
|
1120
|
+
function addLease(state, lease) {
|
|
1121
|
+
state.leases.add(lease);
|
|
1122
|
+
if (state.leases.size < state.leaseSweepSize) return;
|
|
1123
|
+
for (const held of state.leases) if (held.token.isReleased) state.leases.delete(held);
|
|
1124
|
+
state.leaseSweepSize = state.leases.size * 2 + 64;
|
|
1125
|
+
}
|
|
1126
|
+
var collectionRetries = 3;
|
|
1127
|
+
function collectState(state) {
|
|
1128
|
+
registry2.pending.delete(state);
|
|
1129
|
+
state.isCollectionEvicted = false;
|
|
1130
|
+
if (!state.raw.collectPinned) return state.raw.collectGarbage?.();
|
|
1131
|
+
if (weakenDetachedViews(state)) state.collectionRetries = collectionRetries;
|
|
1132
|
+
const pins = [];
|
|
1133
|
+
const { base } = state;
|
|
1134
|
+
const end = base + STRIDE2;
|
|
1135
|
+
for (const lease of state.leases) {
|
|
1136
|
+
if (lease.token.isReleased) {
|
|
1137
|
+
state.leases.delete(lease);
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
for (const id of lease.ids) if (id >= base && id < end) pins.push(id - base);
|
|
1141
|
+
}
|
|
1142
|
+
state.views.forEach((view, local) => {
|
|
1143
|
+
if (view) pins.push(local);
|
|
1144
|
+
});
|
|
1145
|
+
for (const local of state.looseViews.keys()) pins.push(local);
|
|
1146
|
+
for (const [local, reference] of state.weakViews) {
|
|
1147
|
+
if (reference.deref()) pins.push(local);
|
|
1148
|
+
else state.weakViews.delete(local);
|
|
1149
|
+
}
|
|
1150
|
+
const { free, ...stats } = state.raw.collectPinned(Uint32Array.from(pins), rootSlots);
|
|
1151
|
+
invalidate(state);
|
|
1152
|
+
for (const local of free) releaseSlot(state, local);
|
|
1153
|
+
releaseSlotsFrom(state, stats.slots);
|
|
1154
|
+
state.looseViewLimit = Math.max(minimumLooseViewLimit, state.looseViews.size * 2);
|
|
1155
|
+
if (state.collectionRetries > 0 && state.weakViews.size > 0) {
|
|
1156
|
+
state.collectionRetries--;
|
|
1157
|
+
scheduleCollection(state);
|
|
1158
|
+
}
|
|
1159
|
+
return stats;
|
|
1160
|
+
}
|
|
475
1161
|
function rawOperation(document, command, args) {
|
|
476
1162
|
const result = document.op(command, JSON.stringify(args));
|
|
477
1163
|
return result === "" || result === void 0 ? void 0 : JSON.parse(result);
|
|
478
1164
|
}
|
|
479
|
-
function
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
return handle;
|
|
497
|
-
}
|
|
498
|
-
function retainNodes(document, ids) {
|
|
499
|
-
return document.retainNodes?.(ids) ?? {};
|
|
500
|
-
}
|
|
501
|
-
var RoutedDocument = class _RoutedDocument {
|
|
1165
|
+
function globalRecord(state, record) {
|
|
1166
|
+
if (!record) return null;
|
|
1167
|
+
const { base } = state;
|
|
1168
|
+
const link = (local) => local == null ? null : base + local;
|
|
1169
|
+
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) };
|
|
1170
|
+
}
|
|
1171
|
+
var parentTypes = /* @__PURE__ */ new Set(["root", "tag", "script", "style", "cdata"]);
|
|
1172
|
+
var pointerFields = /* @__PURE__ */ new Set(["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"]);
|
|
1173
|
+
var idResultCommands = /* @__PURE__ */ new Set(["select", "matches", "uniqueSort", "traverse", "clone"]);
|
|
1174
|
+
var scratchCommands = /* @__PURE__ */ new Set(["select", "matches", "uniqueSort", "serializeArray", "serialize", "extractPlan"]);
|
|
1175
|
+
var writeCommands = /* @__PURE__ */ new Set(["create", "createNode", "setNode", "import", "insert", "clone", "remove", "removeAttr", "removeData", "addClass", "removeClass", "toggleClass"]);
|
|
1176
|
+
var attributeFields = /* @__PURE__ */ new Set(["attribs", "x-attribsNamespace", "x-attribsPrefix"]);
|
|
1177
|
+
var targetedAttributeWrites = /* @__PURE__ */ new Set(["attr", "removeAttr", "addClass", "removeClass", "toggleClass", "css"]);
|
|
1178
|
+
var recordOnlyWrites = /* @__PURE__ */ new Set([...targetedAttributeWrites, "data", "removeData"]);
|
|
1179
|
+
var structuralWrites = /* @__PURE__ */ new Set(["create", "createNode", "import", "insert", "clone", "remove", "html", "text", "data", "removeData"]);
|
|
1180
|
+
var RoutedDocument = class {
|
|
502
1181
|
nodeSpace = registry2.space;
|
|
503
1182
|
options;
|
|
504
|
-
|
|
1183
|
+
state;
|
|
505
1184
|
get raw() {
|
|
506
|
-
return this.
|
|
1185
|
+
return this.state.raw;
|
|
507
1186
|
}
|
|
508
|
-
constructor(document, options = {}
|
|
1187
|
+
constructor(document, options = {}) {
|
|
509
1188
|
this.options = options;
|
|
510
|
-
this.
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
1189
|
+
this.state = stateFor(document, options);
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Sets (or with `null` removes) an attribute, as the `attr` command does,
|
|
1193
|
+
* through a typed native call. Attribute objects already handed out are
|
|
1194
|
+
* updated in place instead of being read back.
|
|
1195
|
+
*/
|
|
1196
|
+
setAttribute(ids, name, value) {
|
|
1197
|
+
registry2.writes++;
|
|
1198
|
+
for (const { state, locals } of this.groups(ids)) {
|
|
1199
|
+
if (!state.raw.setAttribute) {
|
|
1200
|
+
this.call(state, "attr", { ids: locals, name, value });
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
invalidateNodes(state, locals);
|
|
1204
|
+
state.raw.setAttribute(locals, name, value);
|
|
1205
|
+
for (const local of locals) {
|
|
1206
|
+
const target = cachedView(state, local)?.[VIEW_ATTRIBUTES]?.target;
|
|
1207
|
+
if (!target) continue;
|
|
1208
|
+
if (value === null) delete target[name];
|
|
1209
|
+
else if (name === "__proto__") Object.defineProperty(target, name, { value, writable: true, enumerable: true, configurable: true });
|
|
1210
|
+
else target[name] = value;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
525
1213
|
}
|
|
526
1214
|
retainNode(id) {
|
|
527
|
-
this.
|
|
528
|
-
}
|
|
529
|
-
retainNodes(ids) {
|
|
530
|
-
return ids.filter((id) => id !== void 0).map((id) => this.lookup(id));
|
|
531
|
-
}
|
|
532
|
-
nodeDocument(id) {
|
|
533
|
-
return new _RoutedDocument(this.raw, this.options, this.lookup(id));
|
|
1215
|
+
this.owner(id);
|
|
534
1216
|
}
|
|
535
1217
|
collectGarbage() {
|
|
536
|
-
|
|
537
|
-
return this.raw.collectGarbage?.();
|
|
1218
|
+
return collectState(this.state);
|
|
538
1219
|
}
|
|
539
1220
|
retainNodeData(id, data2) {
|
|
540
|
-
this.
|
|
1221
|
+
dataEntry(this.owner(id), id).data = data2;
|
|
541
1222
|
}
|
|
542
1223
|
nodeData(id) {
|
|
543
|
-
|
|
1224
|
+
const state = this.owner(id);
|
|
1225
|
+
return state.data.get(id - state.base)?.data;
|
|
544
1226
|
}
|
|
545
1227
|
nodeDataOperation(id) {
|
|
546
|
-
const
|
|
1228
|
+
const entry = dataEntry(this.owner(id), id);
|
|
547
1229
|
const options = this.options;
|
|
548
|
-
return (command, args) =>
|
|
1230
|
+
return (command, args) => entry.isReleased ? void 0 : routedFor(entry.state).operate(command, { ...args, ids: [entry.state.base + entry.local], options });
|
|
549
1231
|
}
|
|
550
|
-
localNodeId(
|
|
551
|
-
return this.
|
|
1232
|
+
localNodeId(local) {
|
|
1233
|
+
return this.state.base + local;
|
|
552
1234
|
}
|
|
553
1235
|
rootId() {
|
|
554
|
-
return this.
|
|
1236
|
+
return this.state.base + (this.state.rootLocal ??= this.raw.rootId());
|
|
555
1237
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
1238
|
+
isOwnNode(id) {
|
|
1239
|
+
return id >= this.state.base && id < this.state.base + STRIDE2;
|
|
1240
|
+
}
|
|
1241
|
+
owner(id) {
|
|
1242
|
+
return stateIn(this, id);
|
|
1243
|
+
}
|
|
1244
|
+
globals(state, locals) {
|
|
1245
|
+
const { base } = state;
|
|
1246
|
+
return locals.map((local) => base + local);
|
|
562
1247
|
}
|
|
563
1248
|
groups(ids) {
|
|
564
1249
|
const groups = [];
|
|
1250
|
+
const own = this.state;
|
|
1251
|
+
let last;
|
|
565
1252
|
for (const id of ids) {
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
last.ids.push(handle.local);
|
|
570
|
-
last.global.push(id);
|
|
571
|
-
} else groups.push({ document: handle.document, ids: [handle.local], global: [id] });
|
|
1253
|
+
const state = id >= own.base && id < own.base + STRIDE2 ? own : exposedStateOf(id);
|
|
1254
|
+
if (last?.state === state) last.locals.push(id - state.base);
|
|
1255
|
+
else groups.push(last = { state, locals: [id - state.base] });
|
|
572
1256
|
}
|
|
573
1257
|
return groups;
|
|
574
1258
|
}
|
|
575
|
-
call(
|
|
576
|
-
if (command === "extractPlan" && JSON.stringify(args.plan).includes("innerHTML"))
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if (handle) {
|
|
604
|
-
handle.document = target;
|
|
605
|
-
handle.local = newLocal;
|
|
606
|
-
}
|
|
607
|
-
localMap(target).set(newLocal, entry);
|
|
608
|
-
}
|
|
1259
|
+
call(state, command, args) {
|
|
1260
|
+
if (command === "extractPlan" && JSON.stringify(args.plan).includes("innerHTML")) invalidate(state);
|
|
1261
|
+
const isWrite = Object.hasOwn(args, "value") || writeCommands.has(command);
|
|
1262
|
+
if (isWrite) {
|
|
1263
|
+
registry2.writes++;
|
|
1264
|
+
const changed = recordOnlyWrites.has(command) ? args.ids ?? [] : command === "setNode" && attributeFields.has(args.field) ? [args.id] : void 0;
|
|
1265
|
+
if (changed) invalidateNodes(state, changed);
|
|
1266
|
+
else invalidate(state);
|
|
1267
|
+
}
|
|
1268
|
+
const result = rawOperation(state.raw, command, { ...args, options: args.options ?? this.options });
|
|
1269
|
+
if (isWrite) {
|
|
1270
|
+
refreshWrittenAttributes(state, command, args);
|
|
1271
|
+
refreshChildLists(state);
|
|
1272
|
+
scheduleCollectionIfDue(state);
|
|
1273
|
+
}
|
|
1274
|
+
return result;
|
|
1275
|
+
}
|
|
1276
|
+
/** Moves or copies nodes into `target`; returns their local ids there. */
|
|
1277
|
+
moveInto(target, ids, isCopy = false) {
|
|
1278
|
+
if (!isCopy) {
|
|
1279
|
+
for (const group of this.groups(ids)) {
|
|
1280
|
+
if (group.state === target) continue;
|
|
1281
|
+
if (!target.raw.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
1282
|
+
const adopted = JSON.parse(target.raw.adopt(group.state.raw, group.locals, true));
|
|
1283
|
+
rehome(group.state, target, adopted.mapping, ids);
|
|
1284
|
+
refreshChildLists(group.state);
|
|
1285
|
+
refreshChildLists(target);
|
|
1286
|
+
scheduleCollectionIfDue(group.state);
|
|
609
1287
|
}
|
|
610
|
-
return ids.map((id) =>
|
|
1288
|
+
return ids.map((id) => id - target.base);
|
|
611
1289
|
}
|
|
612
1290
|
const result = [];
|
|
613
1291
|
for (const group of this.groups(ids)) {
|
|
614
|
-
if (
|
|
615
|
-
result.push(...this.call(target, "clone", { ids: group.
|
|
1292
|
+
if (group.state === target) {
|
|
1293
|
+
result.push(...this.call(target, "clone", { ids: group.locals, deep: true }));
|
|
616
1294
|
continue;
|
|
617
1295
|
}
|
|
618
|
-
if (!target.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
619
|
-
|
|
620
|
-
const adopted = JSON.parse(target.adopt(group.
|
|
1296
|
+
if (!target.raw.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
|
|
1297
|
+
invalidate(target);
|
|
1298
|
+
const adopted = JSON.parse(target.raw.adopt(group.state.raw, group.locals, false));
|
|
621
1299
|
result.push(...adopted.roots);
|
|
622
1300
|
}
|
|
623
1301
|
return result;
|
|
624
1302
|
}
|
|
625
1303
|
scratch(command, args, ids) {
|
|
626
|
-
const
|
|
1304
|
+
const states = [...new Set(ids.map((id) => this.owner(id)))];
|
|
627
1305
|
const scratch = new (requireNative()).NativeDocument("", false, JSON.stringify(args.options ?? this.options));
|
|
628
1306
|
const toScratch = /* @__PURE__ */ new Map();
|
|
629
1307
|
const fromScratch = /* @__PURE__ */ new Map();
|
|
630
|
-
for (const
|
|
631
|
-
const records = JSON.parse(
|
|
1308
|
+
for (const state of states) {
|
|
1309
|
+
const records = JSON.parse(state.raw.exportTree());
|
|
632
1310
|
const roots = records.filter((record) => record.parent == null).map((record) => record.id);
|
|
633
1311
|
if (!scratch.adopt) throw new Error("The native addon does not support native document copies.");
|
|
634
|
-
const copied = JSON.parse(scratch.adopt(
|
|
1312
|
+
const copied = JSON.parse(scratch.adopt(state.raw, roots, false));
|
|
635
1313
|
for (const [local, copy] of copied.mapping) {
|
|
636
|
-
const global =
|
|
1314
|
+
const global = state.base + local;
|
|
637
1315
|
toScratch.set(global, copy);
|
|
638
1316
|
fromScratch.set(copy, global);
|
|
639
1317
|
}
|
|
@@ -641,177 +1319,308 @@ var RoutedDocument = class _RoutedDocument {
|
|
|
641
1319
|
const translated = { ...args };
|
|
642
1320
|
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);
|
|
643
1321
|
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)]));
|
|
644
|
-
const result =
|
|
1322
|
+
const result = rawOperation(scratch, command, { ...translated, options: translated.options ?? this.options });
|
|
645
1323
|
return ["select", "matches", "uniqueSort"].includes(command) ? result.map((id) => fromScratch.get(id)).filter((id) => id !== void 0) : result;
|
|
646
1324
|
}
|
|
1325
|
+
isMixed(groups) {
|
|
1326
|
+
return groups.length > 1 && groups.some((group) => group.state !== groups[0].state);
|
|
1327
|
+
}
|
|
647
1328
|
select(selector, contexts) {
|
|
648
1329
|
const ids = contexts ?? [this.rootId()];
|
|
649
|
-
if (!ids.length) return this.call(this.
|
|
1330
|
+
if (!ids.length) return this.call(this.state, "select", { selector, contexts: [] });
|
|
650
1331
|
const groups = this.groups(ids);
|
|
651
|
-
if (
|
|
1332
|
+
if (this.isMixed(groups)) return this.scratch("select", { selector, contexts: ids }, ids);
|
|
652
1333
|
const group = groups[0];
|
|
653
|
-
const found = group.
|
|
654
|
-
return this.globals(group.
|
|
1334
|
+
const found = group.state === this.state ? group.state.raw.select(selector, group.locals) : this.call(group.state, "select", { selector, contexts: group.locals });
|
|
1335
|
+
return this.globals(group.state, found);
|
|
655
1336
|
}
|
|
656
1337
|
text(ids) {
|
|
657
|
-
return this.groups(ids).map((group) => group.
|
|
1338
|
+
return this.groups(ids).map((group) => group.state.raw.text(group.locals)).join("");
|
|
658
1339
|
}
|
|
659
1340
|
innerHtml(id) {
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
1341
|
+
const state = this.owner(id);
|
|
1342
|
+
const local = id - state.base;
|
|
1343
|
+
const isSplicing = recordAt(state, local)?.children?.some((child) => recordAt(state, child)?.type === "root") ?? false;
|
|
1344
|
+
if (isSplicing) invalidate(state);
|
|
1345
|
+
const html = state === this.state ? state.raw.innerHtml(local) : this.call(state, "html", { ids: [local] });
|
|
1346
|
+
if (isSplicing && state.hasChildLists && childRefresher) forEachView(state, childRefresher);
|
|
1347
|
+
return html;
|
|
663
1348
|
}
|
|
664
1349
|
outerHtml(ids) {
|
|
665
|
-
return this.groups(ids).map((group) => group.
|
|
1350
|
+
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("");
|
|
666
1351
|
}
|
|
667
1352
|
attr(id, name) {
|
|
668
|
-
const
|
|
669
|
-
return this.call(
|
|
1353
|
+
const state = this.owner(id);
|
|
1354
|
+
return this.call(state, "attr", { ids: [id - state.base], name }) ?? void 0;
|
|
670
1355
|
}
|
|
671
1356
|
tagName(id) {
|
|
672
|
-
const
|
|
673
|
-
return
|
|
1357
|
+
const state = this.owner(id);
|
|
1358
|
+
return recordAt(state, id - state.base)?.name;
|
|
674
1359
|
}
|
|
675
1360
|
exportTree() {
|
|
676
|
-
return JSON.stringify(JSON.parse(this.raw.exportTree()).map((record) =>
|
|
1361
|
+
return JSON.stringify(JSON.parse(this.raw.exportTree()).map((record) => globalRecord(this.state, record)));
|
|
677
1362
|
}
|
|
678
1363
|
create(html, contextId) {
|
|
679
|
-
return
|
|
1364
|
+
return this.operate("create", { html, contextId });
|
|
680
1365
|
}
|
|
681
1366
|
op(command, json) {
|
|
682
1367
|
return JSON.stringify(this.operate(command, JSON.parse(json)) ?? null);
|
|
683
1368
|
}
|
|
684
1369
|
operate(command, args) {
|
|
685
1370
|
const options = args.options ?? this.options;
|
|
686
|
-
|
|
1371
|
+
const hasValue = Object.hasOwn(args, "value");
|
|
687
1372
|
if (command === "node") {
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
const
|
|
696
|
-
const
|
|
1373
|
+
const state = this.owner(args.id);
|
|
1374
|
+
return globalRecord(state, recordAt(state, args.id - state.base));
|
|
1375
|
+
}
|
|
1376
|
+
if (command === "createNode") return this.state.base + this.call(this.state, command, args);
|
|
1377
|
+
if (command === "import") return this.globals(this.state, this.call(this.state, command, args));
|
|
1378
|
+
if (command === "create") {
|
|
1379
|
+
const context = args.contextId == null ? void 0 : this.owner(args.contextId);
|
|
1380
|
+
const state = context ?? this.state;
|
|
1381
|
+
const contextLocal = context ? args.contextId - context.base : void 0;
|
|
697
1382
|
if (hasParserHooks(options)) {
|
|
698
|
-
const contextRecord = context ?
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
let
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
if (
|
|
712
|
-
|
|
713
|
-
|
|
1383
|
+
const contextRecord = context ? recordAt(context, contextLocal) : void 0;
|
|
1384
|
+
const children = parsedChildren(args.html, { ...options, ...contextRecord ? { __contextName: contextRecord.name, __contextNamespace: contextRecord.namespace } : {} });
|
|
1385
|
+
return this.globals(state, this.moveInto(state, children));
|
|
1386
|
+
}
|
|
1387
|
+
return this.globals(state, this.call(state, command, { ...args, contextId: contextLocal }));
|
|
1388
|
+
}
|
|
1389
|
+
if (command === "setNode" || command === "prop" && hasValue && (args.name === "children" || args.name === "childNodes" || pointerFields.has(args.name))) {
|
|
1390
|
+
const field = command === "setNode" ? args.field : args.name;
|
|
1391
|
+
let result2 = null;
|
|
1392
|
+
for (const id of command === "setNode" ? [args.id] : args.ids ?? []) {
|
|
1393
|
+
let state = this.owner(id);
|
|
1394
|
+
let nodeId2 = id;
|
|
1395
|
+
let value = args.value;
|
|
1396
|
+
if (field === "children" || field === "childNodes") value = this.moveInto(state, value ?? []);
|
|
1397
|
+
else if (pointerFields.has(field) && value != null) {
|
|
1398
|
+
const pointer = this.owner(value);
|
|
1399
|
+
if (pointer !== state) {
|
|
1400
|
+
const moved = [id];
|
|
1401
|
+
this.moveInto(pointer, moved);
|
|
1402
|
+
nodeId2 = moved[0];
|
|
1403
|
+
state = pointer;
|
|
1404
|
+
}
|
|
1405
|
+
value = args.value - pointer.base;
|
|
714
1406
|
}
|
|
715
|
-
|
|
1407
|
+
const local = nodeId2 - state.base;
|
|
1408
|
+
result2 = this.call(state, command, command === "setNode" ? { ...args, id: local, value } : { ...args, ids: [local], value });
|
|
716
1409
|
}
|
|
717
|
-
|
|
718
|
-
}
|
|
1410
|
+
return result2;
|
|
1411
|
+
}
|
|
1412
|
+
if (command === "insert") {
|
|
719
1413
|
const targets = args.targetIds ?? [];
|
|
720
1414
|
const nodes = args.nodeIds ?? [];
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
const
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
result.push(...this.globals(target.document, inserted));
|
|
1415
|
+
const sameDocument = targets.length > 0 && this.groups([...targets, ...nodes]);
|
|
1416
|
+
if (sameDocument && sameDocument.length === 1) {
|
|
1417
|
+
const { state } = sameDocument[0];
|
|
1418
|
+
const inserted = this.call(state, command, { ...args, targetIds: targets.map((id) => id - state.base), nodeIds: nodes.map((id) => id - state.base) });
|
|
1419
|
+
return this.globals(state, inserted);
|
|
727
1420
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
const
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
const children2 = rawOperation(parsed, "node", { id: parsed.rootId() }).children;
|
|
736
|
-
const local = this.move(target.document, children2);
|
|
737
|
-
result = this.call(target.document, "setNode", { id: target.local, field: "children", value: local, options });
|
|
1421
|
+
const result2 = [];
|
|
1422
|
+
for (let index = 0; index < targets.length; index++) {
|
|
1423
|
+
const target = this.owner(targets[index]);
|
|
1424
|
+
const targetLocal = targets[index] - target.base;
|
|
1425
|
+
const local = this.moveInto(target, nodes, index + 1 < targets.length);
|
|
1426
|
+
const inserted = this.call(target, command, { ...args, targetIds: [targetLocal], nodeIds: local });
|
|
1427
|
+
result2.push(...this.globals(target, inserted));
|
|
738
1428
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
} else if (command === "prop" && Object.hasOwn(args, "value") && ["children", "childNodes", "parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(args.name)) {
|
|
744
|
-
result = null;
|
|
1429
|
+
return result2;
|
|
1430
|
+
}
|
|
1431
|
+
if (command === "html" && hasValue && hasParserHooks(options)) {
|
|
1432
|
+
let result2 = null;
|
|
745
1433
|
for (const id of args.ids ?? []) {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
this.move(pointer.document, [id]);
|
|
753
|
-
handle = this.lookup(id);
|
|
754
|
-
}
|
|
755
|
-
value = this.lookup(args.value).local;
|
|
756
|
-
}
|
|
757
|
-
result = this.call(handle.document, command, { ...args, ids: [handle.local], value });
|
|
1434
|
+
const state = this.owner(id);
|
|
1435
|
+
const local = id - state.base;
|
|
1436
|
+
const record = recordAt(state, local);
|
|
1437
|
+
if (!record || !parentTypes.has(record.type)) continue;
|
|
1438
|
+
const children = parsedChildren(String(args.value), { ...options, __contextName: record.name, __contextNamespace: record.namespace });
|
|
1439
|
+
result2 = this.call(state, "setNode", { id: local, field: "children", value: this.moveInto(state, children), options });
|
|
758
1440
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
1441
|
+
return result2;
|
|
1442
|
+
}
|
|
1443
|
+
if (command === "contains") {
|
|
1444
|
+
const container = args.container ?? args.parent;
|
|
1445
|
+
const contained = args.contained ?? args.child;
|
|
1446
|
+
const parent = this.owner(container);
|
|
1447
|
+
const isSameDocument = contained >= parent.base && contained < parent.base + STRIDE2;
|
|
1448
|
+
return isSameDocument && this.call(parent, command, { container: container - parent.base, contained: contained - parent.base });
|
|
1449
|
+
}
|
|
1450
|
+
const ids = command === "select" ? args.contexts ?? [this.rootId()] : args.ids ?? [];
|
|
1451
|
+
const groups = this.groups(ids);
|
|
1452
|
+
if (this.isMixed(groups) && scratchCommands.has(command)) return this.scratch(command, { ...args, options }, ids) ?? null;
|
|
1453
|
+
if (command === "extractPlan") {
|
|
1454
|
+
const group = groups[0];
|
|
1455
|
+
return this.call(group?.state ?? this.state, command, { ...args, options, ids: group?.locals ?? [] }) ?? null;
|
|
1456
|
+
}
|
|
1457
|
+
if (idResultCommands.has(command)) {
|
|
1458
|
+
const isSelect = command === "select";
|
|
1459
|
+
if (!groups.length && (isSelect || command === "matches")) return this.call(this.state, command, { ...args, options, ids: [], ...isSelect ? { contexts: [] } : {} });
|
|
1460
|
+
const result2 = [];
|
|
1461
|
+
for (const group of groups) {
|
|
1462
|
+
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;
|
|
1463
|
+
const values = this.call(group.state, command, { ...args, options, ids: group.locals, ...isSelect ? { contexts: group.locals } : {}, ...pseudoMatches ? { pseudoMatches } : {} });
|
|
1464
|
+
result2.push(...this.globals(group.state, values));
|
|
783
1465
|
}
|
|
1466
|
+
return result2;
|
|
1467
|
+
}
|
|
1468
|
+
if (command === "render" && !hasValue) {
|
|
1469
|
+
const optionsJson = JSON.stringify(options);
|
|
1470
|
+
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("");
|
|
784
1471
|
}
|
|
1472
|
+
if ((command === "outerHtml" || command === "text") && !hasValue) return groups.map((group) => this.call(group.state, command, { ...args, options, ids: group.locals })).join("");
|
|
1473
|
+
if (command === "hasClass") return groups.some((group) => this.call(group.state, command, { ...args, options, ids: group.locals }));
|
|
1474
|
+
if (command === "serializeArray" || command === "serialize") return groups.length ? this.call(groups[0].state, command, { ...args, options, ids: groups[0].locals }) : command === "serializeArray" ? [] : "";
|
|
1475
|
+
if (command === "html") for (const group of groups) invalidate(group.state);
|
|
1476
|
+
const isWrite = hasValue || writeCommands.has(command);
|
|
1477
|
+
let result = null;
|
|
1478
|
+
for (const group of isWrite ? groups : groups.slice(0, 1)) result = this.call(group.state, command, { ...args, options, ids: group.locals });
|
|
785
1479
|
return result ?? null;
|
|
786
1480
|
}
|
|
787
1481
|
};
|
|
1482
|
+
function parsedChildren(html, options) {
|
|
1483
|
+
const parsed = parseNativeDocument(html, options, false);
|
|
1484
|
+
exposeState(parsed.state);
|
|
1485
|
+
return parsed.operate("node", { id: parsed.rootId() }).children;
|
|
1486
|
+
}
|
|
1487
|
+
function dataEntry(state, id) {
|
|
1488
|
+
const local = id - state.base;
|
|
1489
|
+
let entry = state.data.get(local);
|
|
1490
|
+
if (!entry) state.data.set(local, entry = { state, local });
|
|
1491
|
+
return entry;
|
|
1492
|
+
}
|
|
1493
|
+
function rehome(source, target, mapping, ids) {
|
|
1494
|
+
registry2.writes++;
|
|
1495
|
+
invalidate(source);
|
|
1496
|
+
invalidate(target);
|
|
1497
|
+
exposeState(target);
|
|
1498
|
+
const moved = /* @__PURE__ */ new Map();
|
|
1499
|
+
for (const [oldLocal, newLocal] of mapping) {
|
|
1500
|
+
moved.set(source.base + oldLocal, target.base + newLocal);
|
|
1501
|
+
const node = uncacheView(source, oldLocal);
|
|
1502
|
+
if (node) {
|
|
1503
|
+
node[VIEW_STATE] = target;
|
|
1504
|
+
node[VIEW_LOCAL] = newLocal;
|
|
1505
|
+
cacheView(target, newLocal, node);
|
|
1506
|
+
if (node[VIEW_CHILD_TARGET]) target.hasChildLists = true;
|
|
1507
|
+
}
|
|
1508
|
+
const entry = source.data.get(oldLocal);
|
|
1509
|
+
if (entry) {
|
|
1510
|
+
source.data.delete(oldLocal);
|
|
1511
|
+
entry.state = target;
|
|
1512
|
+
entry.local = newLocal;
|
|
1513
|
+
target.data.set(newLocal, entry);
|
|
1514
|
+
}
|
|
1515
|
+
const adapterNode = source.adapterNodes?.[oldLocal];
|
|
1516
|
+
if (adapterNode) {
|
|
1517
|
+
source.adapterNodes[oldLocal] = void 0;
|
|
1518
|
+
(target.adapterNodes ??= [])[newLocal] = adapterNode;
|
|
1519
|
+
adapterNode[VIEW_STATE] = target;
|
|
1520
|
+
adapterNode[VIEW_LOCAL] = newLocal;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
const rewrite = (list) => {
|
|
1524
|
+
let isTouched = false;
|
|
1525
|
+
for (let index = 0; index < list.length; index++) {
|
|
1526
|
+
const next = moved.get(list[index]);
|
|
1527
|
+
if (next !== void 0) {
|
|
1528
|
+
list[index] = next;
|
|
1529
|
+
isTouched = true;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
return isTouched;
|
|
1533
|
+
};
|
|
1534
|
+
for (const lease of [...source.leases]) {
|
|
1535
|
+
if (!rewrite(lease.ids)) continue;
|
|
1536
|
+
target.leases.add(lease);
|
|
1537
|
+
if (!lease.states.includes(target)) lease.states.push(target);
|
|
1538
|
+
if (!lease.ids.some((id) => id >= source.base && id < source.base + STRIDE2)) {
|
|
1539
|
+
source.leases.delete(lease);
|
|
1540
|
+
lease.states = lease.states.filter((state) => state !== source);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
rewrite(ids);
|
|
1544
|
+
}
|
|
1545
|
+
function refreshWrittenAttributes(state, command, args) {
|
|
1546
|
+
if (!hasViews(state)) return;
|
|
1547
|
+
let locals;
|
|
1548
|
+
if (targetedAttributeWrites.has(command)) locals = args.ids ?? [];
|
|
1549
|
+
else if (command === "setNode") {
|
|
1550
|
+
if (!attributeFields.has(args.field)) return;
|
|
1551
|
+
locals = [args.id];
|
|
1552
|
+
} else if (structuralWrites.has(command)) return;
|
|
1553
|
+
const refresh = (view) => {
|
|
1554
|
+
if (view && view[VIEW_ATTRIBUTES]) attributeRefresher?.(view);
|
|
1555
|
+
};
|
|
1556
|
+
if (locals) for (const local of locals) refresh(cachedView(state, local));
|
|
1557
|
+
else forEachView(state, refresh);
|
|
1558
|
+
}
|
|
1559
|
+
var attributeRefresher;
|
|
1560
|
+
var childRefresher;
|
|
1561
|
+
function onViewRefresh(attributes, children) {
|
|
1562
|
+
attributeRefresher = attributes;
|
|
1563
|
+
childRefresher = children;
|
|
1564
|
+
}
|
|
1565
|
+
function refreshChildLists(state) {
|
|
1566
|
+
if (!state.hasChildLists || !childRefresher) return;
|
|
1567
|
+
const touched = state.raw.takeTouched?.();
|
|
1568
|
+
if (touched === void 0) return;
|
|
1569
|
+
if (touched === null) {
|
|
1570
|
+
forEachView(state, childRefresher);
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
for (const local of touched) {
|
|
1574
|
+
const view = cachedView(state, local);
|
|
1575
|
+
if (view) childRefresher(view);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
788
1578
|
function routeDocument(document, options = {}) {
|
|
789
1579
|
return document.nodeSpace === registry2.space ? document : new RoutedDocument(document, options);
|
|
790
1580
|
}
|
|
1581
|
+
function routedFor(state) {
|
|
1582
|
+
return state.routed ??= new RoutedDocument(state.raw, state.options);
|
|
1583
|
+
}
|
|
791
1584
|
function sameNodeSpace(first, second) {
|
|
792
1585
|
return first === second || !!first.nodeSpace && first.nodeSpace === second.nodeSpace;
|
|
793
1586
|
}
|
|
1587
|
+
function isLocalState(state) {
|
|
1588
|
+
return state.space === registry2.space;
|
|
1589
|
+
}
|
|
1590
|
+
function isRouted(document) {
|
|
1591
|
+
return document.nodeSpace === registry2.space;
|
|
1592
|
+
}
|
|
794
1593
|
|
|
795
1594
|
// src/nodes.ts
|
|
796
|
-
var
|
|
797
|
-
var
|
|
798
|
-
var nodeState = nodeGlobals[nodeStateKey] ??= { views: /* @__PURE__ */ new WeakMap(), bindings: /* @__PURE__ */ new WeakMap(), caches: /* @__PURE__ */ new WeakMap(), finalizer: new FinalizationRegistry(({ cache, id }) => {
|
|
799
|
-
if (!cache.get(id)?.deref()) cache.delete(id);
|
|
800
|
-
}) };
|
|
801
|
-
var { bindings, caches } = nodeState;
|
|
802
|
-
var arrayIndex = /^(?:0|[1-9]\d*)$/;
|
|
1595
|
+
var VIEW_CHILDREN = /* @__PURE__ */ Symbol.for("rusteerio.node.children");
|
|
1596
|
+
var emptyRecord = Object.freeze({ id: -1, type: "released", children: [] });
|
|
803
1597
|
function operation(document, command, args = {}) {
|
|
804
1598
|
const direct = document.operate;
|
|
805
1599
|
if (direct) return direct.call(document, command, args);
|
|
806
1600
|
const value = document.op(command, JSON.stringify(args));
|
|
807
1601
|
return value === void 0 || value === "" ? void 0 : JSON.parse(value);
|
|
808
1602
|
}
|
|
1603
|
+
function viewId(node) {
|
|
1604
|
+
const view = node;
|
|
1605
|
+
const state = view?.[VIEW_STATE];
|
|
1606
|
+
return state !== void 0 && view[VIEW_SELF] === view && isLocalState(state) ? state.base + view[VIEW_LOCAL] : void 0;
|
|
1607
|
+
}
|
|
1608
|
+
function isNativeNode(node) {
|
|
1609
|
+
const view = node;
|
|
1610
|
+
return view?.[VIEW_STATE] !== void 0 && view[VIEW_SELF] === view;
|
|
1611
|
+
}
|
|
1612
|
+
function viewIdIn(document, node) {
|
|
1613
|
+
const id = viewId(node);
|
|
1614
|
+
if (id !== void 0) exposeTo(document, node[VIEW_STATE]);
|
|
1615
|
+
return id;
|
|
1616
|
+
}
|
|
809
1617
|
function nodeBinding(node) {
|
|
810
|
-
|
|
1618
|
+
const id = node && typeof node === "object" ? viewId(node) : void 0;
|
|
1619
|
+
return id === void 0 ? void 0 : { document: routedFor(node[VIEW_STATE]), id };
|
|
811
1620
|
}
|
|
812
1621
|
function nodeId(node, document) {
|
|
813
|
-
const
|
|
814
|
-
return
|
|
1622
|
+
const id = node && typeof node === "object" ? viewId(node) : void 0;
|
|
1623
|
+
return id !== void 0 && (!document || isRouted(document)) ? id : void 0;
|
|
815
1624
|
}
|
|
816
1625
|
function hydrateLocation(location) {
|
|
817
1626
|
if (!location || typeof location !== "object") return location;
|
|
@@ -824,26 +1633,201 @@ function hydrateLocation(location) {
|
|
|
824
1633
|
return location;
|
|
825
1634
|
}
|
|
826
1635
|
function nodeRecord(document, id) {
|
|
827
|
-
return operation(document, "node", { id });
|
|
1636
|
+
if (!isRouted(document)) return operation(document, "node", { id });
|
|
1637
|
+
const state = stateIn(document, id);
|
|
1638
|
+
return recordAt(state, id - state.base);
|
|
1639
|
+
}
|
|
1640
|
+
var isElementType = (type) => type === "tag" || type === "script" || type === "style";
|
|
1641
|
+
function traverseRecords(document, ids, kind) {
|
|
1642
|
+
if (!isRouted(document)) return void 0;
|
|
1643
|
+
const result = [];
|
|
1644
|
+
for (const id of ids) {
|
|
1645
|
+
const state = stateIn(document, id);
|
|
1646
|
+
const { base } = state;
|
|
1647
|
+
const node = recordAt(state, id - base);
|
|
1648
|
+
if (!node) continue;
|
|
1649
|
+
const isElement2 = (local) => isElementType(recordAt(state, local)?.type);
|
|
1650
|
+
if (kind === "children") {
|
|
1651
|
+
for (const child of node.children ?? []) if (isElement2(child)) result.push(base + child);
|
|
1652
|
+
} else if (kind === "contents") {
|
|
1653
|
+
for (const child of node.children ?? []) result.push(base + child);
|
|
1654
|
+
} else if (kind === "parent") {
|
|
1655
|
+
if (node.parent != null && isElement2(node.parent)) result.push(base + node.parent);
|
|
1656
|
+
} else if (kind === "parents" || kind === "ancestors") {
|
|
1657
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1658
|
+
for (let parent = node.parent; parent != null && !seen.has(parent); ) {
|
|
1659
|
+
seen.add(parent);
|
|
1660
|
+
const ancestor = recordAt(state, parent);
|
|
1661
|
+
if (!ancestor || ancestor.type === "root") break;
|
|
1662
|
+
if (isElementType(ancestor.type)) result.push(base + parent);
|
|
1663
|
+
parent = ancestor.parent;
|
|
1664
|
+
}
|
|
1665
|
+
} else if (kind === "next" || kind === "prev" || kind === "nextAll" || kind === "prevAll") {
|
|
1666
|
+
const isForward = kind === "next" || kind === "nextAll";
|
|
1667
|
+
const isSingle = kind === "next" || kind === "prev";
|
|
1668
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1669
|
+
for (let sibling = isForward ? node.next : node.prev; sibling != null && !seen.has(sibling); ) {
|
|
1670
|
+
seen.add(sibling);
|
|
1671
|
+
const record = recordAt(state, sibling);
|
|
1672
|
+
if (!record) break;
|
|
1673
|
+
if (isElementType(record.type)) {
|
|
1674
|
+
result.push(base + sibling);
|
|
1675
|
+
if (isSingle) break;
|
|
1676
|
+
}
|
|
1677
|
+
sibling = isForward ? record.next : record.prev;
|
|
1678
|
+
}
|
|
1679
|
+
} else if (kind === "siblings") {
|
|
1680
|
+
const parent = node.parent == null ? null : recordAt(state, node.parent);
|
|
1681
|
+
const local = id - base;
|
|
1682
|
+
for (const other of parent?.children ?? []) if (other !== local && isElement2(other)) result.push(base + other);
|
|
1683
|
+
} else return void 0;
|
|
1684
|
+
}
|
|
1685
|
+
return result;
|
|
828
1686
|
}
|
|
829
|
-
function
|
|
830
|
-
|
|
1687
|
+
function viewAt(state, local) {
|
|
1688
|
+
const existing = state.views[local] ?? cachedView(state, local);
|
|
1689
|
+
if (existing) return existing;
|
|
1690
|
+
const parsed = state.adapterNodes?.[local];
|
|
1691
|
+
if (parsed) {
|
|
1692
|
+
state.adapterNodes[local] = void 0;
|
|
1693
|
+
return adoptObject(state, local, parsed);
|
|
1694
|
+
}
|
|
1695
|
+
const snapshot = plainSnapshot(state, local);
|
|
1696
|
+
let constructor;
|
|
1697
|
+
if (snapshot) constructor = viewConstructor(snapshot.typeOf(local), false);
|
|
1698
|
+
else {
|
|
1699
|
+
const record = recordAt(state, local);
|
|
1700
|
+
if (!record) return void 0;
|
|
1701
|
+
constructor = viewConstructor(record.type, record.sourceCodeLocation !== void 0);
|
|
1702
|
+
}
|
|
1703
|
+
const view = new constructor(state, local);
|
|
1704
|
+
cacheView(state, local, view);
|
|
1705
|
+
return view;
|
|
1706
|
+
}
|
|
1707
|
+
function rootNode(document, id) {
|
|
1708
|
+
if (!isRouted(document)) throw new TypeError("Native nodes require a routed document");
|
|
1709
|
+
const state = stateIn(document, id);
|
|
1710
|
+
const local = id - state.base;
|
|
1711
|
+
const existing = cachedView(state, local);
|
|
1712
|
+
if (existing) return existing;
|
|
1713
|
+
if (state.adapterNodes?.[local] || state.options.sourceCodeLocationInfo) return viewAt(state, local);
|
|
1714
|
+
const view = new (viewConstructor("root", false))(state, local);
|
|
1715
|
+
cacheView(state, local, view);
|
|
1716
|
+
return view;
|
|
831
1717
|
}
|
|
832
|
-
function
|
|
833
|
-
|
|
1718
|
+
function getNode(document, id, original) {
|
|
1719
|
+
if (!isRouted(document)) throw new TypeError("Native nodes require a routed document");
|
|
1720
|
+
const state = stateIn(document, id);
|
|
1721
|
+
const local = id - state.base;
|
|
1722
|
+
if (original === void 0) return viewAt(state, local);
|
|
1723
|
+
return adoptObject(state, local, original);
|
|
1724
|
+
}
|
|
1725
|
+
function viewRecord(view) {
|
|
1726
|
+
const state = view[VIEW_STATE];
|
|
1727
|
+
const local = view[VIEW_LOCAL];
|
|
1728
|
+
return state.records[local] ?? recordAt(state, local) ?? emptyRecord;
|
|
1729
|
+
}
|
|
1730
|
+
function linkedView(view, local) {
|
|
1731
|
+
return local == null ? null : viewAt(view[VIEW_STATE], local) ?? null;
|
|
1732
|
+
}
|
|
1733
|
+
function setField(view, field, value) {
|
|
1734
|
+
const state = view[VIEW_STATE];
|
|
1735
|
+
operation(routedFor(state), "setNode", { id: state.base + view[VIEW_LOCAL], field, value });
|
|
1736
|
+
}
|
|
1737
|
+
function setPointer(view, field, value) {
|
|
1738
|
+
setField(view, field, value == null ? null : importNodes(routedFor(view[VIEW_STATE]), [value])[0]);
|
|
1739
|
+
}
|
|
1740
|
+
function attributesOf(view) {
|
|
1741
|
+
const state = view[VIEW_STATE];
|
|
1742
|
+
let attributes = view[VIEW_ATTRIBUTES];
|
|
1743
|
+
if (!attributes) view[VIEW_ATTRIBUTES] = attributes = createAttributes(view, state.options._useHtmlParser2 === false ? null : Object.prototype);
|
|
1744
|
+
if (attributes.generation !== state.generation || attributes.state !== state) syncAttributes(view, attributes);
|
|
1745
|
+
return attributes.proxy;
|
|
1746
|
+
}
|
|
1747
|
+
function createAttributes(view, prototype) {
|
|
834
1748
|
const target = Object.create(prototype);
|
|
1749
|
+
const handler = Object.create(attributeWrites);
|
|
1750
|
+
handler.view = view;
|
|
1751
|
+
handler.target = target;
|
|
1752
|
+
handler.generation = -1;
|
|
1753
|
+
handler.state = view[VIEW_STATE];
|
|
1754
|
+
handler.proxy = new Proxy(target, handler);
|
|
1755
|
+
return handler;
|
|
1756
|
+
}
|
|
1757
|
+
function syncAttributes(view, attributes) {
|
|
1758
|
+
const { target } = attributes;
|
|
1759
|
+
const state = view[VIEW_STATE];
|
|
1760
|
+
const local = view[VIEW_LOCAL];
|
|
1761
|
+
if (attributes.generation === -1) {
|
|
1762
|
+
const snapshot = plainSnapshot(state, local);
|
|
1763
|
+
if (snapshot) {
|
|
1764
|
+
snapshot.copyAttributes(local, target);
|
|
1765
|
+
attributes.generation = state.generation;
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
const values = viewRecord(view).attribs ?? {};
|
|
1770
|
+
const keys = Object.keys(target);
|
|
1771
|
+
const nextKeys = Object.keys(values);
|
|
1772
|
+
let isSameOrder = keys.length === nextKeys.length;
|
|
1773
|
+
for (let index = 0; isSameOrder && index < keys.length; index++) isSameOrder = keys[index] === nextKeys[index];
|
|
1774
|
+
if (!isSameOrder) for (const key of keys) delete target[key];
|
|
1775
|
+
for (const key of nextKeys) {
|
|
1776
|
+
if (isSameOrder && target[key] === values[key]) continue;
|
|
1777
|
+
if (key === "__proto__") Object.defineProperty(target, key, { value: values[key], writable: true, enumerable: true, configurable: true });
|
|
1778
|
+
else target[key] = values[key];
|
|
1779
|
+
}
|
|
1780
|
+
attributes.generation = view[VIEW_STATE].generation;
|
|
1781
|
+
attributes.state = view[VIEW_STATE];
|
|
1782
|
+
}
|
|
1783
|
+
function refreshAttributes(view) {
|
|
1784
|
+
const attributes = view[VIEW_ATTRIBUTES];
|
|
1785
|
+
if (attributes) syncAttributes(view, attributes);
|
|
1786
|
+
}
|
|
1787
|
+
onViewRefresh(refreshAttributes, fillChildren);
|
|
1788
|
+
var attributeWrites = {
|
|
1789
|
+
set(target, key, value) {
|
|
1790
|
+
if (typeof key === "symbol") return Reflect.set(target, key, value);
|
|
1791
|
+
const view = this.view;
|
|
1792
|
+
setField(view, "attribs", { ...viewRecord(view).attribs, [key]: String(value) });
|
|
1793
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1794
|
+
return true;
|
|
1795
|
+
},
|
|
1796
|
+
deleteProperty(target, key) {
|
|
1797
|
+
if (typeof key === "symbol") return Reflect.deleteProperty(target, key);
|
|
1798
|
+
const view = this.view;
|
|
1799
|
+
const values = { ...viewRecord(view).attribs };
|
|
1800
|
+
delete values[key];
|
|
1801
|
+
setField(view, "attribs", values);
|
|
1802
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1803
|
+
return true;
|
|
1804
|
+
},
|
|
1805
|
+
defineProperty(target, key, descriptor) {
|
|
1806
|
+
if (typeof key === "symbol") return Reflect.defineProperty(target, key, descriptor);
|
|
1807
|
+
const view = this.view;
|
|
1808
|
+
setField(view, "attribs", { ...viewRecord(view).attribs, [key]: String(descriptor.value) });
|
|
1809
|
+
syncAttributes(view, view[VIEW_ATTRIBUTES]);
|
|
1810
|
+
return true;
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
function attributeMap(view, field) {
|
|
1814
|
+
const read = () => viewRecord(view)[field] ?? {};
|
|
1815
|
+
const target = Object.create(view[VIEW_STATE].options._useHtmlParser2 === false ? null : Object.prototype);
|
|
1816
|
+
const viewField = `x-${field}`;
|
|
835
1817
|
return new Proxy(target, {
|
|
836
1818
|
get(_target, key) {
|
|
837
|
-
|
|
1819
|
+
if (typeof key === "symbol") return Reflect.get(target, key);
|
|
1820
|
+
const values = read();
|
|
1821
|
+
return Object.hasOwn(values, key) ? values[key] : Reflect.get(target, key);
|
|
838
1822
|
},
|
|
839
1823
|
set(_target, key, value) {
|
|
840
|
-
setField(
|
|
1824
|
+
setField(view, viewField, { ...read(), [key]: String(value) });
|
|
841
1825
|
return true;
|
|
842
1826
|
},
|
|
843
1827
|
deleteProperty(_target, key) {
|
|
844
1828
|
const values = { ...read() };
|
|
845
1829
|
delete values[key];
|
|
846
|
-
setField(
|
|
1830
|
+
setField(view, viewField, values);
|
|
847
1831
|
return true;
|
|
848
1832
|
},
|
|
849
1833
|
ownKeys() {
|
|
@@ -853,247 +1837,358 @@ function attributes(document, id, field = "attribs", prototype = document.option
|
|
|
853
1837
|
return Object.hasOwn(read(), key) || key in target;
|
|
854
1838
|
},
|
|
855
1839
|
getOwnPropertyDescriptor(_target, key) {
|
|
856
|
-
|
|
1840
|
+
const values = read();
|
|
1841
|
+
return Object.hasOwn(values, key) ? { value: values[key], writable: true, enumerable: true, configurable: true } : void 0;
|
|
857
1842
|
},
|
|
858
1843
|
defineProperty(_target, key, descriptor) {
|
|
859
|
-
|
|
860
|
-
setField(document, id, field, values);
|
|
1844
|
+
setField(view, viewField, { ...read(), [key]: String(descriptor.value) });
|
|
861
1845
|
return true;
|
|
862
1846
|
}
|
|
863
1847
|
});
|
|
864
1848
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const values = snapshot();
|
|
888
|
-
if (key === "length") values.length = value;
|
|
889
|
-
else if (typeof key === "string" && arrayIndex.test(key)) values[Number(key)] = value;
|
|
890
|
-
else return Reflect.set(target, key, value);
|
|
891
|
-
save(values);
|
|
892
|
-
return true;
|
|
893
|
-
},
|
|
894
|
-
deleteProperty(_target, key) {
|
|
895
|
-
if (typeof key === "string" && arrayIndex.test(key)) {
|
|
896
|
-
const values = snapshot();
|
|
897
|
-
values.splice(Number(key), 1);
|
|
898
|
-
save(values);
|
|
899
|
-
return true;
|
|
900
|
-
}
|
|
901
|
-
return Reflect.deleteProperty(target, key);
|
|
902
|
-
},
|
|
903
|
-
has(_target, key) {
|
|
904
|
-
return typeof key === "string" && arrayIndex.test(key) ? Number(key) < read().length : Reflect.has(target, key);
|
|
905
|
-
},
|
|
906
|
-
ownKeys() {
|
|
907
|
-
return [...read().map((_child, i) => String(i)), "length"];
|
|
908
|
-
},
|
|
909
|
-
getOwnPropertyDescriptor(_target, key) {
|
|
910
|
-
if (key === "length") return { ...Reflect.getOwnPropertyDescriptor(target, "length"), value: read().length };
|
|
911
|
-
if (typeof key === "string" && arrayIndex.test(key) && Number(key) < read().length) return { value: getNode(document, read()[Number(key)]), writable: true, enumerable: true, configurable: true };
|
|
912
|
-
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
1849
|
+
var ChildArray = class _ChildArray extends Array {
|
|
1850
|
+
#view;
|
|
1851
|
+
constructor(view) {
|
|
1852
|
+
super();
|
|
1853
|
+
this.#view = view;
|
|
1854
|
+
}
|
|
1855
|
+
static viewOf(list) {
|
|
1856
|
+
return list instanceof _ChildArray ? list.#view : void 0;
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
Object.defineProperty(ChildArray.prototype, "constructor", { configurable: true, writable: true, value: Array });
|
|
1860
|
+
for (const method of ["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "copyWithin", "fill"]) {
|
|
1861
|
+
Object.defineProperty(ChildArray.prototype, method, {
|
|
1862
|
+
configurable: true,
|
|
1863
|
+
writable: true,
|
|
1864
|
+
value(...args) {
|
|
1865
|
+
const view = ChildArray.viewOf(this);
|
|
1866
|
+
if (!view) return Reflect.apply(Array.prototype[method], this, args);
|
|
1867
|
+
const values = Array.from(this);
|
|
1868
|
+
const result = Reflect.apply(Array.prototype[method], values, args);
|
|
1869
|
+
saveChildren(view, values);
|
|
1870
|
+
return result === values ? this : result;
|
|
913
1871
|
}
|
|
914
1872
|
});
|
|
915
1873
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
var tagTypes = /* @__PURE__ */ new Set(["tag", "script", "style"]);
|
|
919
|
-
var parentTypes = /* @__PURE__ */ new Set(["root", "tag", "script", "style", "cdata"]);
|
|
920
|
-
var dataTypes = /* @__PURE__ */ new Set(["text", "comment", "directive"]);
|
|
921
|
-
function viewKeys(record) {
|
|
922
|
-
const keys = ["parent", "prev", "next", "startIndex", "endIndex"];
|
|
923
|
-
if (parentTypes.has(record.type)) keys.push("children");
|
|
924
|
-
if (record.data !== void 0) keys.push("data");
|
|
925
|
-
if (record.name !== void 0) keys.push("name");
|
|
926
|
-
if (tagTypes.has(record.type)) keys.push("attribs");
|
|
927
|
-
keys.push("type");
|
|
928
|
-
for (const field of sourceFields) if (!keys.includes(field) && field in record) keys.push(field);
|
|
929
|
-
if (tagTypes.has(record.type)) {
|
|
930
|
-
if ("attribsNamespace" in record) keys.push("x-attribsNamespace");
|
|
931
|
-
if ("attribsPrefix" in record) keys.push("x-attribsPrefix");
|
|
932
|
-
}
|
|
933
|
-
return keys;
|
|
934
|
-
}
|
|
935
|
-
function viewValue(state, key, receiver) {
|
|
936
|
-
const { document, id } = state;
|
|
937
|
-
const record = nodeRecord(document, id);
|
|
938
|
-
if (key === "cloneNode") return cloneNode;
|
|
939
|
-
if (key === "nodeType") return { root: 9, text: 3, comment: 8, cdata: 4 }[record.type] ?? 1;
|
|
940
|
-
if (key === "tagName" && tagTypes.has(record.type)) return record.name;
|
|
941
|
-
if (key === "nodeValue" && dataTypes.has(record.type)) return record.data;
|
|
942
|
-
const pointer = parentAliases[key] ?? key;
|
|
943
|
-
if (["parent", "prev", "next"].includes(pointer)) return record[pointer] == null ? null : getNode(document, record[pointer]);
|
|
944
|
-
if (["children", "childNodes", "firstChild", "lastChild"].includes(key) && parentTypes.has(record.type)) {
|
|
945
|
-
const list = state.children ??= children(document, id);
|
|
946
|
-
return key === "firstChild" ? list[0] ?? null : key === "lastChild" ? list[list.length - 1] ?? null : list;
|
|
947
|
-
}
|
|
948
|
-
if (key === "attribs" && tagTypes.has(record.type)) return state.attributes ??= attributes(document, id);
|
|
949
|
-
if ((key === "x-attribsNamespace" && "attribsNamespace" in record || key === "x-attribsPrefix" && "attribsPrefix" in record) && tagTypes.has(record.type)) {
|
|
950
|
-
state.maps ??= {};
|
|
951
|
-
return state.maps[key] ??= attributes(document, id, key === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
|
|
952
|
-
}
|
|
953
|
-
if (key === "attributes" && tagTypes.has(record.type)) {
|
|
954
|
-
const attrs = state.attributes ??= attributes(document, id);
|
|
955
|
-
return Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: record.attribsNamespace?.[name], prefix: record.attribsPrefix?.[name] }));
|
|
956
|
-
}
|
|
957
|
-
if (key === "sourceCodeLocation") return hydrateLocation(record[key]);
|
|
958
|
-
if (sourceFields.has(key)) return record[key] ?? (key === "startIndex" || key === "endIndex" ? null : void 0);
|
|
959
|
-
return void 0;
|
|
1874
|
+
function saveChildren(view, values) {
|
|
1875
|
+
setField(view, "children", importNodes(routedFor(view[VIEW_STATE]), values));
|
|
960
1876
|
}
|
|
961
|
-
function
|
|
962
|
-
const
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1877
|
+
function childList(view) {
|
|
1878
|
+
const existing = view[VIEW_CHILDREN];
|
|
1879
|
+
if (existing) return existing;
|
|
1880
|
+
const state = view[VIEW_STATE];
|
|
1881
|
+
if (!state.hasChildLists) {
|
|
1882
|
+
state.hasChildLists = true;
|
|
1883
|
+
state.raw.takeTouched?.();
|
|
1884
|
+
}
|
|
1885
|
+
const list = new ChildArray(view);
|
|
1886
|
+
view[VIEW_CHILD_TARGET] = list;
|
|
1887
|
+
view[VIEW_CHILDREN] = list;
|
|
1888
|
+
fillChildren(view);
|
|
1889
|
+
return list;
|
|
1890
|
+
}
|
|
1891
|
+
function fillChildren(view) {
|
|
1892
|
+
const target = view[VIEW_CHILD_TARGET];
|
|
1893
|
+
if (!target) return;
|
|
1894
|
+
const state = view[VIEW_STATE];
|
|
1895
|
+
const local = view[VIEW_LOCAL];
|
|
1896
|
+
const snapshot = plainSnapshot(state, local);
|
|
1897
|
+
if (snapshot && state.stale.size === 0) {
|
|
1898
|
+
fillFromSnapshot(state, snapshot, local, target);
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
const locals = viewRecord(view).children ?? [];
|
|
1902
|
+
target.length = locals.length;
|
|
1903
|
+
for (let index = 0; index < locals.length; index++) target[index] = viewAt(state, locals[index]);
|
|
1904
|
+
}
|
|
1905
|
+
function fillFromSnapshot(state, snapshot, local, target) {
|
|
1906
|
+
const count = snapshot.childCount(local);
|
|
1907
|
+
const first = snapshot.childStart(local);
|
|
1908
|
+
const childIds2 = snapshot.childIds;
|
|
1909
|
+
const views = state.views;
|
|
1910
|
+
const isStrong = !state.adapterNodes;
|
|
1911
|
+
const constructors = snapshotConstructors(snapshot);
|
|
1912
|
+
target.length = count;
|
|
1913
|
+
for (let index = 0; index < count; index++) {
|
|
1914
|
+
const child = childIds2[first + index];
|
|
1915
|
+
let node = views[child] ?? (state.weakViews.size ? cachedView(state, child) : void 0);
|
|
1916
|
+
if (node === void 0) {
|
|
1917
|
+
const constructor = isStrong && child < state.baseline && snapshot.isPlain(child) ? constructors(snapshot.typeReference(child)) : void 0;
|
|
1918
|
+
if (constructor) views[child] = node = new constructor(state, child);
|
|
1919
|
+
else node = viewAt(state, child);
|
|
1920
|
+
}
|
|
1921
|
+
target[index] = node;
|
|
975
1922
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1923
|
+
}
|
|
1924
|
+
function snapshotConstructors(snapshot) {
|
|
1925
|
+
let lookup = snapshot.viewConstructors;
|
|
1926
|
+
if (!lookup) {
|
|
1927
|
+
const byReference = [];
|
|
1928
|
+
lookup = (reference) => byReference[reference] ??= viewConstructor(snapshot.name(reference), false);
|
|
1929
|
+
snapshot.viewConstructors = lookup;
|
|
979
1930
|
}
|
|
980
|
-
return
|
|
1931
|
+
return lookup;
|
|
981
1932
|
}
|
|
982
|
-
var
|
|
983
|
-
get(
|
|
984
|
-
|
|
985
|
-
if (typeof key === "string") {
|
|
986
|
-
const state = nodeState.views.get(target);
|
|
987
|
-
if (key === "cloneNode" || key === "nodeType" || sourceFields.has(key) || ["tagName", "nodeValue", "parent", "prev", "next", "parentNode", "previousSibling", "nextSibling", "children", "childNodes", "firstChild", "lastChild", "attribs", "attributes", "x-attribsNamespace", "x-attribsPrefix"].includes(key)) return viewValue(state, key, receiver);
|
|
988
|
-
}
|
|
989
|
-
return Reflect.get(target, key, receiver);
|
|
990
|
-
},
|
|
991
|
-
set(target, key, value, receiver) {
|
|
992
|
-
if (Reflect.getOwnPropertyDescriptor(target, key)) return Reflect.set(target, key, value, receiver);
|
|
993
|
-
if (typeof key === "string" && writeView(nodeState.views.get(target), key, value)) return true;
|
|
994
|
-
return Reflect.set(target, key, value, receiver);
|
|
1933
|
+
var recordField = (field, fallback) => ({
|
|
1934
|
+
get() {
|
|
1935
|
+
return viewRecord(this)[field] ?? fallback;
|
|
995
1936
|
},
|
|
996
|
-
|
|
997
|
-
|
|
1937
|
+
set(value) {
|
|
1938
|
+
setField(this, field, value);
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
var snapshotField = (field) => ({
|
|
1942
|
+
get() {
|
|
1943
|
+
const state = this[VIEW_STATE];
|
|
1944
|
+
const local = this[VIEW_LOCAL];
|
|
1945
|
+
const snapshot = plainSnapshot(state, local);
|
|
1946
|
+
if (snapshot) return field === "type" ? snapshot.typeOf(local) : field === "name" ? snapshot.nameOf(local) : snapshot.dataOf(local);
|
|
1947
|
+
return viewRecord(this)[field];
|
|
998
1948
|
},
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1949
|
+
set(value) {
|
|
1950
|
+
setField(this, field, value);
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
1953
|
+
var linkOffsets = { parent: 1, prev: 2, next: 3 };
|
|
1954
|
+
var pointerField = (field) => ({
|
|
1955
|
+
get() {
|
|
1956
|
+
const state = this[VIEW_STATE];
|
|
1957
|
+
const local = this[VIEW_LOCAL];
|
|
1958
|
+
const snapshot = plainSnapshot(state, local);
|
|
1959
|
+
return linkedView(this, snapshot ? snapshot.linkOf(local, linkOffsets[field]) : viewRecord(this)[field]);
|
|
1002
1960
|
},
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
if (existing) return existing;
|
|
1006
|
-
const state = nodeState.views.get(target);
|
|
1007
|
-
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 };
|
|
1008
|
-
return void 0;
|
|
1961
|
+
set(value) {
|
|
1962
|
+
setPointer(this, field, value);
|
|
1009
1963
|
}
|
|
1964
|
+
});
|
|
1965
|
+
var nodeAccessors = {
|
|
1966
|
+
type: snapshotField("type"),
|
|
1967
|
+
parent: pointerField("parent"),
|
|
1968
|
+
prev: pointerField("prev"),
|
|
1969
|
+
next: pointerField("next"),
|
|
1970
|
+
startIndex: recordField("startIndex", null),
|
|
1971
|
+
endIndex: recordField("endIndex", null)
|
|
1010
1972
|
};
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1973
|
+
var locationAccessor = { get() {
|
|
1974
|
+
return hydrateLocation(viewRecord(this).sourceCodeLocation);
|
|
1975
|
+
}, set(value) {
|
|
1976
|
+
setField(this, "sourceCodeLocation", value);
|
|
1977
|
+
} };
|
|
1978
|
+
var childAccessors = {
|
|
1979
|
+
children: { get() {
|
|
1980
|
+
return childList(this);
|
|
1981
|
+
}, set(value) {
|
|
1982
|
+
setField(this, "children", importNodes(routedFor(this[VIEW_STATE]), value));
|
|
1983
|
+
} }
|
|
1984
|
+
};
|
|
1985
|
+
var elementAccessors = {
|
|
1986
|
+
name: snapshotField("name"),
|
|
1987
|
+
attribs: { get() {
|
|
1988
|
+
return attributesOf(this);
|
|
1989
|
+
}, set(value) {
|
|
1990
|
+
setField(this, "attribs", value);
|
|
1991
|
+
} },
|
|
1992
|
+
namespace: recordField("namespace"),
|
|
1993
|
+
prefix: recordField("prefix"),
|
|
1994
|
+
"x-attribsNamespace": { get() {
|
|
1995
|
+
return viewRecord(this).attribsNamespace !== void 0 ? attributeMap(this, "attribsNamespace") : void 0;
|
|
1996
|
+
}, set(value) {
|
|
1997
|
+
setField(this, "x-attribsNamespace", value);
|
|
1998
|
+
} },
|
|
1999
|
+
"x-attribsPrefix": { get() {
|
|
2000
|
+
return viewRecord(this).attribsPrefix !== void 0 ? attributeMap(this, "attribsPrefix") : void 0;
|
|
2001
|
+
}, set(value) {
|
|
2002
|
+
setField(this, "x-attribsPrefix", value);
|
|
2003
|
+
} }
|
|
2004
|
+
};
|
|
2005
|
+
var dataAccessors = { data: snapshotField("data") };
|
|
2006
|
+
var directiveAccessors = { name: recordField("name"), "x-name": recordField("x-name"), "x-publicId": recordField("x-publicId"), "x-systemId": recordField("x-systemId") };
|
|
2007
|
+
var documentAccessors = { "x-mode": recordField("x-mode") };
|
|
2008
|
+
function accessorsFor(type) {
|
|
2009
|
+
switch (type) {
|
|
2010
|
+
case "tag":
|
|
2011
|
+
case "script":
|
|
2012
|
+
case "style":
|
|
2013
|
+
return { ...nodeAccessors, ...childAccessors, ...elementAccessors };
|
|
2014
|
+
case "root":
|
|
2015
|
+
return { ...nodeAccessors, ...childAccessors, ...documentAccessors };
|
|
2016
|
+
case "cdata":
|
|
2017
|
+
return { ...nodeAccessors, ...childAccessors };
|
|
2018
|
+
case "directive":
|
|
2019
|
+
return { ...nodeAccessors, ...dataAccessors, ...directiveAccessors };
|
|
2020
|
+
case "text":
|
|
2021
|
+
case "comment":
|
|
2022
|
+
return { ...nodeAccessors, ...dataAccessors };
|
|
2023
|
+
default:
|
|
2024
|
+
return { ...nodeAccessors, ...childAccessors, ...dataAccessors, name: recordField("name") };
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
var viewConstructors = /* @__PURE__ */ new Map();
|
|
2028
|
+
var plainConstructors = /* @__PURE__ */ Object.create(null);
|
|
2029
|
+
function viewConstructor(type, hasLocation) {
|
|
2030
|
+
if (!hasLocation) {
|
|
2031
|
+
const plain = plainConstructors[type];
|
|
2032
|
+
if (plain) return plain;
|
|
2033
|
+
}
|
|
2034
|
+
const key = hasLocation ? `${type}:location` : type;
|
|
2035
|
+
let constructor = viewConstructors.get(key);
|
|
2036
|
+
if (constructor) return constructor;
|
|
2037
|
+
const prototype = Object.create(nodePrototype(type));
|
|
2038
|
+
const accessors = hasLocation ? { ...accessorsFor(type), sourceCodeLocation: locationAccessor } : accessorsFor(type);
|
|
2039
|
+
for (const [field, accessor] of Object.entries(accessors)) Object.defineProperty(prototype, field, { ...accessor, configurable: true, enumerable: false });
|
|
2040
|
+
constructor = function(state, local) {
|
|
2041
|
+
this[VIEW_STATE] = state;
|
|
2042
|
+
this[VIEW_LOCAL] = local;
|
|
2043
|
+
this[VIEW_SELF] = this;
|
|
2044
|
+
this[VIEW_ATTRIBUTES] = void 0;
|
|
2045
|
+
this[VIEW_CHILDREN] = void 0;
|
|
2046
|
+
this[VIEW_CHILD_TARGET] = void 0;
|
|
1037
2047
|
};
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
2048
|
+
Object.defineProperty(prototype, inspectSymbol, { configurable: true, writable: true, value: inspectNode });
|
|
2049
|
+
constructor.prototype = prototype;
|
|
2050
|
+
viewConstructors.set(key, constructor);
|
|
2051
|
+
if (!hasLocation) plainConstructors[type] = constructor;
|
|
2052
|
+
return constructor;
|
|
2053
|
+
}
|
|
2054
|
+
var inspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
2055
|
+
var inspectedFields = ["type", "name", "data", "attribs", "namespace", "startIndex", "endIndex"];
|
|
2056
|
+
function inspectNode(depth, options, inspect) {
|
|
2057
|
+
const fields = {};
|
|
2058
|
+
for (const field of inspectedFields) if (field in this && this[field] != null) fields[field] = field === "attribs" ? { ...this.attribs } : this[field];
|
|
2059
|
+
if ("children" in this) fields.children = `[${this.children.length} nodes]`;
|
|
2060
|
+
const name = Object.getPrototypeOf(Object.getPrototypeOf(this))?.constructor?.name ?? "Node";
|
|
2061
|
+
return depth < 0 ? `[${name}]` : `${name} ${inspect(fields, { ...options, depth: 1 })}`;
|
|
2062
|
+
}
|
|
2063
|
+
var adoptedAliases = {
|
|
2064
|
+
parentNode: { configurable: true, enumerable: false, get() {
|
|
2065
|
+
return this.parent;
|
|
2066
|
+
}, set(value) {
|
|
2067
|
+
this.parent = value;
|
|
2068
|
+
} },
|
|
2069
|
+
previousSibling: { configurable: true, enumerable: false, get() {
|
|
2070
|
+
return this.prev;
|
|
2071
|
+
}, set(value) {
|
|
2072
|
+
this.prev = value;
|
|
2073
|
+
} },
|
|
2074
|
+
nextSibling: { configurable: true, enumerable: false, get() {
|
|
2075
|
+
return this.next;
|
|
2076
|
+
}, set(value) {
|
|
2077
|
+
this.next = value;
|
|
2078
|
+
} },
|
|
2079
|
+
nodeType: { configurable: true, enumerable: false, get() {
|
|
2080
|
+
return { root: 9, text: 3, comment: 8, cdata: 4 }[viewRecord(this).type] ?? 1;
|
|
2081
|
+
} },
|
|
2082
|
+
cloneNode: { configurable: true, enumerable: false, writable: true, value: cloneNode }
|
|
2083
|
+
};
|
|
2084
|
+
var adoptedChildAliases = {
|
|
2085
|
+
childNodes: { configurable: true, enumerable: false, get() {
|
|
2086
|
+
return this.children;
|
|
2087
|
+
}, set(value) {
|
|
2088
|
+
this.children = value;
|
|
2089
|
+
} },
|
|
2090
|
+
firstChild: { configurable: true, enumerable: false, get() {
|
|
2091
|
+
return this.children[0] ?? null;
|
|
2092
|
+
} },
|
|
2093
|
+
lastChild: { configurable: true, enumerable: false, get() {
|
|
2094
|
+
return this.children[this.children.length - 1] ?? null;
|
|
2095
|
+
} }
|
|
2096
|
+
};
|
|
2097
|
+
var adoptedElementAliases = {
|
|
2098
|
+
tagName: { configurable: true, enumerable: false, get() {
|
|
2099
|
+
return this.name;
|
|
2100
|
+
}, set(value) {
|
|
2101
|
+
this.name = value;
|
|
2102
|
+
} },
|
|
2103
|
+
attributes: { configurable: true, enumerable: false, get() {
|
|
2104
|
+
const attributes = this.attribs;
|
|
2105
|
+
const record = viewRecord(this);
|
|
2106
|
+
return Object.keys(attributes).map((name) => ({ name, value: attributes[name], namespace: record.attribsNamespace?.[name], prefix: record.attribsPrefix?.[name] }));
|
|
2107
|
+
} }
|
|
2108
|
+
};
|
|
2109
|
+
var adoptedDataAliases = {
|
|
2110
|
+
nodeValue: { configurable: true, enumerable: false, get() {
|
|
2111
|
+
return this.data;
|
|
2112
|
+
}, set(value) {
|
|
2113
|
+
this.data = value;
|
|
2114
|
+
} }
|
|
2115
|
+
};
|
|
2116
|
+
var adoptedFields = /* @__PURE__ */ new Map();
|
|
2117
|
+
var optionalAdoptedKeys = ["name", "data", "namespace", "prefix", "sourceCodeLocation", "x-name", "x-publicId", "x-systemId", "x-mode", "x-attribsNamespace", "x-attribsPrefix"];
|
|
2118
|
+
var optionalAdoptedFields = new Set(optionalAdoptedKeys);
|
|
2119
|
+
var adoptedShapes = /* @__PURE__ */ new Map();
|
|
2120
|
+
function adoptObject(state, local, original) {
|
|
2121
|
+
const record = recordAt(state, local);
|
|
2122
|
+
if (!record) return void 0;
|
|
2123
|
+
const view = original;
|
|
2124
|
+
const attributesPrototype = original.attribs && typeof original.attribs === "object" ? Object.getPrototypeOf(original.attribs) : void 0;
|
|
2125
|
+
view[VIEW_STATE] = state;
|
|
2126
|
+
view[VIEW_LOCAL] = local;
|
|
2127
|
+
view[VIEW_SELF] = view;
|
|
2128
|
+
view[VIEW_ATTRIBUTES] = void 0;
|
|
2129
|
+
view[VIEW_CHILDREN] = void 0;
|
|
2130
|
+
view[VIEW_CHILD_TARGET] = void 0;
|
|
2131
|
+
let fields = adoptedFields.get(record.type);
|
|
2132
|
+
if (!fields) {
|
|
2133
|
+
fields = {};
|
|
2134
|
+
for (const [key, accessor] of Object.entries({ ...accessorsFor(record.type), sourceCodeLocation: locationAccessor })) fields[key] = { ...accessor, configurable: true, enumerable: true };
|
|
2135
|
+
adoptedFields.set(record.type, fields);
|
|
2136
|
+
}
|
|
2137
|
+
let shape = record.type;
|
|
2138
|
+
for (const key of optionalAdoptedKeys) {
|
|
2139
|
+
if (!(key in fields)) continue;
|
|
2140
|
+
const field = key === "x-attribsNamespace" ? "attribsNamespace" : key === "x-attribsPrefix" ? "attribsPrefix" : key;
|
|
2141
|
+
shape += record[field] !== void 0 || Object.hasOwn(original, key) ? "1" : "0";
|
|
2142
|
+
}
|
|
2143
|
+
let descriptors = adoptedShapes.get(shape);
|
|
2144
|
+
if (!descriptors) {
|
|
2145
|
+
const present = {};
|
|
2146
|
+
for (const key in fields) {
|
|
2147
|
+
const field = key === "x-attribsNamespace" ? "attribsNamespace" : key === "x-attribsPrefix" ? "attribsPrefix" : key;
|
|
2148
|
+
if (optionalAdoptedFields.has(key) && record[field] === void 0 && !Object.hasOwn(original, key)) continue;
|
|
2149
|
+
present[key] = fields[key];
|
|
1042
2150
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
define("tagName", () => node.name, (value) => {
|
|
1067
|
-
node.name = value;
|
|
1068
|
-
}, false);
|
|
1069
|
-
for (const field of ["x-attribsNamespace", "x-attribsPrefix"]) {
|
|
1070
|
-
if (!((field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix") in record) && !Object.hasOwn(original, field)) continue;
|
|
1071
|
-
const values = attributes(document, id, field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
|
|
1072
|
-
define(field, () => values, (value) => setField(document, id, field, value));
|
|
1073
|
-
}
|
|
1074
|
-
define("attributes", () => Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: read().attribsNamespace?.[name], prefix: read().attribsPrefix?.[name] })), void 0, false);
|
|
1075
|
-
}
|
|
1076
|
-
if (["text", "comment", "directive"].includes(record.type)) define("nodeValue", () => node.data, (value) => {
|
|
1077
|
-
node.data = value;
|
|
1078
|
-
}, false);
|
|
1079
|
-
define("nodeType", () => ({ root: 9, text: 3, comment: 8, cdata: 4 })[read().type] ?? 1, void 0, false);
|
|
1080
|
-
Object.defineProperty(node, "cloneNode", { configurable: true, enumerable: false, writable: true, value: cloneNode });
|
|
1081
|
-
return node;
|
|
2151
|
+
const isParent = "children" in present;
|
|
2152
|
+
const isData = record.type === "text" || record.type === "comment" || record.type === "directive";
|
|
2153
|
+
descriptors = { ...present, ...adoptedAliases, ...isParent ? adoptedChildAliases : {}, ...isElementType(record.type) ? adoptedElementAliases : {}, ...isData ? adoptedDataAliases : {} };
|
|
2154
|
+
adoptedShapes.set(shape, descriptors);
|
|
2155
|
+
}
|
|
2156
|
+
const isElement2 = isElementType(record.type);
|
|
2157
|
+
try {
|
|
2158
|
+
Object.defineProperties(view, descriptors);
|
|
2159
|
+
} catch {
|
|
2160
|
+
}
|
|
2161
|
+
if (isElement2 && attributesPrototype !== void 0) view[VIEW_ATTRIBUTES] = createAttributes(view, attributesPrototype);
|
|
2162
|
+
cacheView(state, local, view);
|
|
2163
|
+
return view;
|
|
2164
|
+
}
|
|
2165
|
+
function attachParsedNodes(state, nodes) {
|
|
2166
|
+
state.adapterNodes = nodes;
|
|
2167
|
+
for (let local = 0; local < nodes.length; local++) {
|
|
2168
|
+
const node = nodes[local];
|
|
2169
|
+
if (!node) continue;
|
|
2170
|
+
node[VIEW_STATE] = state;
|
|
2171
|
+
node[VIEW_LOCAL] = local;
|
|
2172
|
+
node[VIEW_SELF] = node;
|
|
2173
|
+
}
|
|
1082
2174
|
}
|
|
1083
2175
|
function cloneNode(recursive = false) {
|
|
1084
2176
|
const binding = nodeBinding(this);
|
|
1085
2177
|
if (!binding) throw new TypeError("cloneNode requires a native DOM node receiver");
|
|
1086
2178
|
return getNode(binding.document, operation(binding.document, "clone", { ids: [binding.id], deep: recursive })[0]);
|
|
1087
2179
|
}
|
|
2180
|
+
function childIds(document, id) {
|
|
2181
|
+
const state = stateIn(document, id);
|
|
2182
|
+
return (recordAt(state, id - state.base)?.children ?? []).map((child) => state.base + child);
|
|
2183
|
+
}
|
|
1088
2184
|
function importNodes(document, input) {
|
|
1089
2185
|
if (input == null || input === false) return [];
|
|
1090
2186
|
const values = Array.isArray(input) || typeof input === "object" && "length" in input && !("type" in input) ? Array.from(input) : [input];
|
|
1091
2187
|
const result = [];
|
|
1092
2188
|
for (const node of values) {
|
|
1093
2189
|
if (node == null) continue;
|
|
1094
|
-
const existing =
|
|
2190
|
+
const existing = node && typeof node === "object" ? viewIdIn(document, node) : void 0;
|
|
1095
2191
|
if (existing !== void 0) {
|
|
1096
|
-
document.retainNode?.(existing);
|
|
1097
2192
|
result.push(existing);
|
|
1098
2193
|
continue;
|
|
1099
2194
|
}
|
|
@@ -1118,8 +2213,8 @@ function importNodes(document, input) {
|
|
|
1118
2213
|
const adopt = (oldId, newId) => {
|
|
1119
2214
|
const source = originals.get(oldId);
|
|
1120
2215
|
const oldChildren = records[oldId].children;
|
|
1121
|
-
const newChildren =
|
|
1122
|
-
getNode(document, newId,
|
|
2216
|
+
const newChildren = childIds(document, newId);
|
|
2217
|
+
getNode(document, newId, isNativeNode(source) ? void 0 : source);
|
|
1123
2218
|
for (let i = 0; i < oldChildren.length; i++) if (newChildren[i] !== void 0) adopt(oldChildren[i], newChildren[i]);
|
|
1124
2219
|
};
|
|
1125
2220
|
adopt(root, imported[0]);
|
|
@@ -1130,10 +2225,10 @@ function importNodes(document, input) {
|
|
|
1130
2225
|
|
|
1131
2226
|
// src/dom.ts
|
|
1132
2227
|
var ElementType = Object.freeze({ Root: "root", Text: "text", Directive: "directive", Comment: "comment", Script: "script", Style: "style", Tag: "tag", CDATA: "cdata", Doctype: "doctype" });
|
|
1133
|
-
function initialize(node, type, fields,
|
|
2228
|
+
function initialize(node, type, fields, children = []) {
|
|
1134
2229
|
const document = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
1135
2230
|
const id = operation(document, "createNode", { type, ...fields });
|
|
1136
|
-
if (
|
|
2231
|
+
if (children.length) operation(document, "setNode", { id, field: "children", value: importNodes(document, children) });
|
|
1137
2232
|
return getNode(document, id, node);
|
|
1138
2233
|
}
|
|
1139
2234
|
var Node = class {
|
|
@@ -1188,21 +2283,21 @@ var ProcessingInstruction = class extends DataNode {
|
|
|
1188
2283
|
}
|
|
1189
2284
|
};
|
|
1190
2285
|
var Document = class extends NodeWithChildren {
|
|
1191
|
-
constructor(
|
|
2286
|
+
constructor(children) {
|
|
1192
2287
|
super();
|
|
1193
|
-
return initialize(this, "root", {},
|
|
2288
|
+
return initialize(this, "root", {}, children);
|
|
1194
2289
|
}
|
|
1195
2290
|
};
|
|
1196
2291
|
var CDATA = class extends NodeWithChildren {
|
|
1197
|
-
constructor(
|
|
2292
|
+
constructor(children) {
|
|
1198
2293
|
super();
|
|
1199
|
-
return initialize(this, "cdata", {},
|
|
2294
|
+
return initialize(this, "cdata", {}, children);
|
|
1200
2295
|
}
|
|
1201
2296
|
};
|
|
1202
2297
|
var Element = class extends NodeWithChildren {
|
|
1203
|
-
constructor(name, attribs,
|
|
2298
|
+
constructor(name, attribs, children = [], type) {
|
|
1204
2299
|
super();
|
|
1205
|
-
return initialize(this, type ?? (name === "script" || name === "style" ? name : "tag"), { name, attribs },
|
|
2300
|
+
return initialize(this, type ?? (name === "script" || name === "style" ? name : "tag"), { name, attribs }, children);
|
|
1206
2301
|
}
|
|
1207
2302
|
};
|
|
1208
2303
|
function nodePrototype(type) {
|
|
@@ -1309,7 +2404,7 @@ function dataValue(object, key) {
|
|
|
1309
2404
|
function compileExtractPlan(map, options) {
|
|
1310
2405
|
if (options.pseudos || options.treeAdapter || options.Tokenizer || options.xml && typeof options.xml === "object" && options.xml.Tokenizer) return void 0;
|
|
1311
2406
|
const ancestors = /* @__PURE__ */ new Set();
|
|
1312
|
-
const
|
|
2407
|
+
const compile2 = (input) => {
|
|
1313
2408
|
if (!input || typeof input !== "object" || import_node_util.types.isProxy(input) || ancestors.has(input) || ancestors.size >= 64) return void 0;
|
|
1314
2409
|
for (let current = Object.getPrototypeOf(input); current; current = Object.getPrototypeOf(current)) {
|
|
1315
2410
|
if (import_node_util.types.isProxy(current)) return void 0;
|
|
@@ -1346,7 +2441,7 @@ function compileExtractPlan(map, options) {
|
|
|
1346
2441
|
if (!scalarProperties.has(value) && !/^(?:data-|aria-).+/.test(value)) return void 0;
|
|
1347
2442
|
entries2.push({ key, selector, all, value: { kind: "property", name: value } });
|
|
1348
2443
|
} else {
|
|
1349
|
-
const nested =
|
|
2444
|
+
const nested = compile2(value);
|
|
1350
2445
|
if (!nested) return void 0;
|
|
1351
2446
|
entries2.push({ key, selector, all, value: { kind: "map", entries: nested } });
|
|
1352
2447
|
}
|
|
@@ -1356,7 +2451,7 @@ function compileExtractPlan(map, options) {
|
|
|
1356
2451
|
ancestors.delete(input);
|
|
1357
2452
|
}
|
|
1358
2453
|
};
|
|
1359
|
-
const entries =
|
|
2454
|
+
const entries = compile2(map);
|
|
1360
2455
|
return entries && { version: 1, entries };
|
|
1361
2456
|
}
|
|
1362
2457
|
function hydrateExtractResult(result, entries) {
|
|
@@ -1374,13 +2469,37 @@ function hydrateExtractResult(result, entries) {
|
|
|
1374
2469
|
}
|
|
1375
2470
|
|
|
1376
2471
|
// src/attributes.ts
|
|
1377
|
-
var
|
|
1378
|
-
var
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
2472
|
+
var elementTypes = /* @__PURE__ */ new Set(["tag", "script", "style"]);
|
|
2473
|
+
var booleanAttribute = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i;
|
|
2474
|
+
var absent = /* @__PURE__ */ Symbol("absent");
|
|
2475
|
+
var deferred = /* @__PURE__ */ Symbol("deferred");
|
|
2476
|
+
function readAttribute(selection, name) {
|
|
2477
|
+
const node = selection[0];
|
|
2478
|
+
if (typeof node !== "object" || node === null) return absent;
|
|
2479
|
+
const state = node[VIEW_STATE];
|
|
2480
|
+
if (state === void 0 || node[VIEW_SELF] !== node) return typeof node.type === "string" ? deferred : absent;
|
|
2481
|
+
const local = node[VIEW_LOCAL];
|
|
2482
|
+
const snapshot = plainSnapshot(state, local);
|
|
2483
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
2484
|
+
const type = snapshot ? snapshot.typeOf(local) : record?.type;
|
|
2485
|
+
if (type === void 0 || !elementTypes.has(type)) return absent;
|
|
2486
|
+
const value = attributeAt(state, local, name);
|
|
2487
|
+
if (value === void 0) {
|
|
2488
|
+
const attributes = record?.attribs;
|
|
2489
|
+
if (attributes && Object.hasOwn(attributes, name)) return deferred;
|
|
2490
|
+
return name === "value" ? deferred : absent;
|
|
2491
|
+
}
|
|
2492
|
+
const options = selection.options ?? {};
|
|
2493
|
+
const isXml = options.xmlMode ?? (options.xml === true || typeof options.xml === "object" && options.xml !== null);
|
|
2494
|
+
return !isXml && booleanAttribute.test(name) ? name : value;
|
|
2495
|
+
}
|
|
2496
|
+
function setAttribute(selection, ids, name, value) {
|
|
2497
|
+
const document = selection[DOCUMENT];
|
|
2498
|
+
if (document.setAttribute) document.setAttribute(ids, name, value);
|
|
2499
|
+
else selection.op("attr", { ids, name, value });
|
|
2500
|
+
}
|
|
1382
2501
|
function isElement(selection, id) {
|
|
1383
|
-
return ["tag", "script", "style"].includes(nodeRecord(selection
|
|
2502
|
+
return ["tag", "script", "style"].includes(nodeRecord(selection[DOCUMENT], id)?.type);
|
|
1384
2503
|
}
|
|
1385
2504
|
function nativeValue(value) {
|
|
1386
2505
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
@@ -1403,18 +2522,10 @@ function hydrateValue(value) {
|
|
|
1403
2522
|
return value;
|
|
1404
2523
|
}
|
|
1405
2524
|
function dataObject(selection, id) {
|
|
1406
|
-
const document = selection
|
|
1407
|
-
|
|
1408
|
-
let documents = dataObjects.get(cacheKey);
|
|
1409
|
-
if (!documents) dataObjects.set(cacheKey, documents = /* @__PURE__ */ new Map());
|
|
1410
|
-
const existingReference = documents.get(id);
|
|
1411
|
-
let data2 = existingReference?.deref() ?? document.nodeData?.(id);
|
|
2525
|
+
const document = selection[DOCUMENT];
|
|
2526
|
+
let data2 = document.nodeData?.(id);
|
|
1412
2527
|
if (!data2) {
|
|
1413
|
-
const
|
|
1414
|
-
const dispatch = document.nodeDataOperation?.(id) ?? ((command, args) => {
|
|
1415
|
-
const document2 = documentReference.deref();
|
|
1416
|
-
return document2 ? JSON.parse(document2.op(command, JSON.stringify(args))) : void 0;
|
|
1417
|
-
});
|
|
2528
|
+
const dispatch = document.nodeDataOperation?.(id) ?? ((command, args) => JSON.parse(document.op(command, JSON.stringify(args))));
|
|
1418
2529
|
const target = {};
|
|
1419
2530
|
data2 = new Proxy(target, {
|
|
1420
2531
|
set(object, name, value) {
|
|
@@ -1433,28 +2544,26 @@ function dataObject(selection, id) {
|
|
|
1433
2544
|
return true;
|
|
1434
2545
|
}
|
|
1435
2546
|
});
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
2547
|
+
document.retainNodeData?.(id, data2);
|
|
2548
|
+
}
|
|
2549
|
+
const node = getNode(selection[DOCUMENT], id);
|
|
2550
|
+
if (!Object.hasOwn(node, "data")) {
|
|
2551
|
+
const values = data2;
|
|
2552
|
+
Object.defineProperty(node, "data", { configurable: true, enumerable: true, get: () => values, set: (value) => {
|
|
2553
|
+
for (const key of Object.keys(values)) delete values[key];
|
|
2554
|
+
for (const key of Object.keys(value ?? {})) values[key] = value[key];
|
|
1440
2555
|
} });
|
|
1441
2556
|
}
|
|
1442
|
-
if (existingReference?.deref() !== data2) {
|
|
1443
|
-
const reference = new WeakRef(data2);
|
|
1444
|
-
documents.set(id, reference);
|
|
1445
|
-
dataFinalizer.register(data2, { cache: new WeakRef(documents), id, reference });
|
|
1446
|
-
}
|
|
1447
|
-
document.retainNodeData?.(id, data2);
|
|
1448
2557
|
return data2;
|
|
1449
2558
|
}
|
|
1450
2559
|
function property(selection, id, name, raw = false) {
|
|
1451
2560
|
const result = selection.op("prop", { ids: [id], name, ...raw ? { raw: true } : {} });
|
|
1452
2561
|
if (name === "sourceCodeLocation") return hydrateLocation(result);
|
|
1453
|
-
return result?.__nativeNodeProperty ? getNode(selection
|
|
2562
|
+
return result?.__nativeNodeProperty ? getNode(selection[DOCUMENT], id)[result.__nativeNodeProperty] : result === null ? void 0 : result;
|
|
1454
2563
|
}
|
|
1455
2564
|
function propertyValue(selection, name, value) {
|
|
1456
|
-
if (name === "children" || name === "childNodes") return importNodes(selection
|
|
1457
|
-
if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(name)) return value == null ? null : importNodes(selection
|
|
2565
|
+
if (name === "children" || name === "childNodes") return importNodes(selection[DOCUMENT], value);
|
|
2566
|
+
if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(name)) return value == null ? null : importNodes(selection[DOCUMENT], [value])[0] ?? null;
|
|
1458
2567
|
return value;
|
|
1459
2568
|
}
|
|
1460
2569
|
function attr(name, value) {
|
|
@@ -1463,22 +2572,27 @@ function attr(name, value) {
|
|
|
1463
2572
|
if (typeof name !== "string") throw new Error("Bad combination of arguments.");
|
|
1464
2573
|
this.ids.forEach((id, index) => {
|
|
1465
2574
|
if (!isElement(this, id)) return;
|
|
1466
|
-
const node = getNode(this
|
|
2575
|
+
const node = getNode(this[DOCUMENT], id);
|
|
1467
2576
|
const current = node.attribs[name];
|
|
1468
2577
|
const next = value.call(node, index, current);
|
|
1469
|
-
this
|
|
2578
|
+
setAttribute(this, [id], name, next === null ? null : String(next));
|
|
1470
2579
|
});
|
|
1471
2580
|
} else if (typeof name === "object") {
|
|
1472
|
-
for (const key of Object.keys(name)) this
|
|
2581
|
+
for (const key of Object.keys(name)) setAttribute(this, this.ids, key, name[key] === null ? null : String(name[key]));
|
|
1473
2582
|
} else {
|
|
1474
|
-
this
|
|
2583
|
+
setAttribute(this, this.ids, name, value === null ? null : String(value));
|
|
1475
2584
|
}
|
|
1476
2585
|
return this;
|
|
1477
2586
|
}
|
|
1478
2587
|
if (arguments.length > 1) return this;
|
|
2588
|
+
if (typeof name === "string") {
|
|
2589
|
+
const cached2 = readAttribute(this, name);
|
|
2590
|
+
if (cached2 === absent) return void 0;
|
|
2591
|
+
if (cached2 !== deferred) return cached2;
|
|
2592
|
+
}
|
|
1479
2593
|
const result = this.op("attr", { ids: this.ids, ...typeof name === "string" ? { name } : {} });
|
|
1480
2594
|
if (result === null) return void 0;
|
|
1481
|
-
return !name && this.ids.length ? getNode(this
|
|
2595
|
+
return !name && this.ids.length ? getNode(this[DOCUMENT], this.ids[0]).attribs : result;
|
|
1482
2596
|
}
|
|
1483
2597
|
function prop(name, value) {
|
|
1484
2598
|
if (typeof name === "string" && value === void 0) return this.ids.length ? property(this, this.ids[0], name) : void 0;
|
|
@@ -1487,7 +2601,7 @@ function prop(name, value) {
|
|
|
1487
2601
|
if (typeof name === "object") throw new TypeError("Bad combination of arguments.");
|
|
1488
2602
|
this.ids.forEach((id, index) => {
|
|
1489
2603
|
if (!isElement(this, id)) return;
|
|
1490
|
-
const next = value.call(getNode(this
|
|
2604
|
+
const next = value.call(getNode(this[DOCUMENT], id), index, property(this, id, name, true));
|
|
1491
2605
|
this.op("prop", { ids: [id], name, value: propertyValue(this, name, next) });
|
|
1492
2606
|
});
|
|
1493
2607
|
} else if (typeof name === "object") {
|
|
@@ -1530,7 +2644,7 @@ function css(name, value) {
|
|
|
1530
2644
|
for (const id of this.ids) {
|
|
1531
2645
|
if (!isElement(this, id)) continue;
|
|
1532
2646
|
const current = this.op("css", { ids: [id], name: key }) ?? void 0;
|
|
1533
|
-
const next = name[key].call(getNode(this
|
|
2647
|
+
const next = name[key].call(getNode(this[DOCUMENT], id), propertyIndex, current);
|
|
1534
2648
|
this.op("css", { ids: [id], name: key, value: next == null ? null : String(next) });
|
|
1535
2649
|
}
|
|
1536
2650
|
} else this.op("css", { ids: this.ids, name: key, value: name[key] == null ? null : String(name[key]) });
|
|
@@ -1539,7 +2653,7 @@ function css(name, value) {
|
|
|
1539
2653
|
this.ids.forEach((id, index) => {
|
|
1540
2654
|
if (!isElement(this, id)) return;
|
|
1541
2655
|
const current = this.op("css", { ids: [id], name }) ?? void 0;
|
|
1542
|
-
const next = value.call(getNode(this
|
|
2656
|
+
const next = value.call(getNode(this[DOCUMENT], id), index, current);
|
|
1543
2657
|
this.op("css", { ids: [id], name, value: next == null ? null : String(next) });
|
|
1544
2658
|
});
|
|
1545
2659
|
} else if (typeof name === "string") this.op("css", { ids: this.ids, name, value: value == null ? null : String(value) });
|
|
@@ -1552,7 +2666,7 @@ function classMethod(command) {
|
|
|
1552
2666
|
if (typeof name === "function") {
|
|
1553
2667
|
this.ids.forEach((id, index) => {
|
|
1554
2668
|
if (!isElement(this, id)) return;
|
|
1555
|
-
const node = getNode(this
|
|
2669
|
+
const node = getNode(this[DOCUMENT], id);
|
|
1556
2670
|
const next = command === "toggleClass" ? name.call(node, index, node.attribs.class ?? "", state) : name.call(node, index, node.attribs.class ?? "");
|
|
1557
2671
|
if (typeof next === "string") this.op(command, { ids: [id], name: next, ...typeof state === "boolean" ? { state } : {} });
|
|
1558
2672
|
});
|
|
@@ -1569,7 +2683,8 @@ function installAttributes(CheerioClass) {
|
|
|
1569
2683
|
data,
|
|
1570
2684
|
css,
|
|
1571
2685
|
removeAttr(name) {
|
|
1572
|
-
|
|
2686
|
+
const ids = this.ids;
|
|
2687
|
+
for (const single of String(name).split(/\s+/)) if (single) setAttribute(this, ids, single, null);
|
|
1573
2688
|
return this;
|
|
1574
2689
|
},
|
|
1575
2690
|
hasClass(name) {
|
|
@@ -1597,9 +2712,9 @@ function parseWithNative(content, options, isDocument2, context) {
|
|
|
1597
2712
|
if (!isDocument2 && context) {
|
|
1598
2713
|
const document2 = nodeBinding(context)?.document ?? routeDocument(new (requireNative()).NativeDocument("", false, JSON.stringify(cleanParserOptions(options))), options);
|
|
1599
2714
|
const contextId = importNodes(document2, [context])[0];
|
|
1600
|
-
const
|
|
2715
|
+
const children = operation(document2, "create", { html: content, contextId, options });
|
|
1601
2716
|
const root = operation(document2, "createNode", { type: "root", options });
|
|
1602
|
-
operation(document2, "setNode", { id: root, field: "children", value:
|
|
2717
|
+
operation(document2, "setNode", { id: root, field: "children", value: children, options });
|
|
1603
2718
|
return getNode(document2, root);
|
|
1604
2719
|
}
|
|
1605
2720
|
const document = parseNativeDocument(content, options, isDocument2);
|
|
@@ -1612,7 +2727,7 @@ function parseWithHtmlparser2(content, options) {
|
|
|
1612
2727
|
return parseWithNative(content, { ...options, _useHtmlParser2: true }, false, null);
|
|
1613
2728
|
}
|
|
1614
2729
|
function getParse(parser) {
|
|
1615
|
-
return function
|
|
2730
|
+
return function parse3(content, options, isDocument2, context) {
|
|
1616
2731
|
if (Buffer.isBuffer(content)) content = content.toString();
|
|
1617
2732
|
if (typeof content === "string") return parser(content, options, isDocument2, context);
|
|
1618
2733
|
if (!Array.isArray(content) && content.type === "root" && nodeBinding(content)) return content;
|
|
@@ -1625,6 +2740,183 @@ function getParse(parser) {
|
|
|
1625
2740
|
}
|
|
1626
2741
|
var parse = getParse((content, options, isDocument2, context) => options._useHtmlParser2 ? parseWithHtmlparser2(content, options) : parseWithParse5(content, options, isDocument2, context));
|
|
1627
2742
|
|
|
2743
|
+
// src/match.ts
|
|
2744
|
+
var compiled = /* @__PURE__ */ new Map();
|
|
2745
|
+
var compiledLimit = 512;
|
|
2746
|
+
function matchSimpleSelector(document, ids, selector, options) {
|
|
2747
|
+
if (!isRouted(document)) return void 0;
|
|
2748
|
+
const compounds = compile(selector);
|
|
2749
|
+
if (!compounds) return void 0;
|
|
2750
|
+
const isXml = isXmlMode(options);
|
|
2751
|
+
const isLowerCaseTags = options.lowerCaseTags ?? !isXml;
|
|
2752
|
+
const isLowerCaseAttributes = options.lowerCaseAttributeNames ?? !isXml;
|
|
2753
|
+
const result = [];
|
|
2754
|
+
for (const id of ids) {
|
|
2755
|
+
const state = stateIn(document, id);
|
|
2756
|
+
if (!sameMatchOptions(state.options, isXml, isLowerCaseTags, isLowerCaseAttributes)) return void 0;
|
|
2757
|
+
const local = id - state.base;
|
|
2758
|
+
for (const compound of compounds) {
|
|
2759
|
+
if (matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes)) {
|
|
2760
|
+
result.push(id);
|
|
2761
|
+
break;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
return result;
|
|
2766
|
+
}
|
|
2767
|
+
var walkBudget = 4096;
|
|
2768
|
+
var smallDocumentNodes = 512;
|
|
2769
|
+
var tinyDocumentNodes = 64;
|
|
2770
|
+
function selectSimpleWithin(document, contexts, selector, options) {
|
|
2771
|
+
if (contexts.length !== 1 || !isRouted(document)) return void 0;
|
|
2772
|
+
const compounds = compile(selector);
|
|
2773
|
+
if (!compounds) return void 0;
|
|
2774
|
+
const isXml = isXmlMode(options);
|
|
2775
|
+
const isLowerCaseTags = options.lowerCaseTags ?? !isXml;
|
|
2776
|
+
const isLowerCaseAttributes = options.lowerCaseAttributeNames ?? !isXml;
|
|
2777
|
+
const state = stateIn(document, contexts[0]);
|
|
2778
|
+
if (!sameMatchOptions(state.options, isXml, isLowerCaseTags, isLowerCaseAttributes)) return void 0;
|
|
2779
|
+
const context = contexts[0] - state.base;
|
|
2780
|
+
const size = Math.max(state.baseline, state.snapshotSize);
|
|
2781
|
+
const isDocumentRoot = context === (state.rootLocal ??= state.raw.rootId());
|
|
2782
|
+
const contextType = isDocumentRoot ? "root" : typeAt(state, context);
|
|
2783
|
+
const isReadable = state.bulk instanceof NodeSnapshot ? size <= smallDocumentNodes : state.generation === 0 && size <= tinyDocumentNodes;
|
|
2784
|
+
const isSmallRoot = contextType === "root" && isReadable;
|
|
2785
|
+
if (!isElementType2(contextType) && !isSmallRoot) return void 0;
|
|
2786
|
+
const result = [];
|
|
2787
|
+
const stack = [];
|
|
2788
|
+
pushChildren(state, context, stack);
|
|
2789
|
+
for (let visited = 0; stack.length; visited++) {
|
|
2790
|
+
if (visited === walkBudget) return void 0;
|
|
2791
|
+
const local = stack.pop();
|
|
2792
|
+
const type = typeAt(state, local);
|
|
2793
|
+
if (type === "root") {
|
|
2794
|
+
if (isSmallRoot) return void 0;
|
|
2795
|
+
continue;
|
|
2796
|
+
}
|
|
2797
|
+
if (isElementType2(type)) {
|
|
2798
|
+
for (const compound of compounds) {
|
|
2799
|
+
if (matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes)) {
|
|
2800
|
+
result.push(state.base + local);
|
|
2801
|
+
break;
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
pushChildren(state, local, stack);
|
|
2806
|
+
}
|
|
2807
|
+
return result;
|
|
2808
|
+
}
|
|
2809
|
+
var isElementType2 = (type) => type === "tag" || type === "script" || type === "style";
|
|
2810
|
+
function typeAt(state, local) {
|
|
2811
|
+
const snapshot = plainSnapshot(state, local);
|
|
2812
|
+
return snapshot ? snapshot.typeOf(local) : recordAt(state, local)?.type;
|
|
2813
|
+
}
|
|
2814
|
+
function pushChildren(state, local, stack) {
|
|
2815
|
+
const snapshot = plainSnapshot(state, local);
|
|
2816
|
+
if (snapshot) {
|
|
2817
|
+
for (let index = snapshot.childCount(local) - 1; index >= 0; index--) stack.push(snapshot.childAt(local, index));
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2820
|
+
const children = recordAt(state, local)?.children ?? [];
|
|
2821
|
+
for (let index = children.length - 1; index >= 0; index--) stack.push(children[index]);
|
|
2822
|
+
}
|
|
2823
|
+
function isXmlMode(options) {
|
|
2824
|
+
return options.xmlMode ?? (options.xml === true || typeof options.xml === "object" && options.xml !== null);
|
|
2825
|
+
}
|
|
2826
|
+
function sameMatchOptions(documentOptions, isXml, isLowerCaseTags, isLowerCaseAttributes) {
|
|
2827
|
+
const isDocumentXml = isXmlMode(documentOptions);
|
|
2828
|
+
return isDocumentXml === isXml && (documentOptions.lowerCaseTags ?? !isDocumentXml) === isLowerCaseTags && (documentOptions.lowerCaseAttributeNames ?? !isDocumentXml) === isLowerCaseAttributes;
|
|
2829
|
+
}
|
|
2830
|
+
function matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes) {
|
|
2831
|
+
const snapshot = plainSnapshot(state, local);
|
|
2832
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
2833
|
+
if (!snapshot && !record) return false;
|
|
2834
|
+
if (!isElementType2(snapshot ? snapshot.typeOf(local) : record.type)) return false;
|
|
2835
|
+
if (compound.tag !== void 0 && (snapshot ? snapshot.nameOf(local) : record.name) !== (isLowerCaseTags ? compound.lowerTag : compound.tag)) return false;
|
|
2836
|
+
for (const id of compound.ids) if (attributeAt(state, local, "id") !== id) return false;
|
|
2837
|
+
if (compound.classes.length) {
|
|
2838
|
+
const classes = attributeAt(state, local, "class");
|
|
2839
|
+
if (classes === void 0) return false;
|
|
2840
|
+
for (const name of compound.classes) if (!hasClass(classes, name)) return false;
|
|
2841
|
+
}
|
|
2842
|
+
for (const name of isLowerCaseAttributes ? compound.lowerAttributes : compound.attributes) if (attributeAt(state, local, name) === void 0) return false;
|
|
2843
|
+
return true;
|
|
2844
|
+
}
|
|
2845
|
+
var isAsciiWhitespace = (code) => code === 32 || code === 9 || code === 10 || code === 12 || code === 13;
|
|
2846
|
+
function hasClass(classes, name) {
|
|
2847
|
+
for (let start = classes.indexOf(name); start !== -1; start = classes.indexOf(name, start + 1)) {
|
|
2848
|
+
const end = start + name.length;
|
|
2849
|
+
if ((start === 0 || isAsciiWhitespace(classes.charCodeAt(start - 1))) && (end === classes.length || isAsciiWhitespace(classes.charCodeAt(end)))) return true;
|
|
2850
|
+
}
|
|
2851
|
+
return false;
|
|
2852
|
+
}
|
|
2853
|
+
function asciiLowerCase(value) {
|
|
2854
|
+
return /[A-Z]/.test(value) ? value.replace(/[A-Z]/g, (letter) => letter.toLowerCase()) : value;
|
|
2855
|
+
}
|
|
2856
|
+
function compile(selector) {
|
|
2857
|
+
const cached2 = compiled.get(selector);
|
|
2858
|
+
if (cached2 !== void 0) return cached2;
|
|
2859
|
+
const result = parse2(selector);
|
|
2860
|
+
if (compiled.size >= compiledLimit) compiled.clear();
|
|
2861
|
+
compiled.set(selector, result);
|
|
2862
|
+
return result;
|
|
2863
|
+
}
|
|
2864
|
+
var identifierStart = /[A-Za-z_]/;
|
|
2865
|
+
var identifierPart = /[A-Za-z0-9_-]/;
|
|
2866
|
+
function parse2(selector) {
|
|
2867
|
+
const compounds = [];
|
|
2868
|
+
let index = 0;
|
|
2869
|
+
const skipSpace = () => {
|
|
2870
|
+
while (index < selector.length && isAsciiWhitespace(selector.charCodeAt(index))) index++;
|
|
2871
|
+
};
|
|
2872
|
+
const identifier = () => {
|
|
2873
|
+
const start = index;
|
|
2874
|
+
if (selector[index] === "-") index++;
|
|
2875
|
+
if (!identifierStart.test(selector[index] ?? "")) return null;
|
|
2876
|
+
while (index < selector.length && identifierPart.test(selector[index])) index++;
|
|
2877
|
+
return selector.slice(start, index);
|
|
2878
|
+
};
|
|
2879
|
+
for (; ; ) {
|
|
2880
|
+
skipSpace();
|
|
2881
|
+
const compound = { tag: void 0, lowerTag: void 0, ids: [], classes: [], attributes: [], lowerAttributes: [] };
|
|
2882
|
+
let hasPart = false;
|
|
2883
|
+
if (selector[index] === "*") {
|
|
2884
|
+
index++;
|
|
2885
|
+
hasPart = true;
|
|
2886
|
+
} else if (/[A-Za-z]/.test(selector[index] ?? "")) {
|
|
2887
|
+
compound.tag = identifier();
|
|
2888
|
+
hasPart = true;
|
|
2889
|
+
}
|
|
2890
|
+
for (; ; ) {
|
|
2891
|
+
const character = selector[index];
|
|
2892
|
+
if (character === "#" || character === ".") {
|
|
2893
|
+
index++;
|
|
2894
|
+
const name = identifier();
|
|
2895
|
+
if (name === null) return null;
|
|
2896
|
+
(character === "#" ? compound.ids : compound.classes).push(name);
|
|
2897
|
+
} else if (character === "[") {
|
|
2898
|
+
index++;
|
|
2899
|
+
skipSpace();
|
|
2900
|
+
const name = identifier();
|
|
2901
|
+
if (name === null) return null;
|
|
2902
|
+
skipSpace();
|
|
2903
|
+
if (selector[index] !== "]") return null;
|
|
2904
|
+
index++;
|
|
2905
|
+
compound.attributes.push(name);
|
|
2906
|
+
} else break;
|
|
2907
|
+
hasPart = true;
|
|
2908
|
+
}
|
|
2909
|
+
if (!hasPart) return null;
|
|
2910
|
+
compound.lowerTag = compound.tag === void 0 ? void 0 : asciiLowerCase(compound.tag);
|
|
2911
|
+
compound.lowerAttributes = compound.attributes.map(asciiLowerCase);
|
|
2912
|
+
compounds.push(compound);
|
|
2913
|
+
skipSpace();
|
|
2914
|
+
if (index === selector.length) return compounds;
|
|
2915
|
+
if (selector[index] !== ",") return null;
|
|
2916
|
+
index++;
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
|
|
1628
2920
|
// src/selection.ts
|
|
1629
2921
|
var numeric = /^(?:0|[1-9]\d*)$/;
|
|
1630
2922
|
var isMarkup = (value) => /<[a-zA-Z!/?]/.test(value);
|
|
@@ -1696,103 +2988,166 @@ function* customPseudoArguments(selector, name) {
|
|
|
1696
2988
|
index = end;
|
|
1697
2989
|
}
|
|
1698
2990
|
}
|
|
2991
|
+
var isIndex = (property2) => {
|
|
2992
|
+
if (typeof property2 !== "string") return false;
|
|
2993
|
+
const first = property2.charCodeAt(0);
|
|
2994
|
+
return first >= 48 && first <= 57 && numeric.test(property2);
|
|
2995
|
+
};
|
|
2996
|
+
var plainSelectionLimit = 16;
|
|
2997
|
+
var lengthOf = (target) => target[VALUES]?.length ?? target[IDS].length;
|
|
2998
|
+
function nodeAt(target, index) {
|
|
2999
|
+
if (target[VALUES]) return target[VALUES][index];
|
|
3000
|
+
const id = target[IDS][index];
|
|
3001
|
+
return id === void 0 ? void 0 : getNode(target[DOCUMENT], id);
|
|
3002
|
+
}
|
|
3003
|
+
function releaseIds(target) {
|
|
3004
|
+
if (target[LEASE]) updateLease(target[DOCUMENT], target[LEASE], target[VALUES] ? [] : target[IDS]);
|
|
3005
|
+
}
|
|
3006
|
+
function writeIndex(target, index, value) {
|
|
3007
|
+
if (target[VALUES]) target[VALUES][index] = value;
|
|
3008
|
+
else {
|
|
3009
|
+
const id = importNodes(target[DOCUMENT], [value])[0];
|
|
3010
|
+
if (id === void 0) {
|
|
3011
|
+
target[VALUES] = target[IDS].map((existing) => getNode(target[DOCUMENT], existing));
|
|
3012
|
+
target[VALUES][index] = value;
|
|
3013
|
+
} else target[IDS][index] = id;
|
|
3014
|
+
}
|
|
3015
|
+
releaseIds(target);
|
|
3016
|
+
}
|
|
3017
|
+
var selectionHandler = {
|
|
3018
|
+
get: (target, property2) => isIndex(property2) ? nodeAt(target, Number(property2)) : property2 === "length" ? lengthOf(target) : Reflect.get(target, property2),
|
|
3019
|
+
set: (target, property2, value) => {
|
|
3020
|
+
if (isIndex(property2)) {
|
|
3021
|
+
writeIndex(target, Number(property2), value);
|
|
3022
|
+
return true;
|
|
3023
|
+
}
|
|
3024
|
+
if (property2 === "length") {
|
|
3025
|
+
if (target[VALUES]) target[VALUES].length = value;
|
|
3026
|
+
else target[IDS].length = value;
|
|
3027
|
+
releaseIds(target);
|
|
3028
|
+
return true;
|
|
3029
|
+
}
|
|
3030
|
+
return Reflect.set(target, property2, value);
|
|
3031
|
+
},
|
|
3032
|
+
has: (target, property2) => isIndex(property2) ? Number(property2) < lengthOf(target) : property2 === "length" || Reflect.has(target, property2),
|
|
3033
|
+
ownKeys: (target) => [...Array.from({ length: lengthOf(target) }, (_, i) => String(i)), "length", ...Reflect.ownKeys(target)],
|
|
3034
|
+
getOwnPropertyDescriptor: (target, property2) => {
|
|
3035
|
+
if (isIndex(property2) && Number(property2) < lengthOf(target))
|
|
3036
|
+
return { value: nodeAt(target, Number(property2)), writable: true, configurable: true, enumerable: true };
|
|
3037
|
+
if (property2 === "length") return { value: lengthOf(target), writable: true, configurable: true, enumerable: true };
|
|
3038
|
+
return Reflect.getOwnPropertyDescriptor(target, property2);
|
|
3039
|
+
},
|
|
3040
|
+
deleteProperty: (target, property2) => {
|
|
3041
|
+
if (isIndex(property2)) {
|
|
3042
|
+
if (target[VALUES])
|
|
3043
|
+
delete target[VALUES][Number(property2)];
|
|
3044
|
+
else
|
|
3045
|
+
delete target[IDS][Number(property2)];
|
|
3046
|
+
releaseIds(target);
|
|
3047
|
+
return true;
|
|
3048
|
+
}
|
|
3049
|
+
return Reflect.deleteProperty(target, property2);
|
|
3050
|
+
}
|
|
3051
|
+
};
|
|
1699
3052
|
var Cheerio = class {
|
|
1700
|
-
|
|
3053
|
+
/** @internal */
|
|
3054
|
+
get _document() {
|
|
3055
|
+
return this[DOCUMENT];
|
|
3056
|
+
}
|
|
3057
|
+
/** @internal */
|
|
3058
|
+
get _api() {
|
|
3059
|
+
return this[API];
|
|
3060
|
+
}
|
|
3061
|
+
/** @internal */
|
|
3062
|
+
get _ids() {
|
|
3063
|
+
return this[IDS];
|
|
3064
|
+
}
|
|
1701
3065
|
constructor(api, document, ids = [], root = null, options = {}, values) {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
|
-
return new Proxy(this,
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
1734
|
-
return true;
|
|
1735
|
-
}
|
|
1736
|
-
return Reflect.set(target, property2, value, receiver);
|
|
1737
|
-
},
|
|
1738
|
-
has: (target, property2) => typeof property2 === "string" && numeric.test(property2) ? Number(property2) < target.length : Reflect.has(target, property2),
|
|
1739
|
-
ownKeys: (target) => [...Array.from({ length: target.length }, (_, i) => String(i)), ...Reflect.ownKeys(target)],
|
|
1740
|
-
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),
|
|
1741
|
-
deleteProperty: (target, property2) => {
|
|
1742
|
-
if (typeof property2 === "string" && numeric.test(property2)) {
|
|
1743
|
-
if (target._values)
|
|
1744
|
-
delete target._values[Number(property2)];
|
|
1745
|
-
else
|
|
1746
|
-
delete target._ids[Number(property2)];
|
|
1747
|
-
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
1748
|
-
return true;
|
|
1749
|
-
}
|
|
1750
|
-
return Reflect.deleteProperty(target, property2);
|
|
1751
|
-
}
|
|
1752
|
-
});
|
|
3066
|
+
this[DOCUMENT] = document;
|
|
3067
|
+
this[API] = api;
|
|
3068
|
+
this[IDS] = ids;
|
|
3069
|
+
this[VALUES] = values;
|
|
3070
|
+
this[LEASE] = void 0;
|
|
3071
|
+
const count = values ? values.length : ids.length;
|
|
3072
|
+
const isPlain = count <= plainSelectionLimit;
|
|
3073
|
+
this[IS_PLAIN] = isPlain;
|
|
3074
|
+
if (isPlain) this.length = count;
|
|
3075
|
+
this.options = options;
|
|
3076
|
+
this._root = root;
|
|
3077
|
+
if (isPlain) {
|
|
3078
|
+
if (values) for (let index = 0; index < count; index++) this[index] = values[index];
|
|
3079
|
+
else for (let index = 0; index < count; index++) this[index] = getNode(document, ids[index]);
|
|
3080
|
+
return;
|
|
3081
|
+
}
|
|
3082
|
+
if (!values) this[LEASE] = leaseNodes(document, this, ids);
|
|
3083
|
+
return new Proxy(this, selectionHandler);
|
|
3084
|
+
}
|
|
3085
|
+
/** @internal Re-reads a plain selection after direct index writes or after its nodes moved documents. */
|
|
3086
|
+
_syncIndices() {
|
|
3087
|
+
const length = this.length;
|
|
3088
|
+
const values = this[VALUES];
|
|
3089
|
+
const ids = this[IDS];
|
|
3090
|
+
let isChanged = (values ?? ids).length !== length;
|
|
3091
|
+
for (let index = 0; !isChanged && index < length; index++) isChanged = values ? this[index] !== values[index] : viewId(this[index]) !== ids[index];
|
|
3092
|
+
if (!isChanged) return;
|
|
3093
|
+
const items = Array.from({ length }, (_unused, index) => this[index]);
|
|
3094
|
+
const isAllNodes = items.every((value) => value && typeof value === "object" && typeof value.type === "string");
|
|
3095
|
+
this[VALUES] = isAllNodes ? void 0 : items;
|
|
3096
|
+
this[IDS] = isAllNodes ? importNodes(this[DOCUMENT], items) : [];
|
|
1753
3097
|
}
|
|
1754
3098
|
/** @internal */
|
|
1755
3099
|
get ids() {
|
|
1756
|
-
|
|
3100
|
+
if (this[IS_PLAIN]) this._syncIndices();
|
|
3101
|
+
return this[VALUES] ? importNodes(this[DOCUMENT], this[VALUES]) : this[IDS];
|
|
1757
3102
|
}
|
|
1758
3103
|
/** @internal */
|
|
1759
3104
|
op(command, args = {}) {
|
|
1760
3105
|
const values = args;
|
|
1761
|
-
return operation(this
|
|
3106
|
+
return operation(this[DOCUMENT], command, { ...values, options: values.options ?? this.options });
|
|
1762
3107
|
}
|
|
1763
3108
|
/** @internal */
|
|
1764
3109
|
_query(command, args) {
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
|
|
3110
|
+
const pseudos = this.options.pseudos;
|
|
3111
|
+
const callbacks = pseudos ? Object.entries(pseudos).filter((entry) => typeof entry[1] === "function") : [];
|
|
3112
|
+
if (!callbacks.length) {
|
|
3113
|
+
if (command === "matches" && args.ids) {
|
|
3114
|
+
const matched = matchSimpleSelector(this[DOCUMENT], args.ids, args.selector, args.options ?? this.options);
|
|
3115
|
+
if (matched) return matched;
|
|
3116
|
+
}
|
|
3117
|
+
if (command === "select" && args.contexts) {
|
|
3118
|
+
const found = selectSimpleWithin(this[DOCUMENT], args.contexts, args.selector, args.options ?? this.options);
|
|
3119
|
+
if (found) return found;
|
|
3120
|
+
}
|
|
3121
|
+
return command === "select" && !args.options ? this[DOCUMENT].select(args.selector, args.contexts) : this.op(command, args);
|
|
3122
|
+
}
|
|
1768
3123
|
const pseudoMatches = {};
|
|
1769
|
-
const candidates = [.../* @__PURE__ */ new Set([...this.
|
|
3124
|
+
const candidates = [.../* @__PURE__ */ new Set([...this[DOCUMENT].select("*"), ...args.ids ?? [], ...args.contexts ? this[DOCUMENT].select("*", args.contexts) : []])];
|
|
1770
3125
|
for (const [name, callback] of callbacks) {
|
|
1771
3126
|
for (const argument of customPseudoArguments(args.selector, name)) {
|
|
1772
3127
|
if (argument !== void 0 && callback.length < 2)
|
|
1773
3128
|
throw new Error(`Pseudo-class :${name} doesn't have any arguments`);
|
|
1774
3129
|
if (argument === void 0 && callback.length >= 2)
|
|
1775
3130
|
throw new Error(`Pseudo-class :${name} requires an argument`);
|
|
1776
|
-
pseudoMatches[`${name}(${argument ?? ""})`] = candidates.filter((id) => callback(getNode(this
|
|
3131
|
+
pseudoMatches[`${name}(${argument ?? ""})`] = candidates.filter((id) => callback(getNode(this[DOCUMENT], id), argument ?? null));
|
|
1777
3132
|
}
|
|
1778
3133
|
}
|
|
1779
3134
|
return this.op(command, { ...args, pseudoMatches });
|
|
1780
3135
|
}
|
|
1781
3136
|
/** @internal */
|
|
1782
3137
|
_fromIds(ids) {
|
|
1783
|
-
const result = new this.
|
|
3138
|
+
const result = new this[API].fn.constructor(this[API], this[DOCUMENT], ids, this._root, this.options);
|
|
1784
3139
|
result.prevObject = this;
|
|
1785
3140
|
return result;
|
|
1786
3141
|
}
|
|
1787
3142
|
/** @internal */
|
|
1788
3143
|
_fromValues(values) {
|
|
1789
3144
|
const allNodes = values.every((value) => value && typeof value === "object" && typeof value.type === "string");
|
|
1790
|
-
const result = new this.
|
|
3145
|
+
const result = new this[API].fn.constructor(this[API], this[DOCUMENT], allNodes ? importNodes(this[DOCUMENT], values) : [], this._root, this.options, allNodes ? void 0 : values);
|
|
1791
3146
|
result.prevObject = this;
|
|
1792
3147
|
return result;
|
|
1793
3148
|
}
|
|
1794
3149
|
_make(value, context) {
|
|
1795
|
-
const result = typeof value === "string" || value?.cheerio ? this
|
|
3150
|
+
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]);
|
|
1796
3151
|
result.prevObject = this;
|
|
1797
3152
|
return result;
|
|
1798
3153
|
}
|
|
@@ -1800,7 +3155,7 @@ var Cheerio = class {
|
|
|
1800
3155
|
return parse(content, options, isDocument2, context);
|
|
1801
3156
|
}
|
|
1802
3157
|
_render(content) {
|
|
1803
|
-
return this.
|
|
3158
|
+
return this[DOCUMENT].outerHtml(importNodes(this[DOCUMENT], content));
|
|
1804
3159
|
}
|
|
1805
3160
|
/** @internal */
|
|
1806
3161
|
_domIds(content, contextId) {
|
|
@@ -1808,22 +3163,26 @@ var Cheerio = class {
|
|
|
1808
3163
|
return [];
|
|
1809
3164
|
if (typeof content === "string")
|
|
1810
3165
|
return this.op("create", { html: content, contextId, options: this.options });
|
|
1811
|
-
if (content?.cheerio)
|
|
1812
|
-
|
|
3166
|
+
if (content?.cheerio) {
|
|
3167
|
+
if (!content[DOCUMENT] || !sameNodeSpace(this[DOCUMENT], content[DOCUMENT]))
|
|
3168
|
+
return importNodes(this[DOCUMENT], content.toArray());
|
|
3169
|
+
exposeDocumentTo(this[DOCUMENT], content[DOCUMENT]);
|
|
3170
|
+
return content.ids;
|
|
3171
|
+
}
|
|
1813
3172
|
if (typeof content === "object" && "length" in content && !content.type)
|
|
1814
3173
|
return Array.from(content).flatMap((item) => this._domIds(item, contextId));
|
|
1815
|
-
return importNodes(this
|
|
3174
|
+
return importNodes(this[DOCUMENT], [content]);
|
|
1816
3175
|
}
|
|
1817
3176
|
_makeDomArray(content, clone = false) {
|
|
1818
3177
|
const ids = this._domIds(content);
|
|
1819
|
-
return (clone ? this.op("clone", { ids, deep: true }) : ids).map((id) => getNode(this
|
|
3178
|
+
return (clone ? this.op("clone", { ids, deep: true }) : ids).map((id) => getNode(this[DOCUMENT], id));
|
|
1820
3179
|
}
|
|
1821
3180
|
find(selector) {
|
|
1822
3181
|
if (!selector)
|
|
1823
3182
|
return this._fromIds([]);
|
|
1824
3183
|
if (typeof selector === "string")
|
|
1825
3184
|
return this._findBySelector(selector, Infinity);
|
|
1826
|
-
const ids = importNodes(this
|
|
3185
|
+
const ids = importNodes(this[DOCUMENT], selector);
|
|
1827
3186
|
return this._fromIds(ids.filter((id) => this.ids.some((container) => this.op("contains", { container, contained: id }))));
|
|
1828
3187
|
}
|
|
1829
3188
|
_findBySelector(selector, limit) {
|
|
@@ -1836,21 +3195,21 @@ var Cheerio = class {
|
|
|
1836
3195
|
return ids;
|
|
1837
3196
|
if (typeof selector === "string")
|
|
1838
3197
|
return this._query("matches", { ids, selector, options: this.options });
|
|
1839
|
-
return ids.filter((id, index) => this._predicate(selector, getNode(this
|
|
3198
|
+
return ids.filter((id, index) => this._predicate(selector, getNode(this[DOCUMENT], id), index));
|
|
1840
3199
|
}
|
|
1841
3200
|
/** @internal */
|
|
1842
3201
|
_predicate(selector, node, index) {
|
|
1843
3202
|
if (typeof selector === "function")
|
|
1844
3203
|
return !!selector.call(node, index, node);
|
|
1845
3204
|
if (typeof selector === "string")
|
|
1846
|
-
return this._query("matches", { ids: importNodes(this
|
|
3205
|
+
return this._query("matches", { ids: importNodes(this[DOCUMENT], [node]), selector, options: this.options }).length > 0;
|
|
1847
3206
|
if (selector?.cheerio)
|
|
1848
3207
|
return selector.toArray().includes(node);
|
|
1849
3208
|
return node === selector;
|
|
1850
3209
|
}
|
|
1851
3210
|
/** @internal */
|
|
1852
3211
|
_traverse(kind, selector) {
|
|
1853
|
-
let ids = this.op("traverse", { ids: this.ids, kind });
|
|
3212
|
+
let ids = traverseRecords(this[DOCUMENT], this.ids, kind) ?? this.op("traverse", { ids: this.ids, kind });
|
|
1854
3213
|
ids = this._filterIds(ids, selector);
|
|
1855
3214
|
if (this.length > 1 && ids.length > 1) {
|
|
1856
3215
|
if (kind === "parents" || kind === "siblings")
|
|
@@ -1893,8 +3252,8 @@ var Cheerio = class {
|
|
|
1893
3252
|
_until(kind, until, filter) {
|
|
1894
3253
|
let ids = [];
|
|
1895
3254
|
for (const id of this.ids)
|
|
1896
|
-
for (const candidate of this.op("traverse", { ids: [id], kind })) {
|
|
1897
|
-
if (until && this._predicate(until, getNode(this
|
|
3255
|
+
for (const candidate of traverseRecords(this[DOCUMENT], [id], kind) ?? this.op("traverse", { ids: [id], kind })) {
|
|
3256
|
+
if (until && this._predicate(until, getNode(this[DOCUMENT], candidate), ids.length))
|
|
1898
3257
|
break;
|
|
1899
3258
|
ids.push(candidate);
|
|
1900
3259
|
}
|
|
@@ -1917,25 +3276,37 @@ var Cheerio = class {
|
|
|
1917
3276
|
return this._fromIds([]);
|
|
1918
3277
|
const result = [];
|
|
1919
3278
|
for (const id of this.ids) {
|
|
1920
|
-
const record = nodeRecord(this
|
|
1921
|
-
const candidates = [...["tag", "script", "style"].includes(record.type) ? [id] : [], ...this.op("traverse", { ids: [id], kind: "parents" })];
|
|
1922
|
-
const
|
|
3279
|
+
const record = nodeRecord(this[DOCUMENT], id);
|
|
3280
|
+
const candidates = [...["tag", "script", "style"].includes(record.type) ? [id] : [], ...traverseRecords(this[DOCUMENT], [id], "parents") ?? this.op("traverse", { ids: [id], kind: "parents" })];
|
|
3281
|
+
const matched = typeof selector === "string" ? new Set(this._filterIds(candidates, selector)) : void 0;
|
|
3282
|
+
const match = matched ? candidates.find((candidate) => matched.has(candidate)) : candidates.find((candidate) => this._predicate(selector, getNode(this[DOCUMENT], candidate), 0));
|
|
1923
3283
|
if (match !== void 0 && !result.includes(match))
|
|
1924
3284
|
result.push(match);
|
|
1925
3285
|
}
|
|
1926
3286
|
return this._fromIds(result);
|
|
1927
3287
|
}
|
|
1928
3288
|
each(callback) {
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
3289
|
+
if (this[IS_PLAIN]) {
|
|
3290
|
+
const length2 = this.length;
|
|
3291
|
+
for (let i = 0; i < length2; i++)
|
|
3292
|
+
if (callback.call(this[i], i, this[i]) === false)
|
|
3293
|
+
break;
|
|
3294
|
+
return this;
|
|
3295
|
+
}
|
|
3296
|
+
const values = this[VALUES], ids = this[IDS], document = this[DOCUMENT];
|
|
3297
|
+
const length = values ? values.length : ids.length;
|
|
3298
|
+
for (let i = 0; i < length; i++) {
|
|
3299
|
+
const node = values ? values[i] : getNode(document, ids[i]);
|
|
3300
|
+
if (callback.call(node, i, node) === false)
|
|
1932
3301
|
break;
|
|
3302
|
+
}
|
|
1933
3303
|
return this;
|
|
1934
3304
|
}
|
|
1935
3305
|
map(callback) {
|
|
1936
3306
|
const result = [];
|
|
1937
|
-
|
|
1938
|
-
|
|
3307
|
+
const items = this._items();
|
|
3308
|
+
for (let i = 0; i < items.length; i++) {
|
|
3309
|
+
const value = callback.call(items[i], i, items[i]);
|
|
1939
3310
|
if (value != null)
|
|
1940
3311
|
result.push(...Array.isArray(value) ? value : [value]);
|
|
1941
3312
|
}
|
|
@@ -1948,7 +3319,7 @@ var Cheerio = class {
|
|
|
1948
3319
|
const matcher = match;
|
|
1949
3320
|
if (typeof match !== "string")
|
|
1950
3321
|
return nodes.filter((node, index) => typeof matcher === "function" ? matcher.call(node, index, node) : matcher?.cheerio ? matcher.toArray().includes(node) : matcher === node);
|
|
1951
|
-
const document = this?.
|
|
3322
|
+
const document = this?.[DOCUMENT] ?? nodeBinding(root)?.document ?? nodeBinding(nodes[0])?.document ?? routeDocument(new (requireNative()).NativeDocument("", false));
|
|
1952
3323
|
const ids = importNodes(document, nodes);
|
|
1953
3324
|
const selected = new Set(operation(document, "matches", { ids, selector: match, options: { xmlMode } }));
|
|
1954
3325
|
return nodes.filter((node) => {
|
|
@@ -1981,50 +3352,72 @@ var Cheerio = class {
|
|
|
1981
3352
|
return this;
|
|
1982
3353
|
if (index < 0)
|
|
1983
3354
|
index += this.length;
|
|
1984
|
-
|
|
3355
|
+
const item = this._itemAt(index);
|
|
3356
|
+
return this._fromValues(item === void 0 ? [] : [item]);
|
|
1985
3357
|
}
|
|
1986
3358
|
get(index) {
|
|
1987
|
-
return index == null ? this.toArray() : this
|
|
3359
|
+
return index == null ? this.toArray() : this._itemAt(index < 0 ? this.length + index : index);
|
|
1988
3360
|
}
|
|
1989
3361
|
toArray() {
|
|
1990
|
-
return
|
|
3362
|
+
return this._items();
|
|
3363
|
+
}
|
|
3364
|
+
/** @internal Every item, read without a proxy trap per index. */
|
|
3365
|
+
_items() {
|
|
3366
|
+
if (this[IS_PLAIN]) {
|
|
3367
|
+
const length = this.length;
|
|
3368
|
+
const items = new Array(length);
|
|
3369
|
+
for (let i = 0; i < length; i++) items[i] = this[i];
|
|
3370
|
+
return items;
|
|
3371
|
+
}
|
|
3372
|
+
const values = this[VALUES], ids = this[IDS], document = this[DOCUMENT];
|
|
3373
|
+
return values ? values.slice() : ids.map((id) => getNode(document, id));
|
|
3374
|
+
}
|
|
3375
|
+
/** @internal */
|
|
3376
|
+
_itemAt(index) {
|
|
3377
|
+
if (this[IS_PLAIN]) return this[index];
|
|
3378
|
+
const values = this[VALUES];
|
|
3379
|
+
if (values) return values[index];
|
|
3380
|
+
const id = this[IDS][index];
|
|
3381
|
+
return id === void 0 ? void 0 : getNode(this[DOCUMENT], id);
|
|
1991
3382
|
}
|
|
1992
3383
|
slice(start, end) {
|
|
1993
|
-
|
|
3384
|
+
const ids = this.ids;
|
|
3385
|
+
return this[VALUES] ? this._fromValues(this[VALUES].slice(start, end)) : this._fromIds(ids.slice(start, end));
|
|
1994
3386
|
}
|
|
1995
3387
|
end() {
|
|
1996
3388
|
return this.prevObject ?? this._make([]);
|
|
1997
3389
|
}
|
|
1998
3390
|
add(other, context) {
|
|
1999
|
-
|
|
3391
|
+
const added = this[API](other, context);
|
|
3392
|
+
const addedIds = added[DOCUMENT] && sameNodeSpace(this[DOCUMENT], added[DOCUMENT]) ? added.ids : importNodes(this[DOCUMENT], added.toArray());
|
|
3393
|
+
return this._fromIds(this.op("uniqueSort", { ids: [...this.ids, ...addedIds] }));
|
|
2000
3394
|
}
|
|
2001
3395
|
addBack(selector) {
|
|
2002
3396
|
return this.prevObject ? this.add(selector ? this.prevObject.filter(selector) : this.prevObject) : this;
|
|
2003
3397
|
}
|
|
2004
3398
|
index(selector) {
|
|
2005
|
-
const haystack = selector == null ? this.parent().children() : typeof selector === "string" ? this
|
|
3399
|
+
const haystack = selector == null ? this.parent().children() : typeof selector === "string" ? this[API](selector) : this;
|
|
2006
3400
|
const needle = selector == null || typeof selector === "string" ? this[0] : selector?.cheerio ? selector[0] : selector;
|
|
2007
3401
|
return haystack.toArray().indexOf(needle);
|
|
2008
3402
|
}
|
|
2009
3403
|
splice(...args) {
|
|
2010
3404
|
return Reflect.apply(Array.prototype.splice, this, args);
|
|
2011
3405
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
yield this[i];
|
|
3406
|
+
[Symbol.iterator]() {
|
|
3407
|
+
return this._items()[Symbol.iterator]();
|
|
2015
3408
|
}
|
|
2016
3409
|
/** @internal */
|
|
2017
3410
|
_insert(position, content) {
|
|
2018
|
-
const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3411
|
+
const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], id).type));
|
|
2019
3412
|
if (!targets.length)
|
|
2020
3413
|
return this;
|
|
2021
3414
|
if (typeof content[0] === "function")
|
|
2022
3415
|
return this.each((index, node) => {
|
|
2023
3416
|
if (!targets.includes(this.ids[index]))
|
|
2024
3417
|
return;
|
|
2025
|
-
if ((position === "before" || position === "after") && nodeRecord(this
|
|
3418
|
+
if ((position === "before" || position === "after") && nodeRecord(this[DOCUMENT], this.ids[index]).parent == null)
|
|
2026
3419
|
return;
|
|
2027
|
-
const value = content[0].call(node, index, this.
|
|
3420
|
+
const value = content[0].call(node, index, this[DOCUMENT].innerHtml(this.ids[index]));
|
|
2028
3421
|
let nodes2 = this._domIds(value);
|
|
2029
3422
|
if (index < this.length - 1)
|
|
2030
3423
|
nodes2 = this.op("clone", { ids: nodes2, deep: true });
|
|
@@ -2049,20 +3442,20 @@ var Cheerio = class {
|
|
|
2049
3442
|
return this._insert("after", content);
|
|
2050
3443
|
}
|
|
2051
3444
|
appendTo(target) {
|
|
2052
|
-
this
|
|
3445
|
+
this[API](target).append(this);
|
|
2053
3446
|
return this;
|
|
2054
3447
|
}
|
|
2055
3448
|
prependTo(target) {
|
|
2056
|
-
this
|
|
3449
|
+
this[API](target).prepend(this);
|
|
2057
3450
|
return this;
|
|
2058
3451
|
}
|
|
2059
3452
|
/** @internal */
|
|
2060
3453
|
_insertRelative(target, position) {
|
|
2061
|
-
const targets = this
|
|
3454
|
+
const targets = this[API](target).ids;
|
|
2062
3455
|
this.remove();
|
|
2063
3456
|
const inserted = [];
|
|
2064
3457
|
for (const id of targets) {
|
|
2065
|
-
if (nodeRecord(this
|
|
3458
|
+
if (nodeRecord(this[DOCUMENT], id).parent == null)
|
|
2066
3459
|
continue;
|
|
2067
3460
|
const clones = this.op("clone", { ids: this.ids, deep: true });
|
|
2068
3461
|
this.op("insert", { targetIds: [id], nodeIds: clones, position });
|
|
@@ -2082,7 +3475,7 @@ var Cheerio = class {
|
|
|
2082
3475
|
}
|
|
2083
3476
|
replaceWith(content) {
|
|
2084
3477
|
return this.each((index, node) => {
|
|
2085
|
-
if (nodeRecord(this
|
|
3478
|
+
if (nodeRecord(this[DOCUMENT], this.ids[index]).parent == null)
|
|
2086
3479
|
return;
|
|
2087
3480
|
const value = typeof content === "function" ? content.call(node, index, node) : content;
|
|
2088
3481
|
this.op("insert", { targetIds: [this.ids[index]], nodeIds: this._domIds(value), position: "replace" });
|
|
@@ -2095,33 +3488,33 @@ var Cheerio = class {
|
|
|
2095
3488
|
}
|
|
2096
3489
|
html(content) {
|
|
2097
3490
|
if (content === void 0)
|
|
2098
|
-
return this.length && ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3491
|
+
return this.length && ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], this.ids[0]).type) ? this[DOCUMENT].innerHtml(this.ids[0]) : null;
|
|
2099
3492
|
if (!content?.cheerio) {
|
|
2100
3493
|
this.op("html", { ids: this.ids, value: String(content) });
|
|
2101
3494
|
return this;
|
|
2102
3495
|
}
|
|
2103
3496
|
for (const id of this.ids) {
|
|
2104
|
-
const nodes = content?.cheerio ? importNodes(this
|
|
3497
|
+
const nodes = content?.cheerio ? importNodes(this[DOCUMENT], content.toArray()) : this._domIds(String(content), id);
|
|
2105
3498
|
this.op("setNode", { id, field: "children", value: nodes });
|
|
2106
3499
|
}
|
|
2107
3500
|
return this;
|
|
2108
3501
|
}
|
|
2109
3502
|
text(content) {
|
|
2110
3503
|
if (content === void 0)
|
|
2111
|
-
return this.
|
|
3504
|
+
return this[DOCUMENT].text(this.ids);
|
|
2112
3505
|
if (typeof content !== "function") {
|
|
2113
3506
|
this.op("text", { ids: this.ids, value: String(content) });
|
|
2114
3507
|
return this;
|
|
2115
3508
|
}
|
|
2116
3509
|
for (let i = 0; i < this.ids.length; i++) {
|
|
2117
3510
|
const id = this.ids[i];
|
|
2118
|
-
const value = typeof content === "function" ? content.call(getNode(this
|
|
3511
|
+
const value = typeof content === "function" ? content.call(getNode(this[DOCUMENT], id), i, this[DOCUMENT].text([id])) : content;
|
|
2119
3512
|
this.op("text", { ids: [id], value: String(value) });
|
|
2120
3513
|
}
|
|
2121
3514
|
return this;
|
|
2122
3515
|
}
|
|
2123
3516
|
toString() {
|
|
2124
|
-
return this.
|
|
3517
|
+
return this[DOCUMENT].outerHtml(this.ids);
|
|
2125
3518
|
}
|
|
2126
3519
|
clone() {
|
|
2127
3520
|
return this._fromIds(this.op("clone", { ids: this.ids, deep: true }));
|
|
@@ -2129,8 +3522,8 @@ var Cheerio = class {
|
|
|
2129
3522
|
/** @internal */
|
|
2130
3523
|
_deepest(id, tagsOnly = false) {
|
|
2131
3524
|
for (; ; ) {
|
|
2132
|
-
const
|
|
2133
|
-
const child = tagsOnly ?
|
|
3525
|
+
const children = this.op("traverse", { ids: [id], kind: "children" });
|
|
3526
|
+
const child = tagsOnly ? children.find((candidate) => nodeRecord(this[DOCUMENT], candidate).type === "tag") : children[0];
|
|
2134
3527
|
if (child === void 0)
|
|
2135
3528
|
return id;
|
|
2136
3529
|
id = child;
|
|
@@ -2141,24 +3534,23 @@ var Cheerio = class {
|
|
|
2141
3534
|
const lastParent = this.parents().last();
|
|
2142
3535
|
for (let i = 0; i < this.length; i++) {
|
|
2143
3536
|
const id = this.ids[i];
|
|
2144
|
-
const node = getNode(this
|
|
3537
|
+
const node = getNode(this[DOCUMENT], id);
|
|
2145
3538
|
const value = typeof content === "function" ? content.call(node, i, node) : typeof content === "string" && !isMarkup(content) ? lastParent.find(content).clone() : content;
|
|
2146
3539
|
let wrappers = this._domIds(value);
|
|
2147
3540
|
if (i < this.length - 1)
|
|
2148
3541
|
wrappers = this.op("clone", { ids: wrappers, deep: true });
|
|
2149
3542
|
const wrapper = wrappers[0];
|
|
2150
|
-
if (wrapper === void 0 || !["root", "tag", "script", "style"].includes(nodeRecord(this
|
|
3543
|
+
if (wrapper === void 0 || !["root", "tag", "script", "style"].includes(nodeRecord(this[DOCUMENT], wrapper).type))
|
|
2151
3544
|
continue;
|
|
2152
|
-
const deepest = this._deepest(wrapper);
|
|
2153
3545
|
if (inner) {
|
|
2154
|
-
if (!["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this
|
|
3546
|
+
if (!["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], id).type))
|
|
2155
3547
|
continue;
|
|
2156
3548
|
const contents = this.op("traverse", { ids: [id], kind: "contents" });
|
|
2157
|
-
this.op("setNode", { id:
|
|
3549
|
+
this.op("setNode", { id: this._deepest(wrapper), field: "children", value: contents });
|
|
2158
3550
|
this.op("setNode", { id, field: "children", value: [wrapper] });
|
|
2159
|
-
} else if (nodeRecord(this
|
|
2160
|
-
this.op("insert", { targetIds: [id], nodeIds: [wrapper], position: "before" });
|
|
2161
|
-
this.op("setNode", { id:
|
|
3551
|
+
} else if (nodeRecord(this[DOCUMENT], id).parent != null) {
|
|
3552
|
+
const [inserted = wrapper] = this.op("insert", { targetIds: [id], nodeIds: [wrapper], position: "before" });
|
|
3553
|
+
this.op("setNode", { id: this._deepest(inserted), field: "children", value: [id] });
|
|
2162
3554
|
}
|
|
2163
3555
|
}
|
|
2164
3556
|
return this;
|
|
@@ -2178,7 +3570,7 @@ var Cheerio = class {
|
|
|
2178
3570
|
return this;
|
|
2179
3571
|
const first = this[0];
|
|
2180
3572
|
const wrappers = this._make(typeof content === "function" ? content.call(first, 0, first) : content).insertBefore(first);
|
|
2181
|
-
const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this
|
|
3573
|
+
const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this[DOCUMENT], id).type === "tag");
|
|
2182
3574
|
if (root !== void 0)
|
|
2183
3575
|
this.op("insert", { targetIds: [this._deepest(root, true)], nodeIds: this.ids, position: "append" });
|
|
2184
3576
|
return this;
|
|
@@ -2188,6 +3580,19 @@ var Cheerio = class {
|
|
|
2188
3580
|
}
|
|
2189
3581
|
};
|
|
2190
3582
|
Object.defineProperty(Cheerio.prototype, "cheerio", { value: "[cheerio object]", writable: true, configurable: true });
|
|
3583
|
+
var inspectCustom = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
3584
|
+
Object.defineProperty(Cheerio.prototype, inspectCustom, {
|
|
3585
|
+
configurable: true,
|
|
3586
|
+
writable: true,
|
|
3587
|
+
value(depth, options, inspect) {
|
|
3588
|
+
const prototype = Object.getPrototypeOf(this);
|
|
3589
|
+
if (depth < 0) return options.stylize(`[${prototype.constructor.name}]`, "special");
|
|
3590
|
+
const shown = Object.create(prototype);
|
|
3591
|
+
Object.defineProperty(shown, inspectCustom, { value: void 0 });
|
|
3592
|
+
for (const key of Object.keys(this)) shown[key] = this[key];
|
|
3593
|
+
return inspect(shown, { ...options, depth });
|
|
3594
|
+
}
|
|
3595
|
+
});
|
|
2191
3596
|
installAttributes(Cheerio);
|
|
2192
3597
|
var nativeExtractionMethods = Object.freeze({
|
|
2193
3598
|
make: Cheerio.prototype._make,
|
|
@@ -2212,12 +3617,12 @@ function nativePrefix(scope, map, keys, key) {
|
|
|
2212
3617
|
const slot = Object.getOwnPropertyDescriptor(map, name);
|
|
2213
3618
|
if (!slot || !slot.enumerable || !("value" in slot)) break;
|
|
2214
3619
|
Object.defineProperty(prefix, name, { value: slot.value, enumerable: true, configurable: true });
|
|
2215
|
-
const
|
|
2216
|
-
if (!
|
|
3620
|
+
const compiled2 = compileExtractPlan(prefix, scope.options);
|
|
3621
|
+
if (!compiled2) {
|
|
2217
3622
|
delete prefix[name];
|
|
2218
3623
|
break;
|
|
2219
3624
|
}
|
|
2220
|
-
plan =
|
|
3625
|
+
plan = compiled2;
|
|
2221
3626
|
count++;
|
|
2222
3627
|
}
|
|
2223
3628
|
if (!plan || !count) return void 0;
|
|
@@ -2245,10 +3650,12 @@ function extract(map) {
|
|
|
2245
3650
|
const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
|
|
2246
3651
|
const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
|
|
2247
3652
|
const selection = this._findBySelector(selector, all ? Infinity : 1);
|
|
3653
|
+
const rows = typeof value === "object" ? nativeRows(this, key, all, selector, value) : void 0;
|
|
2248
3654
|
const read = (index) => {
|
|
2249
3655
|
if (typeof value === "function") return value(selection[index], key, result);
|
|
2250
3656
|
const scope = this._make === nativeExtractionMethods.make ? this._fromIds([selection.ids[index]]) : this._make(selection[index]);
|
|
2251
|
-
|
|
3657
|
+
if (typeof value === "string") return scope.prop(value);
|
|
3658
|
+
return rows ? completeRow(scope, value, rows, index) : scope.extract(value);
|
|
2252
3659
|
};
|
|
2253
3660
|
let extracted;
|
|
2254
3661
|
if (all) {
|
|
@@ -2265,6 +3672,69 @@ function extract(map) {
|
|
|
2265
3672
|
}
|
|
2266
3673
|
return result;
|
|
2267
3674
|
}
|
|
3675
|
+
function nativeRows(scope, key, all, selector, map) {
|
|
3676
|
+
const keys = plainKeys(map);
|
|
3677
|
+
if (!keys || scope._make !== nativeExtractionMethods.make || scope._findBySelector !== nativeExtractionMethods.find || scope.prop !== nativeExtractionMethods.prop || scope.extract !== nativeExtractionMethods.extract) return void 0;
|
|
3678
|
+
const subset = /* @__PURE__ */ Object.create(null);
|
|
3679
|
+
const nativeKeys = /* @__PURE__ */ new Set();
|
|
3680
|
+
for (const name of keys) {
|
|
3681
|
+
const slot = Object.getOwnPropertyDescriptor(map, name);
|
|
3682
|
+
if (!slot || !slot.enumerable || !("value" in slot)) continue;
|
|
3683
|
+
const single = /* @__PURE__ */ Object.create(null);
|
|
3684
|
+
Object.defineProperty(single, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3685
|
+
if (!compileExtractPlan(single, scope.options)) continue;
|
|
3686
|
+
Object.defineProperty(subset, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3687
|
+
nativeKeys.add(name);
|
|
3688
|
+
}
|
|
3689
|
+
if (!nativeKeys.size || nativeKeys.size === keys.length) return void 0;
|
|
3690
|
+
const outer = /* @__PURE__ */ Object.create(null);
|
|
3691
|
+
Object.defineProperty(outer, key, { value: all ? [{ selector, value: subset }] : { selector, value: subset }, enumerable: true, configurable: true });
|
|
3692
|
+
const plan = compileExtractPlan(outer, scope.options);
|
|
3693
|
+
if (!plan) return void 0;
|
|
3694
|
+
const writes = writeCount();
|
|
3695
|
+
const values = scope.op("extractPlan", { ids: scope.ids, plan });
|
|
3696
|
+
hydrateExtractResult(values, plan.entries);
|
|
3697
|
+
const extracted = values[key];
|
|
3698
|
+
const rows = all ? extracted : extracted === void 0 ? [] : [extracted];
|
|
3699
|
+
return Array.isArray(rows) ? { keys: nativeKeys, rows, writes } : void 0;
|
|
3700
|
+
}
|
|
3701
|
+
function completeRow(scope, map, rows, index) {
|
|
3702
|
+
const row = {};
|
|
3703
|
+
const native = rows.rows[index] ?? {};
|
|
3704
|
+
for (const name in map) {
|
|
3705
|
+
if (rows.keys.has(name) && writeCount() === rows.writes) {
|
|
3706
|
+
row[name] = native[name];
|
|
3707
|
+
continue;
|
|
3708
|
+
}
|
|
3709
|
+
const entry = /* @__PURE__ */ Object.create(null);
|
|
3710
|
+
Object.defineProperty(entry, name, { value: map[name], enumerable: true, configurable: true });
|
|
3711
|
+
fillEntries(scope, entry, row);
|
|
3712
|
+
}
|
|
3713
|
+
return row;
|
|
3714
|
+
}
|
|
3715
|
+
function fillEntries(scope, map, result) {
|
|
3716
|
+
for (const key in map) {
|
|
3717
|
+
const entry = map[key];
|
|
3718
|
+
const all = Array.isArray(entry);
|
|
3719
|
+
const descriptor = all ? entry[0] : entry;
|
|
3720
|
+
const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
|
|
3721
|
+
const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
|
|
3722
|
+
const selection = scope._findBySelector(selector, all ? Infinity : 1);
|
|
3723
|
+
const read = (index) => {
|
|
3724
|
+
if (typeof value === "function") return value(selection[index], key, result);
|
|
3725
|
+
const child = scope._make === nativeExtractionMethods.make ? scope._fromIds([selection.ids[index]]) : scope._make(selection[index]);
|
|
3726
|
+
return typeof value === "string" ? child.prop(value) : child.extract(value);
|
|
3727
|
+
};
|
|
3728
|
+
if (all) {
|
|
3729
|
+
const values = [];
|
|
3730
|
+
for (let index = 0; index < selection.length; index += 1) {
|
|
3731
|
+
const extracted = read(index);
|
|
3732
|
+
if (extracted != null) values.push(...Array.isArray(extracted) ? extracted : [extracted]);
|
|
3733
|
+
}
|
|
3734
|
+
result[key] = values;
|
|
3735
|
+
} else result[key] = selection.length ? read(0) : void 0;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
2268
3738
|
|
|
2269
3739
|
// src/index.ts
|
|
2270
3740
|
var import_promises = require("timers/promises");
|
|
@@ -2318,13 +3788,22 @@ function createAPI(document, options, initialRoot = document.rootId()) {
|
|
|
2318
3788
|
class LoadedCheerio extends Cheerio {
|
|
2319
3789
|
}
|
|
2320
3790
|
let api;
|
|
2321
|
-
const
|
|
2322
|
-
if (selector?.cheerio) return selector;
|
|
2323
|
-
const opts = flattenOptions(override, internal);
|
|
2324
|
-
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);
|
|
3791
|
+
const createRoot = (rootIds, opts) => {
|
|
2325
3792
|
const rootInstance = new LoadedCheerio(api, document, rootIds, null, opts);
|
|
2326
3793
|
rootInstance._root = rootInstance;
|
|
3794
|
+
return rootInstance;
|
|
3795
|
+
};
|
|
3796
|
+
const initialize2 = function(selector, context, root, override) {
|
|
3797
|
+
resumeCollection(document);
|
|
3798
|
+
if (selector?.cheerio) {
|
|
3799
|
+
exposeDocumentTo(document, selector[DOCUMENT]);
|
|
3800
|
+
return selector;
|
|
3801
|
+
}
|
|
3802
|
+
const opts = flattenOptions(override, internal);
|
|
3803
|
+
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);
|
|
2327
3804
|
if (!selector) return new LoadedCheerio(api, document, [], rootInstance, opts);
|
|
3805
|
+
const id = viewIdIn(document, selector);
|
|
3806
|
+
if (id !== void 0) return new LoadedCheerio(api, document, [id], rootInstance, opts);
|
|
2328
3807
|
if (typeof selector === "string" && isHtml(selector)) return new LoadedCheerio(api, document, operation(document, "create", { html: selector, options: opts }), rootInstance, opts);
|
|
2329
3808
|
if (typeof selector === "object") {
|
|
2330
3809
|
const values = "length" in selector && !selector.type ? Array.from(selector) : [selector];
|
|
@@ -2343,55 +3822,57 @@ function createAPI(document, options, initialRoot = document.rootId()) {
|
|
|
2343
3822
|
}
|
|
2344
3823
|
return searchContext.find(search);
|
|
2345
3824
|
};
|
|
2346
|
-
api = Object.assign(initialize2, {
|
|
3825
|
+
api = Object.assign(initialize2, staticMethods, {
|
|
2347
3826
|
load,
|
|
2348
|
-
_root:
|
|
3827
|
+
_root: rootNode(document, initialRoot),
|
|
2349
3828
|
_options: internal,
|
|
2350
3829
|
fn: LoadedCheerio.prototype,
|
|
2351
|
-
prototype: LoadedCheerio.prototype
|
|
2352
|
-
root() {
|
|
2353
|
-
return this(this._root);
|
|
2354
|
-
},
|
|
2355
|
-
html(dom2, renderOptions) {
|
|
2356
|
-
if (!this) return "";
|
|
2357
|
-
if (dom2 && typeof dom2 === "object" && !("length" in dom2) && !("type" in dom2)) {
|
|
2358
|
-
renderOptions = dom2;
|
|
2359
|
-
dom2 = void 0;
|
|
2360
|
-
}
|
|
2361
|
-
const nodes = dom2 === void 0 ? [this._root] : this(dom2).toArray();
|
|
2362
|
-
const binding = nodeBinding(this._root);
|
|
2363
|
-
return operation(binding.document, "render", { ids: importNodes(binding.document, nodes), options: flattenOptions(renderOptions, this._options) });
|
|
2364
|
-
},
|
|
2365
|
-
xml(dom2) {
|
|
2366
|
-
const binding = nodeBinding(this._root);
|
|
2367
|
-
return operation(binding.document, "render", { ids: importNodes(binding.document, dom2 === void 0 ? [this._root] : this(dom2).toArray()), options: { ...this._options, xmlMode: true, _useHtmlParser2: true } });
|
|
2368
|
-
},
|
|
2369
|
-
text(elements) {
|
|
2370
|
-
if (!elements && !this) return "";
|
|
2371
|
-
const nodes = elements ?? [this._root];
|
|
2372
|
-
const binding = this ? nodeBinding(this._root) : nodeBinding(nodes[0]);
|
|
2373
|
-
if (binding) return binding.document.text(importNodes(binding.document, nodes));
|
|
2374
|
-
const doc = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
2375
|
-
return doc.text(importNodes(doc, nodes));
|
|
2376
|
-
},
|
|
2377
|
-
parseHTML(data2, context, keepScripts = typeof context === "boolean" ? context : false) {
|
|
2378
|
-
if (!data2 || typeof data2 !== "string") return null;
|
|
2379
|
-
if (typeof context === "boolean") keepScripts = context;
|
|
2380
|
-
const parsed = this.load(data2, this._options, false);
|
|
2381
|
-
if (!keepScripts) parsed("script").remove();
|
|
2382
|
-
return parsed._root.children.slice();
|
|
2383
|
-
},
|
|
2384
|
-
extract(map) {
|
|
2385
|
-
return this.root().extract(map);
|
|
2386
|
-
},
|
|
2387
|
-
contains,
|
|
2388
|
-
merge
|
|
3830
|
+
prototype: LoadedCheerio.prototype
|
|
2389
3831
|
});
|
|
2390
3832
|
return api;
|
|
2391
3833
|
}
|
|
2392
|
-
|
|
3834
|
+
var staticMethods = {
|
|
3835
|
+
root() {
|
|
3836
|
+
return this(this._root);
|
|
3837
|
+
},
|
|
3838
|
+
html(dom2, renderOptions) {
|
|
3839
|
+
if (!this) return "";
|
|
3840
|
+
if (dom2 && typeof dom2 === "object" && !("length" in dom2) && !("type" in dom2)) {
|
|
3841
|
+
renderOptions = dom2;
|
|
3842
|
+
dom2 = void 0;
|
|
3843
|
+
}
|
|
3844
|
+
const nodes = dom2 === void 0 ? [this._root] : this(dom2).toArray();
|
|
3845
|
+
const binding = nodeBinding(this._root);
|
|
3846
|
+
return operation(binding.document, "render", { ids: importNodes(binding.document, nodes), options: flattenOptions(renderOptions, this._options) });
|
|
3847
|
+
},
|
|
3848
|
+
xml(dom2) {
|
|
3849
|
+
const binding = nodeBinding(this._root);
|
|
3850
|
+
return operation(binding.document, "render", { ids: importNodes(binding.document, dom2 === void 0 ? [this._root] : this(dom2).toArray()), options: { ...this._options, xmlMode: true, _useHtmlParser2: true } });
|
|
3851
|
+
},
|
|
3852
|
+
text(elements) {
|
|
3853
|
+
if (!elements && !this) return "";
|
|
3854
|
+
const nodes = elements ?? [this._root];
|
|
3855
|
+
const binding = this ? nodeBinding(this._root) : nodeBinding(nodes[0]);
|
|
3856
|
+
if (binding) return binding.document.text(importNodes(binding.document, nodes));
|
|
3857
|
+
const doc = routeDocument(new (requireNative()).NativeDocument("", false));
|
|
3858
|
+
return doc.text(importNodes(doc, nodes));
|
|
3859
|
+
},
|
|
3860
|
+
parseHTML(data2, context, keepScripts = typeof context === "boolean" ? context : false) {
|
|
3861
|
+
if (!data2 || typeof data2 !== "string") return null;
|
|
3862
|
+
if (typeof context === "boolean") keepScripts = context;
|
|
3863
|
+
const parsed = this.load(data2, this._options, false);
|
|
3864
|
+
if (!keepScripts) parsed("script").remove();
|
|
3865
|
+
return parsed._root.children.slice();
|
|
3866
|
+
},
|
|
3867
|
+
extract(map) {
|
|
3868
|
+
return this.root().extract(map);
|
|
3869
|
+
},
|
|
3870
|
+
contains,
|
|
3871
|
+
merge
|
|
3872
|
+
};
|
|
3873
|
+
function makeRoot(document, children) {
|
|
2393
3874
|
const id = operation(document, "createNode", { type: "root" });
|
|
2394
|
-
operation(document, "setNode", { id, field: "children", value:
|
|
3875
|
+
operation(document, "setNode", { id, field: "children", value: children });
|
|
2395
3876
|
return id;
|
|
2396
3877
|
}
|
|
2397
3878
|
function load(content, options, isDocument2 = true) {
|