capybara-simulated 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3681,7 +3681,7 @@
3681
3681
  ]);
3682
3682
  var P_SCOPE_BOUNDARY = /* @__PURE__ */ new Set(["applet", "caption", "html", "table", "td", "th", "marquee", "object", "template", "button"]);
3683
3683
  var DOCTYPE_RE = /^\s*<!doctype\s+([^\s>]+)(?:\s+(?:public\s+("[^"]*"|'[^']*')(?:\s+("[^"]*"|'[^']*'))?|system\s+("[^"]*"|'[^']*')))?[^>]*>/i;
3684
- function installHtmlParser({ Document: Document2, Element: Element2, Text: Text2, Comment: Comment2, DocumentFragment: DocumentFragment2, DocumentType: DocumentType2 }) {
3684
+ function installHtmlParser({ Document: Document2, Element: Element2, Text: Text2, Comment: Comment2, DocumentFragment: DocumentFragment2, DocumentType: DocumentType2, createHtmlPageDocument: createHtmlPageDocument2 }) {
3685
3685
  const unquote = /* @__PURE__ */ __name((s) => s == null ? "" : s.slice(1, -1), "unquote");
3686
3686
  const HTML_NS_P = "http://www.w3.org/1999/xhtml";
3687
3687
  const SVG_NS_P = "http://www.w3.org/2000/svg";
@@ -3690,7 +3690,7 @@
3690
3690
  const XML_NS_P = "http://www.w3.org/XML/1998/namespace";
3691
3691
  const XMLNS_NS_P = "http://www.w3.org/2000/xmlns/";
3692
3692
  function parseDocument2(html) {
3693
- const doc = new Document2();
3693
+ const doc = createHtmlPageDocument2(false);
3694
3694
  const dt = DocumentType2 && DOCTYPE_RE.exec(html);
3695
3695
  if (dt) {
3696
3696
  const node = new DocumentType2(dt[1], unquote(dt[2]), unquote(dt[3] || dt[4]), doc);
@@ -3698,7 +3698,6 @@
3698
3698
  doc._children.push(node);
3699
3699
  }
3700
3700
  const root = new Element2("html");
3701
- doc.documentElement = root;
3702
3701
  root._parent = doc;
3703
3702
  doc._children.push(root);
3704
3703
  const head = new Element2("head");
@@ -7071,9 +7070,13 @@
7071
7070
  this.nodeType = NODE_ELEMENT;
7072
7071
  this._ownerDoc = null;
7073
7072
  }
7074
- getRootNode(_options) {
7073
+ getRootNode(options) {
7074
+ const composed = !!(options && options.composed);
7075
7075
  let cur = this;
7076
- while (cur._parent) cur = cur._parent;
7076
+ while (cur._parent) {
7077
+ if (!composed && cur._isShadowRoot) break;
7078
+ cur = cur._parent;
7079
+ }
7077
7080
  return cur;
7078
7081
  }
7079
7082
  // Per DOM, `nodeValue` is null for every node type except Attr (its value)
@@ -7430,7 +7433,6 @@
7430
7433
  copy._children.push(cc);
7431
7434
  }
7432
7435
  if (copy.nodeType === NODE_DOC) {
7433
- copy.documentElement = copy._children.find((c) => c.nodeType === NODE_ELEMENT) || null;
7434
7436
  for (const c of copy._children) walkSubtree(c, (n) => {
7435
7437
  n._ownerDoc = copy;
7436
7438
  });
@@ -7846,6 +7848,7 @@
7846
7848
  const prevSib = idx > 0 ? this._children[idx - 1] : null;
7847
7849
  const nextSib = idx < this._children.length ? this._children[idx] : null;
7848
7850
  this._children.splice(idx, 0, ...moved);
7851
+ liveRangesOnInsert(this, idx, moved.length);
7849
7852
  const connected = isConnected(this);
7850
7853
  for (const c of moved) {
7851
7854
  c._parent = this;
@@ -7868,9 +7871,11 @@
7868
7871
  const prevSib = i > 0 ? this._children[i - 1] : null;
7869
7872
  const nextSib = i + 1 < this._children.length ? this._children[i + 1] : null;
7870
7873
  for (const c of nodes) adoptIntoParent(this, c);
7874
+ liveRangesOnRemove(this, old, i);
7871
7875
  old._parent = null;
7872
7876
  unregisterSubtree(old);
7873
7877
  this._children.splice(i, 1, ...nodes);
7878
+ liveRangesOnInsert(this, i, nodes.length);
7874
7879
  for (const c of nodes) {
7875
7880
  c._parent = this;
7876
7881
  registerSubtree(c);
@@ -7888,7 +7893,9 @@
7888
7893
  if (child && child.nodeType === NODE_FRAGMENT) return this._insertFragmentChildren(child, null);
7889
7894
  adoptIntoParent(this, child);
7890
7895
  child._parent = this;
7896
+ const insertIndex = this._children.length;
7891
7897
  this._children.push(child);
7898
+ liveRangesOnInsert(this, insertIndex, 1);
7892
7899
  registerSubtree(child);
7893
7900
  recordChildList(this, [child], []);
7894
7901
  if (isConnected(this)) globalThis.__csimFireCEConnect(child);
@@ -7908,6 +7915,8 @@
7908
7915
  const prevSib = i > 0 ? this._children[i - 1] : null;
7909
7916
  const nextSib = i + 1 < this._children.length ? this._children[i + 1] : null;
7910
7917
  const wasConnected = isConnected(this);
7918
+ nodeIteratorPreRemove(child);
7919
+ liveRangesOnRemove(this, child, i);
7911
7920
  this._children.splice(i, 1);
7912
7921
  child._parent = null;
7913
7922
  unregisterSubtree(child);
@@ -7930,6 +7939,7 @@
7930
7939
  if (i < 0) return this.appendChild(child);
7931
7940
  child._parent = this;
7932
7941
  this._children.splice(i, 0, child);
7942
+ liveRangesOnInsert(this, i, 1);
7933
7943
  registerSubtree(child);
7934
7944
  recordChildList(this, [child], []);
7935
7945
  if (isConnected(this)) globalThis.__csimFireCEConnect(child);
@@ -7959,9 +7969,11 @@
7959
7969
  const wasConnected = isConnected(this);
7960
7970
  adoptIntoParent(this, neu);
7961
7971
  const j = this._children.indexOf(old);
7972
+ liveRangesOnRemove(this, old, j);
7962
7973
  neu._parent = this;
7963
7974
  old._parent = null;
7964
7975
  this._children[j] = neu;
7976
+ liveRangesOnInsert(this, j, 1);
7965
7977
  unregisterSubtree(old);
7966
7978
  registerSubtree(neu);
7967
7979
  recordChildList(this, [neu], [old]);
@@ -8056,6 +8068,7 @@
8056
8068
  }
8057
8069
  _setData(next) {
8058
8070
  const prev = this._data;
8071
+ liveRangesOnReplaceData(this, 0, prev.length, next.length);
8059
8072
  if (prev === next) return;
8060
8073
  this._data = next;
8061
8074
  recordCharacterData(this, prev);
@@ -8118,7 +8131,9 @@
8118
8131
  const len = prev.length;
8119
8132
  if (offset > len) throw new globalThis.DOMException("The offset is greater than the data length.", "IndexSizeError");
8120
8133
  if (offset + count > len) count = len - offset;
8121
- this._data = prev.slice(0, offset) + String(data) + prev.slice(offset + count);
8134
+ const str = String(data);
8135
+ liveRangesOnReplaceData(this, offset, count, str.length);
8136
+ this._data = prev.slice(0, offset) + str + prev.slice(offset + count);
8122
8137
  recordCharacterData(this, prev);
8123
8138
  }
8124
8139
  };
@@ -8146,19 +8161,24 @@
8146
8161
  // install chain on that template (including `{{on "click"}}` on
8147
8162
  // search-result anchors).
8148
8163
  splitText(offset) {
8164
+ offset = offset >>> 0;
8149
8165
  const len = this._data.length;
8150
- if (offset < 0 || offset > len) {
8166
+ if (offset > len) {
8151
8167
  throw new globalThis.DOMException("Index or size is negative or greater than the allowed amount", "IndexSizeError");
8152
8168
  }
8153
- const suffix = this._data.substring(offset);
8154
- const newNode = new this.constructor(suffix);
8169
+ const count = len - offset;
8170
+ const newNode = new this.constructor(this._data.substring(offset));
8155
8171
  newNode._ownerDoc = this._ownerDoc;
8156
- if (this._parent) {
8157
- const idx = this._parent._children.indexOf(this);
8158
- this._parent._children.splice(idx + 1, 0, newNode);
8159
- newNode._parent = this._parent;
8172
+ const parent = this._parent;
8173
+ if (parent) {
8174
+ const idx = parent._children.indexOf(this);
8175
+ parent._children.splice(idx + 1, 0, newNode);
8176
+ newNode._parent = parent;
8177
+ registerSubtree(newNode);
8178
+ recordChildList(parent, [newNode], []);
8179
+ liveRangesOnSplit(this, offset, newNode, parent, idx);
8160
8180
  }
8161
- this.data = this._data.substring(0, offset);
8181
+ this._replaceData(offset, count, "");
8162
8182
  return newNode;
8163
8183
  }
8164
8184
  // DOM `Text.wholeText`: the concatenated data of this node and its contiguous
@@ -8473,6 +8493,7 @@
8473
8493
  e._ns = this._ns;
8474
8494
  e._prefix = this._prefix;
8475
8495
  e._localName = this._localName;
8496
+ if (this._tag === "script" && this._csimRan) e._csimRan = true;
8476
8497
  return e;
8477
8498
  }
8478
8499
  // tagName / nodeName: the qualified name, ASCII-uppercased only for an
@@ -10847,7 +10868,95 @@
10847
10868
  for (const __h of GLOBAL_EVENT_HANDLER_ATTRS) {
10848
10869
  if (!(__h in Element.prototype)) Element.prototype[__h] = null;
10849
10870
  }
10850
- var Document = class _Document extends Node {
10871
+ var DOMImplementation = class {
10872
+ static {
10873
+ __name(this, "DOMImplementation");
10874
+ }
10875
+ constructor(doc) {
10876
+ this._doc = doc;
10877
+ }
10878
+ // Legacy: `hasFeature` always returns true (DOM §4.5.1).
10879
+ hasFeature() {
10880
+ return true;
10881
+ }
10882
+ // `createHTMLDocument(title)` — DOMParser shims and Turbo Drive's page-
10883
+ // snapshot logic both probe it. Returns a fresh Document with a minimal
10884
+ // `<!DOCTYPE html><html><head><title>X</title></head><body></body></html>`
10885
+ // skeleton; full HTML-spec construction (quirks-mode flag) is out of scope.
10886
+ createHTMLDocument(...args) {
10887
+ const d = new Document();
10888
+ const doctype = new DocumentType("html", "", "", d);
10889
+ doctype._parent = d;
10890
+ const html = new Element("html");
10891
+ const head = new Element("head");
10892
+ const body = new Element("body");
10893
+ html._children = newChildList([head, body]);
10894
+ head._parent = html;
10895
+ body._parent = html;
10896
+ html._parent = d;
10897
+ d._children = newChildList([doctype, html]);
10898
+ if (args.length > 0 && args[0] !== void 0) {
10899
+ const t = new Element("title");
10900
+ t._children = newChildList([Object.assign(new Text(String(args[0])), { _parent: t })]);
10901
+ t._parent = head;
10902
+ head._children.push(t);
10903
+ }
10904
+ d._contentType = "text/html";
10905
+ walkSubtree(d, (n) => {
10906
+ n._ownerDoc = d;
10907
+ });
10908
+ return d;
10909
+ }
10910
+ // createDocumentType(qualifiedName, publicId, systemId) — modern spec
10911
+ // validates only the name (a "valid doctype name"); no namespace checks.
10912
+ createDocumentType(qualifiedName, publicId, systemId) {
10913
+ const name = String(qualifiedName);
10914
+ if (!isValidDoctypeName(name)) {
10915
+ throw new globalThis.DOMException(
10916
+ `The qualified name '${name}' is not a valid doctype name.`,
10917
+ "InvalidCharacterError"
10918
+ );
10919
+ }
10920
+ return new DocumentType(name, publicId, systemId, this._doc);
10921
+ }
10922
+ // createDocument(namespace, qualifiedName, doctype) — a fresh XMLDocument with
10923
+ // an optional root element (from the validated qualifiedName) and an optional
10924
+ // doctype, in [doctype?, element?] order.
10925
+ createDocument(...args) {
10926
+ if (args.length < 2) {
10927
+ throw new TypeError("Failed to execute 'createDocument': 2 arguments required.");
10928
+ }
10929
+ const namespace = args[0], qualifiedName = args[1], doctype = args[2];
10930
+ if (doctype != null && !(doctype instanceof DocumentType)) {
10931
+ throw new TypeError("Failed to execute 'createDocument': parameter 3 is not of type 'DocumentType'.");
10932
+ }
10933
+ const ns = namespace == null || namespace === "" ? null : String(namespace);
10934
+ const qn = qualifiedName === null ? "" : String(qualifiedName);
10935
+ let rns = null, prefix = null, localName = null;
10936
+ if (qn !== "") ({ namespace: rns, prefix, localName } = validateAndExtract(ns, qn, "element"));
10937
+ const d = new XMLDocument();
10938
+ d._contentType = ns === HTML_NS3 ? "application/xhtml+xml" : ns === SVG_NS2 ? "image/svg+xml" : "application/xml";
10939
+ d._children = newChildList();
10940
+ d.readyState = "complete";
10941
+ if (doctype != null) {
10942
+ if (doctype._parent) {
10943
+ const i = doctype._parent._children.indexOf(doctype);
10944
+ if (i >= 0) doctype._parent._children.splice(i, 1);
10945
+ }
10946
+ doctype._parent = d;
10947
+ doctype._ownerDoc = d;
10948
+ d._children.push(doctype);
10949
+ }
10950
+ if (qn !== "") {
10951
+ const el = d._createElement(rns, prefix, localName);
10952
+ el._parent = d;
10953
+ d._children.push(el);
10954
+ }
10955
+ return d;
10956
+ }
10957
+ };
10958
+ globalThis.DOMImplementation = DOMImplementation;
10959
+ var Document = class extends Node {
10851
10960
  static {
10852
10961
  __name(this, "Document");
10853
10962
  }
@@ -10962,27 +11071,37 @@
10962
11071
  constructor() {
10963
11072
  super();
10964
11073
  this.nodeType = NODE_DOC;
10965
- this.readyState = "loading";
10966
- const html = new Element("html");
10967
- const head = new Element("head");
10968
- const body = new Element("body");
10969
- html._parent = this;
10970
- this._children.push(html);
10971
- head._parent = html;
10972
- html._children.push(head);
10973
- body._parent = html;
10974
- html._children.push(body);
10975
- this.documentElement = html;
11074
+ this.readyState = "complete";
11075
+ this._contentType = "application/xml";
11076
+ this._url = "about:blank";
11077
+ this._noBrowsingContext = true;
10976
11078
  for (const name of GLOBAL_EVENT_HANDLER_ATTRS) this[name] = null;
10977
11079
  }
11080
+ // The document element is the document's (single) element child — derived
11081
+ // from the tree rather than maintained as a field, so it stays correct after
11082
+ // any insert / remove (e.g. `new Document().appendChild(html)`), not just the
11083
+ // explicit parser / graft paths. A Document's child list is tiny (an optional
11084
+ // doctype + the root), so the scan is effectively free; the manual loop
11085
+ // avoids a per-access closure allocation on this hot getter.
11086
+ get documentElement() {
11087
+ const kids = this._children;
11088
+ for (let i = 0; i < kids.length; i++) {
11089
+ if (kids[i].nodeType === NODE_ELEMENT) return kids[i];
11090
+ }
11091
+ return null;
11092
+ }
10978
11093
  // jQuery's `mc(node)` helper resolves a node back to its window
10979
11094
  // via `doc.defaultView || doc.parentWindow`; without these the
10980
11095
  // offset / scroll path throws "Cannot read properties of
10981
11096
  // undefined (reading 'pageYOffset')".
10982
11097
  // The main document's window is the global; a nested (iframe) document
10983
11098
  // carries its own `_defaultView` (a frame-window proxy) set at load time.
11099
+ // A document with no browsing context (`new Document()`, createHTMLDocument,
11100
+ // createDocument) has no associated window — `defaultView` is null (DOM
11101
+ // §4.5.1). Returning the global here would splice the live window (and its
11102
+ // document) into a detached document's event path, cycling it unbounded.
10984
11103
  get defaultView() {
10985
- return this._defaultView || globalThis;
11104
+ return this._noBrowsingContext ? null : this._defaultView || globalThis;
10986
11105
  }
10987
11106
  get parentWindow() {
10988
11107
  return this.defaultView;
@@ -11003,15 +11122,14 @@
11003
11122
  return null;
11004
11123
  }
11005
11124
  // Cloning a Document yields a new EMPTY document of the same kind, carrying
11006
- // the content type — children are copied only on a deep clone (cloneNode
11007
- // handles that + sets documentElement). The base shell would re-run the
11008
- // constructor's html/head/body skeleton, leaving a shallow clone non-empty.
11125
+ // the content type and browsing-context-ness — children are copied only on a
11126
+ // deep clone (cloneNode handles that + sets documentElement).
11009
11127
  _cloneShell() {
11010
11128
  const d = new this.constructor();
11011
11129
  d._children = newChildList();
11012
- d.documentElement = null;
11013
11130
  d._contentType = this._contentType;
11014
- if (this._url) d._url = this._url;
11131
+ d._noBrowsingContext = this._noBrowsingContext;
11132
+ d._url = this._url;
11015
11133
  d.readyState = "complete";
11016
11134
  return d;
11017
11135
  }
@@ -11019,8 +11137,10 @@
11019
11137
  // searchParams.js reads `document.location.search`; without this
11020
11138
  // getter the call hits `undefined.search` and the whole bundle's
11021
11139
  // top-level module init aborts before the search-feed fetch fires.
11140
+ // A document with no browsing context (createHTMLDocument) has `location`
11141
+ // null; the main / frame documents return the live location object.
11022
11142
  get location() {
11023
- return globalThis.location;
11143
+ return this._noBrowsingContext ? null : globalThis.location;
11024
11144
  }
11025
11145
  set location(v) {
11026
11146
  globalThis.__locationAssign(String(v));
@@ -11257,7 +11377,9 @@
11257
11377
  // the live tree via `appendChild`. We give it just enough surface
11258
11378
  // for `appendChild` / `childNodes` to work.
11259
11379
  createDocumentFragment() {
11260
- return new DocumentFragment();
11380
+ const f = new DocumentFragment();
11381
+ f._ownerDoc = this;
11382
+ return f;
11261
11383
  }
11262
11384
  // `Document.createEvent(interfaceName)` — legacy DOM Level 2 API
11263
11385
  // still used by libraries that target older browsers (Trix's
@@ -11307,95 +11429,19 @@
11307
11429
  });
11308
11430
  return node;
11309
11431
  }
11310
- // `document.implementation.createHTMLDocument(title)` — DOMParser
11311
- // shims and Turbo Drive page-snapshot logic both probe it. We
11312
- // return a fresh Document with a minimal `<html><head><title>X</title>
11313
- // </head><body></body></html>` skeleton; full HTML-spec
11314
- // construction (DOCTYPE / quirks-mode flag) is out of scope.
11432
+ // `document.implementation` — a per-document, cached `DOMImplementation`
11433
+ // (createHTMLDocument / createDocument / createDocumentType / hasFeature).
11434
+ // Cached so repeated reads return the same instance, and a real class so
11435
+ // `instanceof DOMImplementation` holds.
11315
11436
  get implementation() {
11316
- return {
11317
- createHTMLDocument: /* @__PURE__ */ __name((...args) => {
11318
- const d = new _Document();
11319
- const doctype = new DocumentType("html", "", "", d);
11320
- doctype._parent = d;
11321
- const html = new Element("html");
11322
- const head = new Element("head");
11323
- const body = new Element("body");
11324
- html._children = newChildList([head, body]);
11325
- head._parent = html;
11326
- body._parent = html;
11327
- d.documentElement = html;
11328
- html._parent = d;
11329
- d._children = newChildList([doctype, html]);
11330
- if (args.length > 0 && args[0] !== void 0) {
11331
- const t = new Element("title");
11332
- t._children = newChildList([Object.assign(new Text(String(args[0])), { _parent: t })]);
11333
- t._parent = head;
11334
- head._children.push(t);
11335
- }
11336
- walkSubtree(d, (n) => {
11337
- n._ownerDoc = d;
11338
- });
11339
- return d;
11340
- }, "createHTMLDocument"),
11341
- // createDocumentType(qualifiedName, publicId, systemId) — modern spec
11342
- // validates only the name (a "valid doctype name"); no namespace checks.
11343
- createDocumentType: /* @__PURE__ */ __name((qualifiedName, publicId, systemId) => {
11344
- const name = String(qualifiedName);
11345
- if (!isValidDoctypeName(name)) {
11346
- throw new globalThis.DOMException(
11347
- `The qualified name '${name}' is not a valid doctype name.`,
11348
- "InvalidCharacterError"
11349
- );
11350
- }
11351
- return new DocumentType(name, publicId, systemId, this);
11352
- }, "createDocumentType"),
11353
- // createDocument(namespace, qualifiedName, doctype) — a fresh XMLDocument
11354
- // with an optional root element (from the validated qualifiedName) and an
11355
- // optional doctype, in [doctype?, element?] order.
11356
- createDocument: /* @__PURE__ */ __name((...args) => {
11357
- if (args.length < 2) {
11358
- throw new TypeError("Failed to execute 'createDocument': 2 arguments required.");
11359
- }
11360
- const namespace = args[0], qualifiedName = args[1], doctype = args[2];
11361
- if (doctype != null && !(doctype instanceof DocumentType)) {
11362
- throw new TypeError("Failed to execute 'createDocument': parameter 3 is not of type 'DocumentType'.");
11363
- }
11364
- const ns = namespace == null || namespace === "" ? null : String(namespace);
11365
- const qn = qualifiedName === null ? "" : String(qualifiedName);
11366
- let rns = null, prefix = null, localName = null;
11367
- if (qn !== "") ({ namespace: rns, prefix, localName } = validateAndExtract(ns, qn, "element"));
11368
- const d = new XMLDocument();
11369
- d._contentType = ns === HTML_NS3 ? "application/xhtml+xml" : ns === SVG_NS2 ? "image/svg+xml" : "application/xml";
11370
- d._children = newChildList();
11371
- d.documentElement = null;
11372
- d.readyState = "complete";
11373
- if (doctype != null) {
11374
- if (doctype._parent) {
11375
- const i = doctype._parent._children.indexOf(doctype);
11376
- if (i >= 0) doctype._parent._children.splice(i, 1);
11377
- }
11378
- doctype._parent = d;
11379
- doctype._ownerDoc = d;
11380
- d._children.push(doctype);
11381
- }
11382
- if (qn !== "") {
11383
- const el = d._createElement(rns, prefix, localName);
11384
- el._parent = d;
11385
- d._children.push(el);
11386
- d.documentElement = el;
11387
- }
11388
- return d;
11389
- }, "createDocument"),
11390
- hasFeature: /* @__PURE__ */ __name(() => true, "hasFeature")
11391
- };
11437
+ return this._implementation || (this._implementation = new DOMImplementation(this));
11392
11438
  }
11393
11439
  // Minimal Range stub for `document.createRange()`. We don't model
11394
11440
  // partial-range selection (start/end offsets on text nodes etc.);
11395
11441
  // only document-order comparison between two nodes' start containers
11396
11442
  // via `compareBoundaryPoints`, which is all the consumers here drive.
11397
11443
  createRange() {
11398
- return new DocumentOrderRange();
11444
+ return new DocumentOrderRange(this);
11399
11445
  }
11400
11446
  // Minimal NodeIterator. DOMPurify is the canonical consumer —
11401
11447
  // it walks a freshly-parsed sanitisation fragment via
@@ -11404,49 +11450,58 @@
11404
11450
  // DOMPurify operates on small per-call fragments so the up-front
11405
11451
  // walk is cheaper than the per-step sibling/ancestor traversal.
11406
11452
  createNodeIterator(root, whatToShow, filter) {
11407
- if (whatToShow == null) whatToShow = 4294967295;
11408
- const all = [];
11409
- walkSubtree(root, (n) => all.push(n));
11453
+ if (!isNodeArg(root)) {
11454
+ throw new TypeError("Failed to execute 'createNodeIterator': parameter 1 is not of type 'Node'.");
11455
+ }
11456
+ whatToShow = whatToShow === void 0 ? 4294967295 : whatToShow >>> 0;
11457
+ if (filter === void 0) filter = null;
11458
+ const state2 = { node: root, before: true, active: false };
11410
11459
  const accept = /* @__PURE__ */ __name((n) => {
11411
- const mask = 1 << n.nodeType - 1;
11412
- if (!(mask & whatToShow)) return 3;
11460
+ if (!(1 << n.nodeType - 1 & whatToShow)) return 3;
11413
11461
  if (filter) {
11414
11462
  const fn = typeof filter === "function" ? filter : filter && filter.acceptNode;
11415
11463
  if (fn) {
11416
- const r = fn.call(filter || null, n);
11464
+ if (state2.active) {
11465
+ throw new globalThis.DOMException("Failed to execute 'nextNode' on 'NodeIterator': the iterator's filter is already active.", "InvalidStateError");
11466
+ }
11467
+ state2.active = true;
11468
+ let r;
11469
+ try {
11470
+ r = fn.call(filter || null, n);
11471
+ } finally {
11472
+ state2.active = false;
11473
+ }
11417
11474
  if (r === 2 || r === 3 || r === false) return 3;
11418
11475
  }
11419
11476
  }
11420
11477
  return 1;
11421
11478
  }, "accept");
11422
- let i = -1;
11423
- return {
11424
- root,
11425
- whatToShow,
11426
- filter,
11427
- referenceNode: root,
11428
- pointerBeforeReferenceNode: true,
11479
+ const it = {
11429
11480
  nextNode() {
11430
- while (++i < all.length) {
11431
- if (accept(all[i]) !== 1) continue;
11432
- this.referenceNode = all[i];
11433
- this.pointerBeforeReferenceNode = false;
11434
- return all[i];
11435
- }
11436
- return null;
11481
+ return nodeIteratorTraverse(this, true);
11437
11482
  },
11438
11483
  previousNode() {
11439
- while (--i >= 0) {
11440
- if (accept(all[i]) !== 1) continue;
11441
- this.referenceNode = all[i];
11442
- this.pointerBeforeReferenceNode = false;
11443
- return all[i];
11444
- }
11445
- return null;
11484
+ return nodeIteratorTraverse(this, false);
11446
11485
  },
11447
11486
  detach() {
11448
11487
  }
11449
11488
  };
11489
+ Object.defineProperties(it, {
11490
+ _state: { value: state2, writable: false, enumerable: false },
11491
+ _accept: { value: accept, writable: false, enumerable: false },
11492
+ root: { value: root, enumerable: true },
11493
+ whatToShow: { value: whatToShow, enumerable: true },
11494
+ filter: { value: filter, enumerable: true },
11495
+ referenceNode: { get() {
11496
+ return state2.node;
11497
+ }, enumerable: true },
11498
+ pointerBeforeReferenceNode: { get() {
11499
+ return state2.before;
11500
+ }, enumerable: true },
11501
+ [Symbol.toStringTag]: { value: "NodeIterator" }
11502
+ });
11503
+ LIVE_NODE_ITERATORS.add(it);
11504
+ return it;
11450
11505
  }
11451
11506
  // `Document.createTreeWalker(root, whatToShow, filter)` — Trix
11452
11507
  // builds one to traverse the editable subtree by nodeType (its
@@ -11892,65 +11947,299 @@
11892
11947
  // no browsing context; documentURI follows via this.URL
11893
11948
  };
11894
11949
  globalThis.XMLDocument = XMLDocument;
11950
+ function createHtmlPageDocument(withSkeleton) {
11951
+ const doc = new Document();
11952
+ doc._contentType = void 0;
11953
+ doc._url = void 0;
11954
+ doc._noBrowsingContext = false;
11955
+ doc.readyState = "loading";
11956
+ if (withSkeleton) {
11957
+ const html = new Element("html");
11958
+ const head = new Element("head");
11959
+ const body = new Element("body");
11960
+ html._parent = doc;
11961
+ doc._children.push(html);
11962
+ head._parent = html;
11963
+ html._children.push(head);
11964
+ body._parent = html;
11965
+ html._children.push(body);
11966
+ }
11967
+ return doc;
11968
+ }
11969
+ __name(createHtmlPageDocument, "createHtmlPageDocument");
11970
+ function rangesFor(node) {
11971
+ const d = node && (node.nodeType === NODE_DOC ? node : node.ownerDocument);
11972
+ return d ? d._liveRanges : null;
11973
+ }
11974
+ __name(rangesFor, "rangesFor");
11975
+ function liveRangesOnInsert(parent, index, count) {
11976
+ const reg = rangesFor(parent);
11977
+ if (!reg || reg.size === 0) return;
11978
+ for (const r of reg) {
11979
+ if (r.startContainer === parent && r.startOffset > index) r.startOffset += count;
11980
+ if (r.endContainer === parent && r.endOffset > index) r.endOffset += count;
11981
+ }
11982
+ }
11983
+ __name(liveRangesOnInsert, "liveRangesOnInsert");
11984
+ function sameTreeContains(ancestor, descendant) {
11985
+ for (let n = descendant; n; n = n._parent) {
11986
+ if (n === ancestor) return true;
11987
+ if (n._isShadowRoot) return false;
11988
+ }
11989
+ return false;
11990
+ }
11991
+ __name(sameTreeContains, "sameTreeContains");
11992
+ function liveRangesOnRemove(oldParent, node, index) {
11993
+ const reg = rangesFor(oldParent);
11994
+ if (!reg || reg.size === 0) return;
11995
+ for (const r of reg) {
11996
+ if (sameTreeContains(node, r.startContainer)) {
11997
+ r.startContainer = oldParent;
11998
+ r.startOffset = index;
11999
+ }
12000
+ if (sameTreeContains(node, r.endContainer)) {
12001
+ r.endContainer = oldParent;
12002
+ r.endOffset = index;
12003
+ }
12004
+ if (r.startContainer === oldParent && r.startOffset > index) r.startOffset -= 1;
12005
+ if (r.endContainer === oldParent && r.endOffset > index) r.endOffset -= 1;
12006
+ }
12007
+ }
12008
+ __name(liveRangesOnRemove, "liveRangesOnRemove");
12009
+ function liveRangesOnReplaceData(node, offset, count, dataLen) {
12010
+ const reg = rangesFor(node);
12011
+ if (!reg || reg.size === 0) return;
12012
+ const delta = dataLen - count;
12013
+ for (const r of reg) {
12014
+ if (r.startContainer === node) {
12015
+ if (r.startOffset > offset && r.startOffset <= offset + count) r.startOffset = offset;
12016
+ else if (r.startOffset > offset + count) r.startOffset += delta;
12017
+ }
12018
+ if (r.endContainer === node) {
12019
+ if (r.endOffset > offset && r.endOffset <= offset + count) r.endOffset = offset;
12020
+ else if (r.endOffset > offset + count) r.endOffset += delta;
12021
+ }
12022
+ }
12023
+ }
12024
+ __name(liveRangesOnReplaceData, "liveRangesOnReplaceData");
12025
+ function liveRangesOnSplit(node, offset, newNode, parent, nodeIndex) {
12026
+ const reg = rangesFor(node);
12027
+ if (!reg || reg.size === 0) return;
12028
+ for (const r of reg) {
12029
+ if (r.startContainer === node && r.startOffset > offset) {
12030
+ r.startContainer = newNode;
12031
+ r.startOffset -= offset;
12032
+ }
12033
+ if (r.endContainer === node && r.endOffset > offset) {
12034
+ r.endContainer = newNode;
12035
+ r.endOffset -= offset;
12036
+ }
12037
+ if (parent) {
12038
+ if (r.startContainer === parent && r.startOffset === nodeIndex + 1) r.startOffset += 1;
12039
+ if (r.endContainer === parent && r.endOffset === nodeIndex + 1) r.endOffset += 1;
12040
+ }
12041
+ }
12042
+ }
12043
+ __name(liveRangesOnSplit, "liveRangesOnSplit");
12044
+ var LIVE_NODE_ITERATORS = /* @__PURE__ */ new Set();
12045
+ function followingSkippingSubtree(node, root) {
12046
+ for (let cur = node; cur && cur !== root; cur = cur._parent) {
12047
+ const p = cur._parent;
12048
+ if (p) {
12049
+ const sibs = p._children, i = sibs.indexOf(cur);
12050
+ if (i >= 0 && i + 1 < sibs.length) return sibs[i + 1];
12051
+ }
12052
+ }
12053
+ return null;
12054
+ }
12055
+ __name(followingSkippingSubtree, "followingSkippingSubtree");
12056
+ function followingWithinRoot(node, root) {
12057
+ if (node._children && node._children.length) return node._children[0];
12058
+ return followingSkippingSubtree(node, root);
12059
+ }
12060
+ __name(followingWithinRoot, "followingWithinRoot");
12061
+ function precedingWithinRoot(node, root) {
12062
+ if (node === root || !node._parent) return null;
12063
+ const sibs = node._parent._children, i = sibs.indexOf(node);
12064
+ if (i > 0) {
12065
+ let n = sibs[i - 1];
12066
+ while (n._children && n._children.length) n = n._children[n._children.length - 1];
12067
+ return n;
12068
+ }
12069
+ return node._parent;
12070
+ }
12071
+ __name(precedingWithinRoot, "precedingWithinRoot");
12072
+ function nodeIteratorTraverse(it, forward) {
12073
+ let node = it._state.node;
12074
+ let before = it._state.before;
12075
+ while (true) {
12076
+ if (forward) {
12077
+ if (!before) {
12078
+ const n = followingWithinRoot(node, it.root);
12079
+ if (!n) return null;
12080
+ node = n;
12081
+ } else before = false;
12082
+ } else {
12083
+ if (before) {
12084
+ const n = precedingWithinRoot(node, it.root);
12085
+ if (!n) return null;
12086
+ node = n;
12087
+ } else before = true;
12088
+ }
12089
+ if (it._accept(node) === 1) break;
12090
+ }
12091
+ it._state.node = node;
12092
+ it._state.before = before;
12093
+ return node;
12094
+ }
12095
+ __name(nodeIteratorTraverse, "nodeIteratorTraverse");
12096
+ function nodeIteratorPreRemove(toBeRemoved) {
12097
+ if (LIVE_NODE_ITERATORS.size === 0) return;
12098
+ const removedDoc = toBeRemoved.nodeType === NODE_DOC ? toBeRemoved : toBeRemoved.ownerDocument;
12099
+ for (const it of LIVE_NODE_ITERATORS) {
12100
+ const st = it._state;
12101
+ if (nodeContains(toBeRemoved, it.root)) continue;
12102
+ const itDoc = it.root.nodeType === NODE_DOC ? it.root : it.root.ownerDocument;
12103
+ if (itDoc !== removedDoc) continue;
12104
+ if (!nodeContains(toBeRemoved, st.node)) continue;
12105
+ if (st.before) {
12106
+ const next = followingSkippingSubtree(toBeRemoved, null);
12107
+ if (next) {
12108
+ st.node = next;
12109
+ continue;
12110
+ }
12111
+ st.before = false;
12112
+ }
12113
+ const prevSib = toBeRemoved.previousSibling;
12114
+ if (!prevSib) {
12115
+ st.node = toBeRemoved._parent;
12116
+ } else {
12117
+ let n = prevSib;
12118
+ while (n._children && n._children.length) n = n._children[n._children.length - 1];
12119
+ st.node = n;
12120
+ }
12121
+ }
12122
+ }
12123
+ __name(nodeIteratorPreRemove, "nodeIteratorPreRemove");
12124
+ function nodeLength(node) {
12125
+ const t = node.nodeType;
12126
+ if (t === NODE_DOCTYPE) return 0;
12127
+ if (t === NODE_TEXT || t === NODE_CDATA || t === NODE_COMMENT || t === NODE_PI) {
12128
+ return (node.data || "").length;
12129
+ }
12130
+ return node._children ? node._children.length : 0;
12131
+ }
12132
+ __name(nodeLength, "nodeLength");
12133
+ function setRangeBoundary(range, node, offset, which) {
12134
+ const fn = which === "start" ? "setStart" : "setEnd";
12135
+ if (!isNodeArg(node)) {
12136
+ throw new TypeError(`Failed to execute '${fn}' on 'Range': parameter 1 is not of type 'Node'.`);
12137
+ }
12138
+ if (node.nodeType === NODE_DOCTYPE) {
12139
+ throw new globalThis.DOMException(`Failed to execute '${fn}' on 'Range': the node is a doctype.`, "InvalidNodeTypeError");
12140
+ }
12141
+ offset = offset >>> 0;
12142
+ if (offset > nodeLength(node)) {
12143
+ throw new globalThis.DOMException(`Failed to execute '${fn}' on 'Range': the offset ${offset} is larger than the node's length.`, "IndexSizeError");
12144
+ }
12145
+ const newRoot = ancestorChain(node)[0];
12146
+ if (which === "start") {
12147
+ const endRoot = range.endContainer && ancestorChain(range.endContainer)[0];
12148
+ if (newRoot !== endRoot || compareBoundaryPoint(node, offset, range.endContainer, range.endOffset) > 0) {
12149
+ range.endContainer = node;
12150
+ range.endOffset = offset;
12151
+ }
12152
+ range.startContainer = node;
12153
+ range.startOffset = offset;
12154
+ } else {
12155
+ const startRoot = range.startContainer && ancestorChain(range.startContainer)[0];
12156
+ if (newRoot !== startRoot || compareBoundaryPoint(node, offset, range.startContainer, range.startOffset) < 0) {
12157
+ range.startContainer = node;
12158
+ range.startOffset = offset;
12159
+ }
12160
+ range.endContainer = node;
12161
+ range.endOffset = offset;
12162
+ }
12163
+ range._track();
12164
+ }
12165
+ __name(setRangeBoundary, "setRangeBoundary");
12166
+ function boundaryRelativeToNode(range, node, which, after) {
12167
+ const fn = (which === "start" ? "setStart" : "setEnd") + (after ? "After" : "Before");
12168
+ const parent = node && node._parent;
12169
+ if (!parent) {
12170
+ throw new globalThis.DOMException(`Failed to execute '${fn}' on 'Range': the node has no parent.`, "InvalidNodeTypeError");
12171
+ }
12172
+ const index = parent._children.indexOf(node);
12173
+ setRangeBoundary(range, parent, index + (after ? 1 : 0), which);
12174
+ }
12175
+ __name(boundaryRelativeToNode, "boundaryRelativeToNode");
11895
12176
  var DocumentOrderRange = class _DocumentOrderRange {
11896
12177
  static {
11897
12178
  __name(this, "DocumentOrderRange");
11898
12179
  }
11899
- constructor() {
11900
- const doc = globalThis.document || null;
11901
- this.startContainer = doc;
12180
+ constructor(doc) {
12181
+ const d = doc || globalThis.document || null;
12182
+ this.startContainer = d;
11902
12183
  this.startOffset = 0;
11903
- this.endContainer = doc;
12184
+ this.endContainer = d;
11904
12185
  this.endOffset = 0;
12186
+ this._reg = null;
12187
+ this._track();
12188
+ }
12189
+ // (Re-)register this range in its current document's live-range set. Called
12190
+ // after every boundary change so a range that moves to another document is
12191
+ // tracked there (the registry hangs off the shared document, not a realm).
12192
+ _track() {
12193
+ const sc = this.startContainer;
12194
+ const d = sc && (sc.nodeType === NODE_DOC ? sc : sc.ownerDocument);
12195
+ const reg = d ? d._liveRanges || (d._liveRanges = /* @__PURE__ */ new Set()) : null;
12196
+ if (reg === this._reg) return;
12197
+ if (this._reg) this._reg.delete(this);
12198
+ this._reg = reg;
12199
+ if (reg) reg.add(this);
11905
12200
  }
11906
12201
  setStart(node, offset) {
11907
- this.startContainer = node;
11908
- this.startOffset = offset | 0;
12202
+ setRangeBoundary(this, node, offset, "start");
11909
12203
  }
11910
12204
  setEnd(node, offset) {
11911
- this.endContainer = node;
11912
- this.endOffset = offset | 0;
11913
- }
11914
- // Boundary helpers — node-relative variants of setStart / setEnd.
11915
- // `setStartBefore(n)` puts the range start at (n.parentNode,
11916
- // indexOf(n)); `setStartAfter` adds 1; ditto for end. Per HTML
11917
- // spec — the offset is the position of `n` among its parent's
11918
- // children. The old "offset=0" approximation broke partial-quote
11919
- // tests where the range was supposed to skip past leading
11920
- // siblings, and quote-reply's cloneContents walked from the
11921
- // wrong start position.
12205
+ setRangeBoundary(this, node, offset, "end");
12206
+ }
11922
12207
  setStartBefore(node) {
11923
- const p = node && node._parent;
11924
- this.startContainer = p || node;
11925
- this.startOffset = p ? p._children.indexOf(node) : 0;
12208
+ boundaryRelativeToNode(this, node, "start", false);
11926
12209
  }
11927
12210
  setStartAfter(node) {
11928
- const p = node && node._parent;
11929
- this.startContainer = p || node;
11930
- this.startOffset = p ? p._children.indexOf(node) + 1 : 0;
12211
+ boundaryRelativeToNode(this, node, "start", true);
11931
12212
  }
11932
12213
  setEndBefore(node) {
11933
- const p = node && node._parent;
11934
- this.endContainer = p || node;
11935
- this.endOffset = p ? p._children.indexOf(node) : 0;
12214
+ boundaryRelativeToNode(this, node, "end", false);
11936
12215
  }
11937
12216
  setEndAfter(node) {
11938
- const p = node && node._parent;
11939
- this.endContainer = p || node;
11940
- this.endOffset = p ? p._children.indexOf(node) + 1 : 0;
11941
- }
11942
- // Real DOM: selectNode sets the range to span the given node
11943
- // *within* its parent. Collapse moves both endpoints to one side.
11944
- // Consumers here only care that the start container ends up
11945
- // referring to the node we passed.
11946
- selectNode(node) {
11947
- this.startContainer = this.endContainer = node;
11948
- this.startOffset = this.endOffset = 0;
12217
+ boundaryRelativeToNode(this, node, "end", true);
11949
12218
  }
12219
+ // selectNode spans `node` within its parent: start (parent, index),
12220
+ // end (parent, index+1). A parentless node → InvalidNodeTypeError.
12221
+ selectNode(node) {
12222
+ const parent = node && node._parent;
12223
+ if (!parent) {
12224
+ throw new globalThis.DOMException("Failed to execute 'selectNode' on 'Range': the node has no parent.", "InvalidNodeTypeError");
12225
+ }
12226
+ const index = parent._children.indexOf(node);
12227
+ this.startContainer = parent;
12228
+ this.startOffset = index;
12229
+ this.endContainer = parent;
12230
+ this.endOffset = index + 1;
12231
+ this._track();
12232
+ }
12233
+ // selectNodeContents spans the whole node: start (node, 0), end (node, length).
12234
+ // A doctype has no contents to select → InvalidNodeTypeError.
11950
12235
  selectNodeContents(node) {
12236
+ if (node.nodeType === NODE_DOCTYPE) {
12237
+ throw new globalThis.DOMException("Failed to execute 'selectNodeContents' on 'Range': the node is a doctype.", "InvalidNodeTypeError");
12238
+ }
11951
12239
  this.startContainer = this.endContainer = node;
11952
12240
  this.startOffset = 0;
11953
- this.endOffset = node.nodeType === NODE_TEXT ? (node.data || "").length : node._children ? node._children.length : 0;
12241
+ this.endOffset = nodeLength(node);
12242
+ this._track();
11954
12243
  }
11955
12244
  // `Range.createContextualFragment(html)` — parse `html` as a fragment using
11956
12245
  // the range's start node as context, returning a DocumentFragment owned by the
@@ -11992,9 +12281,7 @@
11992
12281
  return cloneRangeContents(this);
11993
12282
  }
11994
12283
  extractContents() {
11995
- const frag = cloneRangeContents(this);
11996
- deleteRangeContents(this);
11997
- return frag;
12284
+ return extractRangeContents(this);
11998
12285
  }
11999
12286
  // Spec: removes everything inside the range from its container.
12000
12287
  // Turbo's `FrameRenderer` calls `selectNodeContents(currentElement);
@@ -12030,6 +12317,7 @@
12030
12317
  r.startOffset = this.startOffset;
12031
12318
  r.endContainer = this.endContainer;
12032
12319
  r.endOffset = this.endOffset;
12320
+ r._track();
12033
12321
  return r;
12034
12322
  }
12035
12323
  // DOM spec Range#toString: concatenates the text of all Text nodes
@@ -12069,35 +12357,50 @@
12069
12357
  // containers, inserts at child index `startOffset`. Tiptap /
12070
12358
  // ProseMirror's text-insertion fallback uses this.
12071
12359
  insertNode(node) {
12360
+ if (!isNodeArg(node)) throw new TypeError("Failed to execute 'insertNode' on 'Range': parameter 1 is not of type 'Node'.");
12072
12361
  const sc = this.startContainer;
12073
- if (!sc) return;
12074
- if (sc.nodeType === NODE_TEXT) {
12075
- const parent = sc._parent;
12076
- if (!parent) return;
12077
- const text = sc.data || "";
12078
- const before = text.slice(0, this.startOffset);
12079
- const after = text.slice(this.startOffset);
12080
- sc.data = before;
12081
- const idx = parent._children.indexOf(sc);
12082
- if (after.length > 0) {
12083
- const tail = new Text(after);
12084
- parent.insertBefore(tail, parent._children[idx + 1] || null);
12085
- }
12086
- parent.insertBefore(node, parent._children[idx + 1] || null);
12087
- } else {
12088
- const ref = sc._children ? sc._children[this.startOffset] : null;
12089
- sc.insertBefore(node, ref || null);
12362
+ const startIsText = sc.nodeType === NODE_TEXT || sc.nodeType === NODE_CDATA;
12363
+ if (sc.nodeType === NODE_PI || sc.nodeType === NODE_COMMENT || startIsText && !sc._parent || node === sc || nodeContains(node, sc)) {
12364
+ throw new globalThis.DOMException("Failed to execute 'insertNode' on 'Range': the node may not be inserted here.", "HierarchyRequestError");
12365
+ }
12366
+ let referenceNode = startIsText ? sc : sc._children ? sc._children[this.startOffset] || null : null;
12367
+ const parent = referenceNode == null ? sc : referenceNode._parent;
12368
+ ensurePreInsertionValidity(node, parent, referenceNode);
12369
+ if (startIsText) referenceNode = sc.splitText(this.startOffset);
12370
+ if (node === referenceNode) referenceNode = node.nextSibling;
12371
+ if (node._parent) node._parent.removeChild(node);
12372
+ let newOffset = referenceNode == null ? nodeLength(parent) : parent._children.indexOf(referenceNode);
12373
+ newOffset += node.nodeType === NODE_FRAGMENT ? nodeLength(node) : 1;
12374
+ parent.insertBefore(node, referenceNode);
12375
+ if (this.collapsed) {
12376
+ this.endContainer = parent;
12377
+ this.endOffset = newOffset;
12090
12378
  }
12091
- this.setStartAfter(node);
12092
- this.collapse(true);
12093
12379
  }
12094
12380
  // Range#surroundContents(newParent): extract range contents, wrap
12095
12381
  // in `newParent`, insert wrapper at the range's start. Used by
12096
12382
  // highlight / annotate libraries.
12097
12383
  surroundContents(newParent) {
12098
- const frag = this.extractContents();
12099
- newParent.appendChild(frag);
12384
+ const common = this.commonAncestorContainer;
12385
+ const partialNonText = /* @__PURE__ */ __name((boundary, other) => {
12386
+ if (nodeContains(boundary, other)) return false;
12387
+ for (let n = boundary; n && n !== common; n = n._parent) {
12388
+ if (n.nodeType !== NODE_TEXT && n.nodeType !== NODE_CDATA) return true;
12389
+ }
12390
+ return false;
12391
+ }, "partialNonText");
12392
+ if (partialNonText(this.startContainer, this.endContainer) || partialNonText(this.endContainer, this.startContainer)) {
12393
+ throw new globalThis.DOMException("Failed to execute 'surroundContents' on 'Range': the range partially selects a non-Text node.", "InvalidStateError");
12394
+ }
12395
+ const nt = newParent.nodeType;
12396
+ if (nt === NODE_DOC || nt === NODE_DOCTYPE || nt === NODE_FRAGMENT) {
12397
+ throw new globalThis.DOMException("Failed to execute 'surroundContents' on 'Range': the new parent is a Document, DocumentType, or DocumentFragment node.", "InvalidNodeTypeError");
12398
+ }
12399
+ const fragment = extractRangeContents(this);
12400
+ if (newParent._children) for (const c of newParent._children.slice()) newParent.removeChild(c);
12100
12401
  this.insertNode(newParent);
12402
+ newParent.appendChild(fragment);
12403
+ this.selectNode(newParent);
12101
12404
  }
12102
12405
  // Range#comparePoint(node, offset) — -1/0/+1 vs the range.
12103
12406
  // Range#isPointInRange(node, offset) — true if inside.
@@ -12106,12 +12409,30 @@
12106
12409
  if (ancestorChain(node)[0] !== ancestorChain(this.startContainer)[0]) {
12107
12410
  throw new globalThis.DOMException("The node provided is in a different tree than this Range.", "WrongDocumentError");
12108
12411
  }
12109
- if (compareDocOrder(node, this.startContainer) < 0) return -1;
12110
- if (compareDocOrder(node, this.endContainer) > 0) return 1;
12412
+ if (node.nodeType === NODE_DOCTYPE) {
12413
+ throw new globalThis.DOMException("Failed to execute 'comparePoint' on 'Range': the node is a doctype.", "InvalidNodeTypeError");
12414
+ }
12415
+ offset = offset >>> 0;
12416
+ if (offset > nodeLength(node)) {
12417
+ throw new globalThis.DOMException(`Failed to execute 'comparePoint' on 'Range': the offset ${offset} is larger than the node's length.`, "IndexSizeError");
12418
+ }
12419
+ if (compareBoundaryPoint(node, offset, this.startContainer, this.startOffset) < 0) return -1;
12420
+ if (compareBoundaryPoint(node, offset, this.endContainer, this.endOffset) > 0) return 1;
12111
12421
  return 0;
12112
12422
  }
12113
12423
  isPointInRange(node, offset) {
12114
- return this.comparePoint(node, offset) === 0;
12424
+ if (!isNodeArg(node)) throw new TypeError("Failed to execute 'isPointInRange' on 'Range': parameter 1 is not of type 'Node'.");
12425
+ if (ancestorChain(node)[0] !== ancestorChain(this.startContainer)[0]) return false;
12426
+ if (node.nodeType === NODE_DOCTYPE) {
12427
+ throw new globalThis.DOMException("Failed to execute 'isPointInRange' on 'Range': the node is a doctype.", "InvalidNodeTypeError");
12428
+ }
12429
+ offset = offset >>> 0;
12430
+ if (offset > nodeLength(node)) {
12431
+ throw new globalThis.DOMException(`Failed to execute 'isPointInRange' on 'Range': the offset ${offset} is larger than the node's length.`, "IndexSizeError");
12432
+ }
12433
+ if (compareBoundaryPoint(node, offset, this.startContainer, this.startOffset) < 0) return false;
12434
+ if (compareBoundaryPoint(node, offset, this.endContainer, this.endOffset) > 0) return false;
12435
+ return true;
12115
12436
  }
12116
12437
  get collapsed() {
12117
12438
  return this.startContainer === this.endContainer && this.startOffset === this.endOffset;
@@ -12125,8 +12446,40 @@
12125
12446
  while (i < a.length && i < b.length && a[i] === b[i]) i++;
12126
12447
  return i > 0 ? a[i - 1] : this.startContainer;
12127
12448
  }
12128
- compareBoundaryPoints(_how, other) {
12129
- return compareDocOrder(this.startContainer, other.startContainer);
12449
+ // compareBoundaryPoints(how, sourceRange): compares the two ranges' boundary
12450
+ // points selected by `how`. `how` is a WebIDL unsigned short; a value outside
12451
+ // {0,1,2,3} → NotSupportedError. Different roots → WrongDocumentError.
12452
+ compareBoundaryPoints(how, other) {
12453
+ how = how & 65535;
12454
+ if (how > 3) {
12455
+ throw new globalThis.DOMException("Failed to execute 'compareBoundaryPoints' on 'Range': the comparison method must be 0, 1, 2 or 3.", "NotSupportedError");
12456
+ }
12457
+ if (ancestorChain(this.startContainer)[0] !== ancestorChain(other.startContainer)[0]) {
12458
+ throw new globalThis.DOMException("The two Ranges are not in the same tree.", "WrongDocumentError");
12459
+ }
12460
+ let tn, to, on, oo;
12461
+ if (how === 0) {
12462
+ tn = this.startContainer;
12463
+ to = this.startOffset;
12464
+ on = other.startContainer;
12465
+ oo = other.startOffset;
12466
+ } else if (how === 1) {
12467
+ tn = this.endContainer;
12468
+ to = this.endOffset;
12469
+ on = other.startContainer;
12470
+ oo = other.startOffset;
12471
+ } else if (how === 2) {
12472
+ tn = this.endContainer;
12473
+ to = this.endOffset;
12474
+ on = other.endContainer;
12475
+ oo = other.endOffset;
12476
+ } else {
12477
+ tn = this.startContainer;
12478
+ to = this.startOffset;
12479
+ on = other.endContainer;
12480
+ oo = other.endOffset;
12481
+ }
12482
+ return compareBoundaryPoint(tn, to, on, oo);
12130
12483
  }
12131
12484
  };
12132
12485
  DocumentOrderRange.START_TO_START = 0;
@@ -12176,54 +12529,6 @@
12176
12529
  return cur && cur._parent === ancestor ? cur : null;
12177
12530
  }
12178
12531
  __name(__rangeAncestorChild, "__rangeAncestorChild");
12179
- function __appendCloned(parent, child) {
12180
- child._parent = parent;
12181
- parent._children.push(child);
12182
- }
12183
- __name(__appendCloned, "__appendCloned");
12184
- function __emitSlice(target, subtree, startCut, endCut) {
12185
- const kids = subtree._children || [];
12186
- let startIdx = 0, startChild = null;
12187
- if (startCut) {
12188
- if (startCut.container === subtree) {
12189
- startIdx = startCut.offset;
12190
- } else {
12191
- startChild = __rangeAncestorChild(subtree, startCut.container);
12192
- if (startChild) startIdx = kids.indexOf(startChild) + 1;
12193
- }
12194
- }
12195
- let endIdx = kids.length, endChild = null;
12196
- if (endCut) {
12197
- if (endCut.container === subtree) {
12198
- endIdx = endCut.offset;
12199
- } else {
12200
- endChild = __rangeAncestorChild(subtree, endCut.container);
12201
- if (endChild) endIdx = kids.indexOf(endChild);
12202
- }
12203
- }
12204
- if (startChild && startChild === endChild) {
12205
- __appendCloned(target, __cloneSlice(startChild, startCut, endCut));
12206
- return;
12207
- }
12208
- if (startChild) __appendCloned(target, __cloneSlice(startChild, startCut, null));
12209
- for (let i = startIdx; i < endIdx; i++) {
12210
- if (kids[i]) __appendCloned(target, kids[i].cloneNode(true));
12211
- }
12212
- if (endChild) __appendCloned(target, __cloneSlice(endChild, null, endCut));
12213
- }
12214
- __name(__emitSlice, "__emitSlice");
12215
- function __cloneSlice(subtree, startCut, endCut) {
12216
- if (subtree.nodeType === NODE_TEXT) {
12217
- const data = subtree.data || "";
12218
- const lo = startCut && startCut.container === subtree ? startCut.offset : 0;
12219
- const hi = endCut && endCut.container === subtree ? endCut.offset : data.length;
12220
- return new Text(data.slice(lo, hi));
12221
- }
12222
- const shell = subtree.cloneNode(false);
12223
- __emitSlice(shell, subtree, startCut, endCut);
12224
- return shell;
12225
- }
12226
- __name(__cloneSlice, "__cloneSlice");
12227
12532
  function __csimInsertTextAtSelection(text) {
12228
12533
  const sel = globalThis.getSelection && globalThis.getSelection();
12229
12534
  if (!sel || !sel._ranges.length) return false;
@@ -12294,93 +12599,113 @@
12294
12599
  }
12295
12600
  __name(__csimInsertTextAtSelection, "__csimInsertTextAtSelection");
12296
12601
  globalThis.__csimInsertTextAtSelection = __csimInsertTextAtSelection;
12297
- function __deleteSlice(subtree, startCut, endCut) {
12298
- if (subtree.nodeType === NODE_TEXT) {
12299
- const data = subtree.data || "";
12300
- const lo = startCut && startCut.container === subtree ? startCut.offset : 0;
12301
- const hi = endCut && endCut.container === subtree ? endCut.offset : data.length;
12302
- subtree.data = data.slice(0, lo) + data.slice(hi);
12303
- return;
12304
- }
12305
- __emitSliceDelete(subtree, startCut, endCut);
12602
+ function isCharacterData(n) {
12603
+ return n != null && (n.nodeType === NODE_TEXT || n.nodeType === NODE_CDATA || n.nodeType === NODE_COMMENT || n.nodeType === NODE_PI);
12306
12604
  }
12307
- __name(__deleteSlice, "__deleteSlice");
12308
- function __emitSliceDelete(subtree, startCut, endCut) {
12309
- const kids = subtree._children || [];
12310
- let startIdx = 0, startChild = null;
12311
- if (startCut) {
12312
- if (startCut.container === subtree) {
12313
- startIdx = startCut.offset;
12314
- } else {
12315
- startChild = __rangeAncestorChild(subtree, startCut.container);
12316
- if (startChild) startIdx = kids.indexOf(startChild) + 1;
12317
- }
12318
- }
12319
- let endIdx = kids.length, endChild = null;
12320
- if (endCut) {
12321
- if (endCut.container === subtree) {
12322
- endIdx = endCut.offset;
12323
- } else {
12324
- endChild = __rangeAncestorChild(subtree, endCut.container);
12325
- if (endChild) endIdx = kids.indexOf(endChild);
12326
- }
12327
- }
12328
- if (startChild && startChild === endChild) {
12329
- __deleteSlice(startChild, startCut, endCut);
12330
- return;
12605
+ __name(isCharacterData, "isCharacterData");
12606
+ function processRangeContents(range, mode) {
12607
+ const sc = range.startContainer, so = range.startOffset;
12608
+ const ec = range.endContainer, eo = range.endOffset;
12609
+ const ownerDoc = sc && (sc.nodeType === NODE_DOC ? sc : sc.ownerDocument) || globalThis.document;
12610
+ const frag = mode === "delete" ? null : ownerDoc.createDocumentFragment();
12611
+ if (!sc || !ec) return frag;
12612
+ if (sc === ec && so === eo) return frag;
12613
+ if (sc === ec && isCharacterData(sc)) {
12614
+ if (mode !== "delete") {
12615
+ const clone = sc.cloneNode(false);
12616
+ clone._data = (sc.data || "").slice(so, eo);
12617
+ frag.appendChild(clone);
12618
+ }
12619
+ if (mode !== "clone") sc._replaceData(so, eo - so, "");
12620
+ return frag;
12331
12621
  }
12332
- if (startChild) __deleteSlice(startChild, startCut, null);
12333
- if (endChild) __deleteSlice(endChild, null, endCut);
12334
- for (let i = endIdx - 1; i >= startIdx; i--) {
12335
- if (kids[i]) subtree.removeChild(kids[i]);
12622
+ const common = range.commonAncestorContainer;
12623
+ const firstPC = nodeContains(sc, ec) ? null : __rangeAncestorChild(common, sc);
12624
+ const lastPC = nodeContains(ec, sc) ? null : __rangeAncestorChild(common, ec);
12625
+ const contained = [];
12626
+ const kids = common._children || [];
12627
+ for (let i = 0; i < kids.length; i++) {
12628
+ if (compareBoundaryPoint(common, i, sc, so) >= 0 && compareBoundaryPoint(common, i + 1, ec, eo) <= 0) {
12629
+ contained.push(kids[i]);
12630
+ }
12631
+ }
12632
+ let newNode = sc, newOffset = so;
12633
+ if (mode !== "clone" && !nodeContains(sc, ec)) {
12634
+ let ref = sc;
12635
+ while (ref._parent && !nodeContains(ref._parent, ec)) ref = ref._parent;
12636
+ newNode = ref._parent;
12637
+ newOffset = newNode._children.indexOf(ref) + 1;
12638
+ }
12639
+ if (isCharacterData(firstPC)) {
12640
+ if (mode !== "delete") {
12641
+ const clone = sc.cloneNode(false);
12642
+ clone._data = (sc.data || "").slice(so);
12643
+ frag.appendChild(clone);
12644
+ }
12645
+ if (mode !== "clone") sc._replaceData(so, nodeLength(sc) - so, "");
12646
+ } else if (firstPC) {
12647
+ let clone = null;
12648
+ if (mode !== "delete") {
12649
+ clone = firstPC.cloneNode(false);
12650
+ frag.appendChild(clone);
12651
+ }
12652
+ const sub = new DocumentOrderRange(ownerDoc);
12653
+ sub.startContainer = sc;
12654
+ sub.startOffset = so;
12655
+ sub.endContainer = firstPC;
12656
+ sub.endOffset = nodeLength(firstPC);
12657
+ const subResult = processRangeContents(sub, mode);
12658
+ if (clone) clone.appendChild(subResult);
12659
+ if (sub._reg) sub._reg.delete(sub);
12660
+ }
12661
+ for (const child of contained) {
12662
+ if (mode === "clone") frag.appendChild(child.cloneNode(true));
12663
+ else if (mode === "extract") frag.appendChild(child);
12664
+ else if (child._parent) child._parent.removeChild(child);
12665
+ }
12666
+ if (isCharacterData(lastPC)) {
12667
+ if (mode !== "delete") {
12668
+ const clone = ec.cloneNode(false);
12669
+ clone._data = (ec.data || "").slice(0, eo);
12670
+ frag.appendChild(clone);
12671
+ }
12672
+ if (mode !== "clone") ec._replaceData(0, eo, "");
12673
+ } else if (lastPC) {
12674
+ let clone = null;
12675
+ if (mode !== "delete") {
12676
+ clone = lastPC.cloneNode(false);
12677
+ frag.appendChild(clone);
12678
+ }
12679
+ const sub = new DocumentOrderRange(ownerDoc);
12680
+ sub.startContainer = lastPC;
12681
+ sub.startOffset = 0;
12682
+ sub.endContainer = ec;
12683
+ sub.endOffset = eo;
12684
+ const subResult = processRangeContents(sub, mode);
12685
+ if (clone) clone.appendChild(subResult);
12686
+ if (sub._reg) sub._reg.delete(sub);
12687
+ }
12688
+ if (mode !== "clone") {
12689
+ range.startContainer = newNode;
12690
+ range.startOffset = newOffset;
12691
+ range.endContainer = newNode;
12692
+ range.endOffset = newOffset;
12336
12693
  }
12694
+ return frag;
12337
12695
  }
12338
- __name(__emitSliceDelete, "__emitSliceDelete");
12696
+ __name(processRangeContents, "processRangeContents");
12339
12697
  function deleteRangeContents(range) {
12340
- const sc = range.startContainer, so = range.startOffset | 0;
12341
- const ec = range.endContainer, eo = range.endOffset | 0;
12342
- if (sc === ec && sc && sc.nodeType === NODE_TEXT) {
12343
- const data = sc.data || "";
12344
- sc.data = data.slice(0, so) + data.slice(eo);
12345
- range.endOffset = range.startOffset;
12346
- } else if (sc === ec && sc && sc._children) {
12347
- const end = Math.min(eo, sc._children.length);
12348
- const doomed = sc._children.slice(so, end);
12349
- for (const child of doomed) sc.removeChild(child);
12350
- range.endOffset = range.startOffset;
12351
- range.endContainer = range.startContainer;
12352
- } else if (sc && ec) {
12353
- const ancestor = range.commonAncestorContainer;
12354
- if (ancestor) {
12355
- __deleteSlice(ancestor, { container: sc, offset: so }, { container: ec, offset: eo });
12356
- }
12357
- range.endContainer = sc;
12358
- range.endOffset = so;
12359
- }
12698
+ processRangeContents(range, "delete");
12360
12699
  }
12361
12700
  __name(deleteRangeContents, "deleteRangeContents");
12362
12701
  function cloneRangeContents(range) {
12363
- const frag = new DocumentFragment();
12364
- if (!range.startContainer || !range.endContainer) return frag;
12365
- const sc = range.startContainer, so = range.startOffset;
12366
- const ec = range.endContainer, eo = range.endOffset;
12367
- if (sc === ec) {
12368
- if (sc.nodeType === NODE_TEXT) {
12369
- __appendCloned(frag, new Text((sc.data || "").slice(so, eo)));
12370
- } else if (sc._children) {
12371
- for (let i = so; i < Math.min(eo, sc._children.length); i++) {
12372
- __appendCloned(frag, sc._children[i].cloneNode(true));
12373
- }
12374
- }
12375
- return frag;
12376
- }
12377
- const ancestor = range.commonAncestorContainer;
12378
- if (ancestor) {
12379
- __emitSlice(frag, ancestor, { container: sc, offset: so }, { container: ec, offset: eo });
12380
- }
12381
- return frag;
12702
+ return processRangeContents(range, "clone");
12382
12703
  }
12383
12704
  __name(cloneRangeContents, "cloneRangeContents");
12705
+ function extractRangeContents(range) {
12706
+ return processRangeContents(range, "extract");
12707
+ }
12708
+ __name(extractRangeContents, "extractRangeContents");
12384
12709
  DocumentOrderRange.END_TO_START = 3;
12385
12710
  DocumentOrderRange.prototype.START_TO_START = 0;
12386
12711
  DocumentOrderRange.prototype.START_TO_END = 1;
@@ -12510,7 +12835,7 @@
12510
12835
  assertNodeArg(node);
12511
12836
  if (child != null) assertNodeArg(child);
12512
12837
  const parent = this;
12513
- if (node.getRootNode() !== parent.getRootNode()) {
12838
+ if (node.getRootNode({ composed: true }) !== parent.getRootNode({ composed: true })) {
12514
12839
  throw hierarchyError("moveBefore: node and new parent are not in the same tree");
12515
12840
  }
12516
12841
  if (isInclusiveAncestor(node, parent)) {
@@ -12612,7 +12937,7 @@
12612
12937
  return el._attrNodeFor(key);
12613
12938
  }
12614
12939
  __name(makeAttr, "makeAttr");
12615
- var { parseDocument, parseFragment } = installHtmlParser({ Document, Element, Text, Comment, DocumentFragment, DocumentType });
12940
+ var { parseDocument, parseFragment } = installHtmlParser({ Document, Element, Text, Comment, DocumentFragment, DocumentType, createHtmlPageDocument });
12616
12941
  var { parseXml } = installXmlParser({ Element, Text, Comment, ProcessingInstruction, CDATASection, DocumentType });
12617
12942
 
12618
12943
  // lib/capybara/simulated/js/src/abort.js
@@ -17816,10 +18141,15 @@
17816
18141
  this._url = _url || null;
17817
18142
  if (typeof init === "string") {
17818
18143
  this._parseQuery(init);
18144
+ } else if (Array.isArray(init)) {
18145
+ for (const e of init) {
18146
+ if (e == null || e.length !== 2) {
18147
+ throw new TypeError("Failed to construct 'URLSearchParams': each pair must have exactly two elements.");
18148
+ }
18149
+ this._entries.push([String(e[0]), String(e[1])]);
18150
+ }
17819
18151
  } else if (init && typeof init.forEach === "function") {
17820
18152
  init.forEach((v, k) => this._entries.push([String(k), String(v)]));
17821
- } else if (Array.isArray(init)) {
17822
- for (const e of init) this._entries.push([String(e[0]), String(e[1])]);
17823
18153
  } else if (init && typeof init === "object") {
17824
18154
  for (const k of Object.keys(init)) this._entries.push([k, String(init[k])]);
17825
18155
  }
@@ -18453,7 +18783,7 @@
18453
18783
  installNodeConstants(Node);
18454
18784
  globalThis.Text = Text;
18455
18785
  installDomClassAliases({ Element, Document, Text });
18456
- globalThis.document = new Document();
18786
+ globalThis.document = createHtmlPageDocument(true);
18457
18787
  globalThis.window = globalThis;
18458
18788
  globalThis.EventTarget = EventTarget;
18459
18789
  globalThis.Blob = Blob;
@@ -18493,11 +18823,12 @@
18493
18823
  function parseXMLDocument(xml) {
18494
18824
  const doc = new Document();
18495
18825
  doc._children = newChildList();
18496
- doc.documentElement = null;
18826
+ doc._url = void 0;
18827
+ doc._noBrowsingContext = false;
18828
+ doc.readyState = "loading";
18497
18829
  for (const node of parseXml(String(xml == null ? "" : xml))) {
18498
18830
  node._parent = doc;
18499
18831
  doc._children.push(node);
18500
- if (node.nodeType === NODE_ELEMENT && !doc.documentElement) doc.documentElement = node;
18501
18832
  }
18502
18833
  return doc;
18503
18834
  }
@@ -18702,7 +19033,6 @@
18702
19033
  c._parent = null;
18703
19034
  }
18704
19035
  dx._children = newChildList();
18705
- dx.documentElement = null;
18706
19036
  dx._contentType = __ct;
18707
19037
  for (const c of xmlDoc._children) {
18708
19038
  c._parent = dx;
@@ -18710,7 +19040,6 @@
18710
19040
  n._ownerDoc = dx;
18711
19041
  });
18712
19042
  dx._children.push(c);
18713
- if (c.nodeType === NODE_ELEMENT && !dx.documentElement) dx.documentElement = c;
18714
19043
  }
18715
19044
  registerSubtree(dx);
18716
19045
  globalThis.__csimFireCEConnect(dx);