capybara-simulated 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +71 -128
- data/lib/capybara/simulated/browser.rb +442 -48
- data/lib/capybara/simulated/js/bridge.bundle.js +302 -44
- data/lib/capybara/simulated/runtime_shared.rb +5 -0
- data/lib/capybara/simulated/v8_runtime.rb +11 -4
- data/lib/capybara/simulated/version.rb +1 -1
- metadata +1 -1
|
@@ -417,7 +417,7 @@
|
|
|
417
417
|
this._currentTarget = v;
|
|
418
418
|
}
|
|
419
419
|
});
|
|
420
|
-
var
|
|
420
|
+
var DOMException2 = class _DOMException extends Error {
|
|
421
421
|
static {
|
|
422
422
|
__name(this, "DOMException");
|
|
423
423
|
}
|
|
@@ -480,8 +480,8 @@
|
|
|
480
480
|
INVALID_NODE_TYPE_ERR: 24,
|
|
481
481
|
DATA_CLONE_ERR: 25
|
|
482
482
|
}).forEach(([k, v]) => {
|
|
483
|
-
Object.defineProperty(
|
|
484
|
-
Object.defineProperty(
|
|
483
|
+
Object.defineProperty(DOMException2, k, { value: v, enumerable: true });
|
|
484
|
+
Object.defineProperty(DOMException2.prototype, k, { value: v, enumerable: true });
|
|
485
485
|
});
|
|
486
486
|
var CustomEvent = class extends Event {
|
|
487
487
|
static {
|
|
@@ -1798,7 +1798,7 @@
|
|
|
1798
1798
|
globalThis.__isVisibleNode = isVisibleNode;
|
|
1799
1799
|
globalThis.__isLaidOutNode = isLaidOutNode;
|
|
1800
1800
|
function selfHidden(el, ignoreVisibility = false) {
|
|
1801
|
-
|
|
1801
|
+
const hidden = el._attrs.hidden != null;
|
|
1802
1802
|
if (el._tag === "dialog" && el._attrs.open == null) return true;
|
|
1803
1803
|
const inline = inlineHideDecl(el);
|
|
1804
1804
|
if (inline && !state.hasImportantHideRule) {
|
|
@@ -1808,7 +1808,7 @@
|
|
|
1808
1808
|
const visibilitySettled = ignoreVisibility || inline.visibility != null;
|
|
1809
1809
|
if (displaySettled && visibilitySettled) return false;
|
|
1810
1810
|
}
|
|
1811
|
-
return matchesAnyHideRule(el, ignoreVisibility, inline);
|
|
1811
|
+
return matchesAnyHideRule(el, ignoreVisibility, inline, hidden);
|
|
1812
1812
|
}
|
|
1813
1813
|
__name(selfHidden, "selfHidden");
|
|
1814
1814
|
function inlineHideDecl(el) {
|
|
@@ -2297,13 +2297,22 @@
|
|
|
2297
2297
|
}
|
|
2298
2298
|
__name(forEachCandidateRule, "forEachCandidateRule");
|
|
2299
2299
|
var LAYOUT_PROPS = [...CAPTURED_PROPS, "text-transform", "white-space"];
|
|
2300
|
+
var IMPORTANT_RE = /\s*!\s*important\s*$/i;
|
|
2301
|
+
function splitImportant(value) {
|
|
2302
|
+
if (typeof value !== "string" || value.indexOf("!") < 0) return { value, important: false };
|
|
2303
|
+
return IMPORTANT_RE.test(value) ? { value: value.replace(IMPORTANT_RE, "").trim(), important: true } : { value, important: false };
|
|
2304
|
+
}
|
|
2305
|
+
__name(splitImportant, "splitImportant");
|
|
2300
2306
|
function parseInlineLayout(el) {
|
|
2301
2307
|
const out = {};
|
|
2302
2308
|
const s = el._attrs && el._attrs.style;
|
|
2303
2309
|
if (!s) return out;
|
|
2304
2310
|
for (const part of String(s).split(";")) {
|
|
2305
2311
|
const m = /^\s*(top|left|width|height)\s*:\s*([^;]+?)\s*$/.exec(part);
|
|
2306
|
-
if (m)
|
|
2312
|
+
if (m) {
|
|
2313
|
+
const d = splitImportant(m[2]);
|
|
2314
|
+
out[m[1]] = { value: d.value, important: d.important };
|
|
2315
|
+
}
|
|
2307
2316
|
}
|
|
2308
2317
|
return out;
|
|
2309
2318
|
}
|
|
@@ -2343,8 +2352,8 @@
|
|
|
2343
2352
|
return candSource >= current.source;
|
|
2344
2353
|
}
|
|
2345
2354
|
__name(winsProp, "winsProp");
|
|
2346
|
-
function matchesAnyHideRule(el, ignoreVisibility = false, inline = null) {
|
|
2347
|
-
if (state.hideRules.length === 0 && !inline) return
|
|
2355
|
+
function matchesAnyHideRule(el, ignoreVisibility = false, inline = null, hidden = false) {
|
|
2356
|
+
if (state.hideRules.length === 0 && !inline) return hidden;
|
|
2348
2357
|
let bestD = null, bestV = null;
|
|
2349
2358
|
if (inline) {
|
|
2350
2359
|
if (inline.display != null) {
|
|
@@ -2367,6 +2376,7 @@
|
|
|
2367
2376
|
});
|
|
2368
2377
|
}
|
|
2369
2378
|
if (bestD && bestD.value === "none") return true;
|
|
2379
|
+
if (hidden && bestD == null) return true;
|
|
2370
2380
|
if (bestV && (bestV.value === "hidden" || bestV.value === "collapse")) return true;
|
|
2371
2381
|
return false;
|
|
2372
2382
|
}
|
|
@@ -2523,11 +2533,11 @@
|
|
|
2523
2533
|
}
|
|
2524
2534
|
__name(cascadedProperty, "cascadedProperty");
|
|
2525
2535
|
function parseInlinePropertyValue(style, prop) {
|
|
2526
|
-
const re = new RegExp("(?:^|;)\\s*" + prop + "\\s*:\\s*([^;!]+?)\\s*(
|
|
2536
|
+
const re = new RegExp("(?:^|;)\\s*" + prop + "\\s*:\\s*([^;!]+?)\\s*(!\\s*important)?\\s*(?:;|$)", "i");
|
|
2527
2537
|
const m = re.exec(String(style));
|
|
2528
2538
|
if (!m) return null;
|
|
2529
2539
|
const lower = prop === "display" || prop === "visibility" || prop === "text-transform" || prop === "white-space";
|
|
2530
|
-
return { value: lower ? m[1].toLowerCase() : m[1], important:
|
|
2540
|
+
return { value: lower ? m[1].toLowerCase() : m[1], important: m[2] != null };
|
|
2531
2541
|
}
|
|
2532
2542
|
__name(parseInlinePropertyValue, "parseInlinePropertyValue");
|
|
2533
2543
|
function rulesIndexHas(prop) {
|
|
@@ -4532,6 +4542,18 @@
|
|
|
4532
4542
|
return globalThis.__csim_transferStash(view) | 0;
|
|
4533
4543
|
}
|
|
4534
4544
|
__name(stashTransfer, "stashTransfer");
|
|
4545
|
+
function detachTransferables(transferList) {
|
|
4546
|
+
if (!Array.isArray(transferList)) return;
|
|
4547
|
+
for (const t of transferList) {
|
|
4548
|
+
if (t instanceof ArrayBuffer && typeof t.transfer === "function") {
|
|
4549
|
+
try {
|
|
4550
|
+
t.transfer();
|
|
4551
|
+
} catch (_) {
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
__name(detachTransferables, "detachTransferables");
|
|
4535
4557
|
|
|
4536
4558
|
// lib/capybara/simulated/js/src/workers.js
|
|
4537
4559
|
function hasWorkers() {
|
|
@@ -4540,28 +4562,51 @@
|
|
|
4540
4562
|
}
|
|
4541
4563
|
__name(hasWorkers, "hasWorkers");
|
|
4542
4564
|
var TRANSFER_STASH_MIN = 64 * 1024;
|
|
4543
|
-
function
|
|
4565
|
+
function transferSetFrom(transferList) {
|
|
4566
|
+
if (!transferList || !transferList.length) return null;
|
|
4567
|
+
const set = /* @__PURE__ */ new Set();
|
|
4568
|
+
for (const t of transferList) set.add(t instanceof ArrayBuffer ? t : t && t.buffer || t);
|
|
4569
|
+
return set;
|
|
4570
|
+
}
|
|
4571
|
+
__name(transferSetFrom, "transferSetFrom");
|
|
4572
|
+
function encode(data, transferSet) {
|
|
4573
|
+
const NS = globalThis.RustyRacer;
|
|
4574
|
+
const canTransfer = transferSet && NS && typeof NS.transferOut === "function";
|
|
4544
4575
|
return JSON.stringify(data, function(_key, value) {
|
|
4545
4576
|
const isU8 = value instanceof Uint8Array;
|
|
4546
4577
|
const isAB = !isU8 && value instanceof ArrayBuffer;
|
|
4547
4578
|
if (!isU8 && !isAB) return value;
|
|
4579
|
+
const type = isU8 ? "Uint8Array" : "ArrayBuffer";
|
|
4580
|
+
const buf = isU8 ? value.buffer : value;
|
|
4581
|
+
if (canTransfer && transferSet.has(buf)) {
|
|
4582
|
+
const token = NS.transferOut(value) | 0;
|
|
4583
|
+
if (token > 0) {
|
|
4584
|
+
if (globalThis.__csim_transferIssued) globalThis.__csim_transferIssued(token);
|
|
4585
|
+
return isU8 ? { __csimType: type, xfer: token, byteOffset: value.byteOffset, length: value.length } : { __csimType: type, xfer: token };
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4548
4588
|
const view = isU8 ? value : new Uint8Array(value);
|
|
4549
4589
|
if (view.byteLength >= TRANSFER_STASH_MIN) {
|
|
4550
4590
|
const refId = stashTransfer(view);
|
|
4551
|
-
if (refId > 0) return { __csimType:
|
|
4591
|
+
if (refId > 0) return { __csimType: type, refId };
|
|
4552
4592
|
}
|
|
4553
|
-
return {
|
|
4554
|
-
__csimType: isU8 ? "Uint8Array" : "ArrayBuffer",
|
|
4555
|
-
b64: globalThis.btoa(bytesToLatin1(view))
|
|
4556
|
-
};
|
|
4593
|
+
return { __csimType: type, b64: globalThis.btoa(bytesToLatin1(view)) };
|
|
4557
4594
|
});
|
|
4558
4595
|
}
|
|
4559
4596
|
__name(encode, "encode");
|
|
4560
4597
|
function decode(s) {
|
|
4598
|
+
const NS = globalThis.RustyRacer;
|
|
4561
4599
|
return JSON.parse(s, function(_key, value) {
|
|
4562
4600
|
if (!value || typeof value !== "object") return value;
|
|
4563
4601
|
const tag = value.__csimType;
|
|
4564
4602
|
if (tag !== "Uint8Array" && tag !== "ArrayBuffer") return value;
|
|
4603
|
+
if (value.xfer != null && NS && typeof NS.transferIn === "function") {
|
|
4604
|
+
const ab = NS.transferIn(value.xfer);
|
|
4605
|
+
if (ab) {
|
|
4606
|
+
return tag === "ArrayBuffer" ? ab : new Uint8Array(ab, value.byteOffset || 0, value.length != null ? value.length : ab.byteLength);
|
|
4607
|
+
}
|
|
4608
|
+
return tag === "ArrayBuffer" ? new ArrayBuffer(0) : new Uint8Array(0);
|
|
4609
|
+
}
|
|
4565
4610
|
const u = fetchTransfer(value.refId) || latin1ToBytes(globalThis.atob(value.b64 || ""));
|
|
4566
4611
|
return tag === "ArrayBuffer" ? u.buffer : u;
|
|
4567
4612
|
});
|
|
@@ -4585,15 +4630,16 @@
|
|
|
4585
4630
|
this._handle = globalThis.__csim_workerSpawn(this.url) | 0;
|
|
4586
4631
|
if (this._handle > 0) byHandle.set(this._handle, this);
|
|
4587
4632
|
}
|
|
4588
|
-
postMessage(data,
|
|
4633
|
+
postMessage(data, transferList) {
|
|
4589
4634
|
if (this._handle <= 0) return;
|
|
4590
4635
|
let payload;
|
|
4591
4636
|
try {
|
|
4592
|
-
payload = encode(data);
|
|
4637
|
+
payload = encode(data, transferSetFrom(transferList));
|
|
4593
4638
|
} catch (_) {
|
|
4594
4639
|
payload = "null";
|
|
4595
4640
|
}
|
|
4596
4641
|
globalThis.__csim_workerPostToWorker(this._handle, payload);
|
|
4642
|
+
detachTransferables(transferList);
|
|
4597
4643
|
}
|
|
4598
4644
|
terminate() {
|
|
4599
4645
|
if (this._handle <= 0) return;
|
|
@@ -4658,14 +4704,15 @@
|
|
|
4658
4704
|
globalThis.DedicatedWorkerGlobalScope = globalThis.DedicatedWorkerGlobalScope || /* @__PURE__ */ __name(function DedicatedWorkerGlobalScope() {
|
|
4659
4705
|
}, "DedicatedWorkerGlobalScope");
|
|
4660
4706
|
if (typeof globalThis.postMessage !== "function") {
|
|
4661
|
-
globalThis.postMessage = function(data,
|
|
4707
|
+
globalThis.postMessage = function(data, transferList) {
|
|
4662
4708
|
let payload;
|
|
4663
4709
|
try {
|
|
4664
|
-
payload = encode(data);
|
|
4710
|
+
payload = encode(data, transferSetFrom(transferList));
|
|
4665
4711
|
} catch (_) {
|
|
4666
4712
|
payload = "null";
|
|
4667
4713
|
}
|
|
4668
4714
|
globalThis.__csim_workerPostMessage(payload);
|
|
4715
|
+
detachTransferables(transferList);
|
|
4669
4716
|
};
|
|
4670
4717
|
}
|
|
4671
4718
|
globalThis.importScripts = function(...urls) {
|
|
@@ -4780,6 +4827,10 @@
|
|
|
4780
4827
|
this.lastModified = i.lastModified || Date.now();
|
|
4781
4828
|
}
|
|
4782
4829
|
};
|
|
4830
|
+
function utf8Latin1(s) {
|
|
4831
|
+
return bytesToLatin1(new globalThis.TextEncoder().encode(String(s)));
|
|
4832
|
+
}
|
|
4833
|
+
__name(utf8Latin1, "utf8Latin1");
|
|
4783
4834
|
function serializeMultipart(formData) {
|
|
4784
4835
|
const boundary = "----csimFormBoundary" + Math.random().toString(36).slice(2);
|
|
4785
4836
|
let body = "";
|
|
@@ -4788,13 +4839,13 @@
|
|
|
4788
4839
|
if (value instanceof Blob) {
|
|
4789
4840
|
const filename = value.name != null ? String(value.name) : "blob";
|
|
4790
4841
|
const contentType = value.type || "application/octet-stream";
|
|
4791
|
-
body += 'Content-Disposition: form-data; name="' + key + '"; filename="' + filename + '"\r\n';
|
|
4842
|
+
body += 'Content-Disposition: form-data; name="' + utf8Latin1(key) + '"; filename="' + utf8Latin1(filename) + '"\r\n';
|
|
4792
4843
|
body += "Content-Type: " + contentType + "\r\n\r\n";
|
|
4793
4844
|
body += blobBytes(value);
|
|
4794
4845
|
body += "\r\n";
|
|
4795
4846
|
} else {
|
|
4796
|
-
body += 'Content-Disposition: form-data; name="' + key + '"\r\n\r\n';
|
|
4797
|
-
body +=
|
|
4847
|
+
body += 'Content-Disposition: form-data; name="' + utf8Latin1(key) + '"\r\n\r\n';
|
|
4848
|
+
body += utf8Latin1(value) + "\r\n";
|
|
4798
4849
|
}
|
|
4799
4850
|
});
|
|
4800
4851
|
body += "--" + boundary + "--\r\n";
|
|
@@ -5450,7 +5501,8 @@
|
|
|
5450
5501
|
get(_t, prop) {
|
|
5451
5502
|
if (prop === "cssText") return el._attrs.style || "";
|
|
5452
5503
|
if (prop === "getPropertyValue") return (name) => readCssProp(el, String(name));
|
|
5453
|
-
if (prop === "
|
|
5504
|
+
if (prop === "getPropertyPriority") return (name) => readCssPriority(el, String(name));
|
|
5505
|
+
if (prop === "setProperty") return (n, v, priority) => writeCssProp(el, String(n), String(v), priority);
|
|
5454
5506
|
if (prop === "removeProperty") return (name) => removeCssProp(el, String(name));
|
|
5455
5507
|
if (prop === "length") return Object.keys(parsedDecls(el)).length;
|
|
5456
5508
|
if (typeof prop !== "string") return void 0;
|
|
@@ -5467,7 +5519,7 @@
|
|
|
5467
5519
|
return true;
|
|
5468
5520
|
},
|
|
5469
5521
|
has(_t, prop) {
|
|
5470
|
-
if (prop === "cssText" || prop === "getPropertyValue" || prop === "setProperty" || prop === "removeProperty" || prop === "length") return true;
|
|
5522
|
+
if (prop === "cssText" || prop === "getPropertyValue" || prop === "getPropertyPriority" || prop === "setProperty" || prop === "removeProperty" || prop === "length") return true;
|
|
5471
5523
|
return readCssProp(el, camelToKebab(String(prop))) !== "";
|
|
5472
5524
|
}
|
|
5473
5525
|
};
|
|
@@ -5487,17 +5539,34 @@
|
|
|
5487
5539
|
return el._declCache;
|
|
5488
5540
|
}
|
|
5489
5541
|
__name(parsedDecls, "parsedDecls");
|
|
5542
|
+
var IMPORTANT_SUFFIX_RE = /\s*!\s*important\s*$/i;
|
|
5543
|
+
function stripImportant(v) {
|
|
5544
|
+
if (typeof v !== "string" || v.indexOf("!") < 0) return v;
|
|
5545
|
+
return v.replace(IMPORTANT_SUFFIX_RE, "").trim();
|
|
5546
|
+
}
|
|
5547
|
+
__name(stripImportant, "stripImportant");
|
|
5490
5548
|
function readCssProp(el, name) {
|
|
5491
5549
|
const decls = parsedDecls(el);
|
|
5492
|
-
return decls[name] != null ? decls[name] : "";
|
|
5550
|
+
return decls[name] != null ? stripImportant(decls[name]) : "";
|
|
5493
5551
|
}
|
|
5494
5552
|
__name(readCssProp, "readCssProp");
|
|
5495
|
-
function
|
|
5553
|
+
function readCssPriority(el, name) {
|
|
5554
|
+
const v = parsedDecls(el)[name];
|
|
5555
|
+
return v != null && splitImportant(v).important ? "important" : "";
|
|
5556
|
+
}
|
|
5557
|
+
__name(readCssPriority, "readCssPriority");
|
|
5558
|
+
function writeCssProp(el, name, value, priority) {
|
|
5496
5559
|
const decls = parseStyleDecls(el._attrs.style || "");
|
|
5497
5560
|
if (value === "" || value == null) {
|
|
5498
5561
|
delete decls[name];
|
|
5499
5562
|
} else {
|
|
5500
|
-
|
|
5563
|
+
let v = String(value);
|
|
5564
|
+
if (/^\s*important\s*$/i.test(String(priority == null ? "" : priority))) {
|
|
5565
|
+
v = stripImportant(v) + " !important";
|
|
5566
|
+
} else if (priority != null && priority !== "") {
|
|
5567
|
+
return;
|
|
5568
|
+
}
|
|
5569
|
+
decls[name] = v;
|
|
5501
5570
|
}
|
|
5502
5571
|
el.setAttribute("style", serializeStyleDecls(decls));
|
|
5503
5572
|
}
|
|
@@ -5620,10 +5689,9 @@
|
|
|
5620
5689
|
const inlineStyle = el._attrs.style;
|
|
5621
5690
|
if (inlineStyle) {
|
|
5622
5691
|
const m = /(^|;|\s)display\s*:\s*([^;]+)/i.exec(inlineStyle);
|
|
5623
|
-
if (m) return m[2].trim();
|
|
5692
|
+
if (m) return stripImportant(m[2].trim());
|
|
5624
5693
|
}
|
|
5625
|
-
if (el._attrs.hidden != null) return "none";
|
|
5626
|
-
if (matchesAnyHideRule(el)) return "none";
|
|
5694
|
+
if (matchesAnyHideRule(el, true, null, el._attrs.hidden != null)) return "none";
|
|
5627
5695
|
return DEFAULT_DISPLAY[el._tag] || "block";
|
|
5628
5696
|
}
|
|
5629
5697
|
__name(computedDisplayFor, "computedDisplayFor");
|
|
@@ -5631,7 +5699,7 @@
|
|
|
5631
5699
|
const inlineStyle = el._attrs.style;
|
|
5632
5700
|
if (inlineStyle) {
|
|
5633
5701
|
const m = /(^|;|\s)visibility\s*:\s*([^;]+)/i.exec(inlineStyle);
|
|
5634
|
-
if (m) return m[2].trim();
|
|
5702
|
+
if (m) return stripImportant(m[2].trim());
|
|
5635
5703
|
}
|
|
5636
5704
|
return "";
|
|
5637
5705
|
}
|
|
@@ -10030,6 +10098,15 @@
|
|
|
10030
10098
|
};
|
|
10031
10099
|
return list;
|
|
10032
10100
|
}
|
|
10101
|
+
// HTML lets you assign a `FileList` to a file input programmatically — the
|
|
10102
|
+
// canonical pattern is `input.files = dataTransfer.files` (drag-drop libraries,
|
|
10103
|
+
// and the kamalog `attach-images` Stimulus controller, do exactly this). Accept
|
|
10104
|
+
// any array-like of File objects; null/undefined clears the selection.
|
|
10105
|
+
set files(value) {
|
|
10106
|
+
if (this._tag !== "input") return;
|
|
10107
|
+
if ((this._attrs.type || "").toLowerCase() !== "file") return;
|
|
10108
|
+
this._files = value == null ? [] : Array.from(value);
|
|
10109
|
+
}
|
|
10033
10110
|
get innerHTML() {
|
|
10034
10111
|
return serializeChildren(this);
|
|
10035
10112
|
}
|
|
@@ -10843,8 +10920,8 @@
|
|
|
10843
10920
|
function windowNamedLookup(name) {
|
|
10844
10921
|
const doc = globalThis.document;
|
|
10845
10922
|
if (!doc) return void 0;
|
|
10846
|
-
const
|
|
10847
|
-
if (
|
|
10923
|
+
const byId3 = doc.getElementById && doc.getElementById(name);
|
|
10924
|
+
if (byId3) return byId3;
|
|
10848
10925
|
if (!WINDOW_NAME_VALUES.has(name)) return void 0;
|
|
10849
10926
|
let found;
|
|
10850
10927
|
walkSubtree(doc, (el) => {
|
|
@@ -13162,7 +13239,7 @@
|
|
|
13162
13239
|
|
|
13163
13240
|
// lib/capybara/simulated/js/src/abort.js
|
|
13164
13241
|
function defaultAbortReason() {
|
|
13165
|
-
return new
|
|
13242
|
+
return new DOMException2("signal is aborted without reason", "AbortError");
|
|
13166
13243
|
}
|
|
13167
13244
|
__name(defaultAbortReason, "defaultAbortReason");
|
|
13168
13245
|
var AbortSignal = class _AbortSignal extends EventTarget {
|
|
@@ -13194,7 +13271,7 @@
|
|
|
13194
13271
|
// AbortSignal.timeout(ms)}` is the canonical timeout idiom.
|
|
13195
13272
|
static timeout(ms) {
|
|
13196
13273
|
const s = new _AbortSignal();
|
|
13197
|
-
globalThis.setTimeout(() => s._markAborted(new
|
|
13274
|
+
globalThis.setTimeout(() => s._markAborted(new DOMException2("signal timed out", "TimeoutError")), Number(ms) || 0);
|
|
13198
13275
|
return s;
|
|
13199
13276
|
}
|
|
13200
13277
|
// Spec: returns a signal that aborts when any input signal aborts.
|
|
@@ -14137,6 +14214,113 @@
|
|
|
14137
14214
|
};
|
|
14138
14215
|
globalThis.EventSource = EventSource;
|
|
14139
14216
|
|
|
14217
|
+
// lib/capybara/simulated/js/src/websocket.js
|
|
14218
|
+
var byId2 = /* @__PURE__ */ new Map();
|
|
14219
|
+
globalThis.__csim_webSocketById = byId2;
|
|
14220
|
+
var WebSocket = class extends EventTarget {
|
|
14221
|
+
static {
|
|
14222
|
+
__name(this, "WebSocket");
|
|
14223
|
+
}
|
|
14224
|
+
constructor(url, protocols) {
|
|
14225
|
+
super();
|
|
14226
|
+
this.url = String(url);
|
|
14227
|
+
this.readyState = 0;
|
|
14228
|
+
this.bufferedAmount = 0;
|
|
14229
|
+
this.extensions = "";
|
|
14230
|
+
this.protocol = "";
|
|
14231
|
+
this.binaryType = "blob";
|
|
14232
|
+
this.onopen = null;
|
|
14233
|
+
this.onmessage = null;
|
|
14234
|
+
this.onclose = null;
|
|
14235
|
+
this.onerror = null;
|
|
14236
|
+
const list = protocols == null ? [] : Array.isArray(protocols) ? protocols.map(String) : [String(protocols)];
|
|
14237
|
+
this._id = globalThis.__csim_wsOpen(this.url, list) | 0;
|
|
14238
|
+
if (this._id > 0) byId2.set(this._id, this);
|
|
14239
|
+
}
|
|
14240
|
+
send(data) {
|
|
14241
|
+
if (this.readyState === 0) throw new DOMException("Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.", "InvalidStateError");
|
|
14242
|
+
if (this.readyState !== 1) return;
|
|
14243
|
+
if (typeof data === "string") {
|
|
14244
|
+
globalThis.__csim_wsSend(this._id, data, false, false);
|
|
14245
|
+
return;
|
|
14246
|
+
}
|
|
14247
|
+
let bytes;
|
|
14248
|
+
if (data instanceof ArrayBuffer) bytes = new Uint8Array(data);
|
|
14249
|
+
else if (ArrayBuffer.isView(data)) bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
14250
|
+
else bytes = new Uint8Array(0);
|
|
14251
|
+
if (globalThis.RustyRacer) {
|
|
14252
|
+
globalThis.__csim_wsSend(this._id, bytes, true, false);
|
|
14253
|
+
} else {
|
|
14254
|
+
globalThis.__csim_wsSend(this._id, globalThis.btoa(bytesToLatin1(bytes)), true, true);
|
|
14255
|
+
}
|
|
14256
|
+
}
|
|
14257
|
+
close(code, reason) {
|
|
14258
|
+
if (this.readyState === 2 || this.readyState === 3) return;
|
|
14259
|
+
this.readyState = 2;
|
|
14260
|
+
if (this._id > 0) globalThis.__csim_wsClose(this._id, code == null ? 1e3 : code | 0, reason == null ? "" : String(reason));
|
|
14261
|
+
}
|
|
14262
|
+
};
|
|
14263
|
+
WebSocket.CONNECTING = 0;
|
|
14264
|
+
WebSocket.OPEN = 1;
|
|
14265
|
+
WebSocket.CLOSING = 2;
|
|
14266
|
+
WebSocket.CLOSED = 3;
|
|
14267
|
+
globalThis.__csim_deliverWebSocketEvents = function(events) {
|
|
14268
|
+
if (!events || !events.length) return 0;
|
|
14269
|
+
let delivered = 0;
|
|
14270
|
+
for (const e of events) {
|
|
14271
|
+
const ws = byId2.get(e.id | 0);
|
|
14272
|
+
if (!ws) continue;
|
|
14273
|
+
if (e.type === "__open") {
|
|
14274
|
+
if (ws.readyState === 0) {
|
|
14275
|
+
ws.readyState = 1;
|
|
14276
|
+
if (e.protocol) ws.protocol = String(e.protocol);
|
|
14277
|
+
dispatchWithOnHandler(ws, new Event("open"));
|
|
14278
|
+
delivered++;
|
|
14279
|
+
}
|
|
14280
|
+
continue;
|
|
14281
|
+
}
|
|
14282
|
+
if (e.type === "__close" || e.type === "__error") {
|
|
14283
|
+
if (e.type === "__error") {
|
|
14284
|
+
const err = new Event("error");
|
|
14285
|
+
if (e.message) try {
|
|
14286
|
+
err.message = String(e.message);
|
|
14287
|
+
} catch (_) {
|
|
14288
|
+
}
|
|
14289
|
+
dispatchWithOnHandler(ws, err);
|
|
14290
|
+
}
|
|
14291
|
+
if (ws.readyState !== 3) {
|
|
14292
|
+
ws.readyState = 3;
|
|
14293
|
+
const ev = new Event("close");
|
|
14294
|
+
try {
|
|
14295
|
+
ev.code = e.code == null ? 1006 : e.code | 0;
|
|
14296
|
+
ev.reason = e.reason == null ? "" : String(e.reason);
|
|
14297
|
+
ev.wasClean = e.type === "__close" && e.code != null;
|
|
14298
|
+
} catch (_) {
|
|
14299
|
+
}
|
|
14300
|
+
dispatchWithOnHandler(ws, ev);
|
|
14301
|
+
}
|
|
14302
|
+
byId2.delete(e.id | 0);
|
|
14303
|
+
delivered++;
|
|
14304
|
+
continue;
|
|
14305
|
+
}
|
|
14306
|
+
let data;
|
|
14307
|
+
if (e.binary) {
|
|
14308
|
+
const bytes = fetchedToBytes(e.data) || new Uint8Array(0);
|
|
14309
|
+
if (ws.binaryType === "arraybuffer") {
|
|
14310
|
+
data = bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength ? bytes.buffer : bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
14311
|
+
} else {
|
|
14312
|
+
data = typeof globalThis.Blob === "function" ? new globalThis.Blob([bytes]) : bytes.buffer;
|
|
14313
|
+
}
|
|
14314
|
+
} else {
|
|
14315
|
+
data = e.data == null ? "" : e.data;
|
|
14316
|
+
}
|
|
14317
|
+
dispatchWithOnHandler(ws, new MessageEvent("message", { data, origin: ws.url }));
|
|
14318
|
+
delivered++;
|
|
14319
|
+
}
|
|
14320
|
+
return delivered;
|
|
14321
|
+
};
|
|
14322
|
+
globalThis.WebSocket = WebSocket;
|
|
14323
|
+
|
|
14140
14324
|
// lib/capybara/simulated/js/src/request-body.js
|
|
14141
14325
|
function setContentTypeIfMissing(headers, value) {
|
|
14142
14326
|
if (!("Content-Type" in headers) && !("content-type" in headers)) {
|
|
@@ -14518,6 +14702,18 @@
|
|
|
14518
14702
|
if (spec && Array.isArray(spec.fields)) {
|
|
14519
14703
|
for (const pair of spec.fields) this._entries.push([String(pair[0]), String(pair[1])]);
|
|
14520
14704
|
}
|
|
14705
|
+
if (spec && Array.isArray(spec.fileInputs)) {
|
|
14706
|
+
const File2 = globalThis.File;
|
|
14707
|
+
for (const fi of spec.fileInputs) {
|
|
14708
|
+
const el = lookup(fi.handle);
|
|
14709
|
+
const files = el && el.files;
|
|
14710
|
+
if (files && files.length) {
|
|
14711
|
+
for (const f of files) this._entries.push([String(fi.name), f]);
|
|
14712
|
+
} else if (File2) {
|
|
14713
|
+
this._entries.push([String(fi.name), new File2([], "", { type: "application/octet-stream" })]);
|
|
14714
|
+
}
|
|
14715
|
+
}
|
|
14716
|
+
}
|
|
14521
14717
|
if (submitter && submitter._attrs && submitter._attrs.name) {
|
|
14522
14718
|
this._entries.push([String(submitter._attrs.name), String(submitter._attrs.value || "")]);
|
|
14523
14719
|
}
|
|
@@ -15546,7 +15742,12 @@
|
|
|
15546
15742
|
continue;
|
|
15547
15743
|
}
|
|
15548
15744
|
if (type === "file") {
|
|
15549
|
-
|
|
15745
|
+
const files = (f._files || []).map((file) => ({
|
|
15746
|
+
name: String(file.name || ""),
|
|
15747
|
+
handle: file && file._csimHost ? file._handle : null,
|
|
15748
|
+
index: file && file._csimHost ? file._index : null
|
|
15749
|
+
}));
|
|
15750
|
+
fileInputs.push({ name, handle: f._id, files });
|
|
15550
15751
|
continue;
|
|
15551
15752
|
}
|
|
15552
15753
|
fields.push([name, f._attrs.value != null ? f._attrs.value : ""]);
|
|
@@ -17779,7 +17980,16 @@
|
|
|
17779
17980
|
this.dropEffect = "none";
|
|
17780
17981
|
this.effectAllowed = "all";
|
|
17781
17982
|
this.types = [];
|
|
17782
|
-
|
|
17983
|
+
}
|
|
17984
|
+
// `files` is the FileList view of the file-kind items — derived so it stays in
|
|
17985
|
+
// sync however items were added (`items.add(file)`, drag-drop construction, …).
|
|
17986
|
+
get files() {
|
|
17987
|
+
const out = [];
|
|
17988
|
+
for (const it of this.items) if (it.kind === "file" && it._file) out.push(it._file);
|
|
17989
|
+
out.item = function(i) {
|
|
17990
|
+
return this[i] || null;
|
|
17991
|
+
};
|
|
17992
|
+
return out;
|
|
17783
17993
|
}
|
|
17784
17994
|
getData(type) {
|
|
17785
17995
|
for (const it of this.items) if (it.kind === "string" && it.type === type) return it._value;
|
|
@@ -17885,7 +18095,55 @@
|
|
|
17885
18095
|
}
|
|
17886
18096
|
};
|
|
17887
18097
|
globalThis.BroadcastChannel = BroadcastChannel;
|
|
18098
|
+
globalThis.__csimTransferDropAll = function(tokens) {
|
|
18099
|
+
const NS = globalThis.RustyRacer;
|
|
18100
|
+
if (!tokens || !NS || typeof NS.transferDrop !== "function") return;
|
|
18101
|
+
for (let i = 0; i < tokens.length; i++) NS.transferDrop(tokens[i]);
|
|
18102
|
+
};
|
|
17888
18103
|
var __csimWindowProxies = /* @__PURE__ */ new Map();
|
|
18104
|
+
function csimMaybeTransferOut(data, transfer) {
|
|
18105
|
+
if (!transfer || !transfer.length) return null;
|
|
18106
|
+
const NS = globalThis.RustyRacer;
|
|
18107
|
+
if (!NS || typeof NS.transferOut !== "function") return null;
|
|
18108
|
+
const isAB = data instanceof ArrayBuffer;
|
|
18109
|
+
const isView = !isAB && ArrayBuffer.isView(data);
|
|
18110
|
+
if (!isAB && !isView) return null;
|
|
18111
|
+
const buf = isAB ? data : data.buffer;
|
|
18112
|
+
let inList = false;
|
|
18113
|
+
for (let i = 0; i < transfer.length; i++) {
|
|
18114
|
+
const t = transfer[i];
|
|
18115
|
+
if (t === buf || t && t.buffer === buf) {
|
|
18116
|
+
inList = true;
|
|
18117
|
+
break;
|
|
18118
|
+
}
|
|
18119
|
+
}
|
|
18120
|
+
if (!inList) return null;
|
|
18121
|
+
const token = NS.transferOut(data) | 0;
|
|
18122
|
+
if (token <= 0) return null;
|
|
18123
|
+
if (globalThis.__csim_transferIssued) globalThis.__csim_transferIssued(token);
|
|
18124
|
+
return isAB ? { __csimXfer: token, kind: "ArrayBuffer" } : {
|
|
18125
|
+
__csimXfer: token,
|
|
18126
|
+
kind: data.constructor && data.constructor.name || "Uint8Array",
|
|
18127
|
+
byteOffset: data.byteOffset,
|
|
18128
|
+
length: data.length
|
|
18129
|
+
};
|
|
18130
|
+
}
|
|
18131
|
+
__name(csimMaybeTransferOut, "csimMaybeTransferOut");
|
|
18132
|
+
function csimMaybeTransferIn(data) {
|
|
18133
|
+
if (!data || typeof data !== "object" || data.__csimXfer == null) return data;
|
|
18134
|
+
const NS = globalThis.RustyRacer;
|
|
18135
|
+
if (!NS || typeof NS.transferIn !== "function") return data;
|
|
18136
|
+
const ab = NS.transferIn(data.__csimXfer);
|
|
18137
|
+
if (!ab) return new ArrayBuffer(0);
|
|
18138
|
+
if (data.kind === "ArrayBuffer") return ab;
|
|
18139
|
+
const Ctor = globalThis[data.kind] || globalThis.Uint8Array;
|
|
18140
|
+
try {
|
|
18141
|
+
return new Ctor(ab, data.byteOffset || 0, data.length);
|
|
18142
|
+
} catch (_) {
|
|
18143
|
+
return new Uint8Array(ab);
|
|
18144
|
+
}
|
|
18145
|
+
}
|
|
18146
|
+
__name(csimMaybeTransferIn, "csimMaybeTransferIn");
|
|
17889
18147
|
function csimWindowProxy(handle) {
|
|
17890
18148
|
if (handle == null || handle === "") return null;
|
|
17891
18149
|
let proxy = __csimWindowProxies.get(handle);
|
|
@@ -17925,8 +18183,10 @@
|
|
|
17925
18183
|
// lost — fine for the JSON-ish payloads postMessage carries in practice.
|
|
17926
18184
|
// `targetOrigin` is accepted but, like the single-origin model elsewhere,
|
|
17927
18185
|
// not enforced.
|
|
17928
|
-
postMessage(data, targetOrigin,
|
|
17929
|
-
|
|
18186
|
+
postMessage(data, targetOrigin, transfer) {
|
|
18187
|
+
const xfer = csimMaybeTransferOut(data, transfer);
|
|
18188
|
+
globalThis.__csimWindowPostMessage(handle, xfer || data, String(targetOrigin == null ? "*" : targetOrigin));
|
|
18189
|
+
detachTransferables(transfer);
|
|
17930
18190
|
},
|
|
17931
18191
|
get location() {
|
|
17932
18192
|
return location;
|
|
@@ -17972,7 +18232,7 @@
|
|
|
17972
18232
|
for (const ev of events) {
|
|
17973
18233
|
const source = ev && ev.sourceHandle ? csimWindowProxy(ev.sourceHandle) : null;
|
|
17974
18234
|
dispatchWithOnHandler(globalThis, new MessageEvent("message", {
|
|
17975
|
-
data: ev ? ev.data : void 0,
|
|
18235
|
+
data: csimMaybeTransferIn(ev ? ev.data : void 0),
|
|
17976
18236
|
origin: ev && ev.origin || "",
|
|
17977
18237
|
source,
|
|
17978
18238
|
lastEventId: "",
|
|
@@ -18966,7 +19226,7 @@
|
|
|
18966
19226
|
(function() {
|
|
18967
19227
|
"use strict";
|
|
18968
19228
|
globalThis.Event = Event;
|
|
18969
|
-
globalThis.DOMException =
|
|
19229
|
+
globalThis.DOMException = DOMException2;
|
|
18970
19230
|
globalThis.CustomEvent = CustomEvent;
|
|
18971
19231
|
globalThis.MouseEvent = MouseEvent;
|
|
18972
19232
|
globalThis.KeyboardEvent = KeyboardEvent;
|
|
@@ -19731,7 +19991,6 @@
|
|
|
19731
19991
|
if (it.kind === "file") {
|
|
19732
19992
|
const file = { name: it.name, type: "", size: 0 };
|
|
19733
19993
|
dt.items.push(new globalThis.DataTransferItem("file", "application/octet-stream", null, file));
|
|
19734
|
-
dt.files.push(file);
|
|
19735
19994
|
if (!dt.types.includes("Files")) dt.types.push("Files");
|
|
19736
19995
|
} else {
|
|
19737
19996
|
dt.items.push(new globalThis.DataTransferItem("string", it.type, it.value, null));
|
|
@@ -19798,7 +20057,6 @@
|
|
|
19798
20057
|
function __isTabbable(el) {
|
|
19799
20058
|
if (!el || el.nodeType !== NODE_ELEMENT) return false;
|
|
19800
20059
|
if (el._attrs.disabled != null) return false;
|
|
19801
|
-
if (el._attrs.hidden != null) return false;
|
|
19802
20060
|
if (selfHidden(el)) return false;
|
|
19803
20061
|
const ti = el._attrs.tabindex;
|
|
19804
20062
|
if (ti != null) {
|
|
@@ -66,6 +66,9 @@ module Capybara
|
|
|
66
66
|
'__csim_logConsole' => ->(b, *a) { b.log_console(a[0], a[1]); nil },
|
|
67
67
|
'__csim_eventSourceOpen' => ->(b, *a) { b.event_source_open(a[0]) },
|
|
68
68
|
'__csim_eventSourceClose' => ->(b, *a) { b.event_source_close(a[0]); nil },
|
|
69
|
+
'__csim_wsOpen' => ->(b, *a) { b.ws_open(a[0], a[1]) },
|
|
70
|
+
'__csim_wsSend' => ->(b, *a) { b.ws_send(a[0], a[1], a[2], a[3]); nil },
|
|
71
|
+
'__csim_wsClose' => ->(b, *a) { b.ws_close(a[0], a[1], a[2]); nil },
|
|
69
72
|
'__csim_rackFetchAsync' => ->(b, *a) { b.rack_fetch_async(a[0], a[1], a[2], a[3]) },
|
|
70
73
|
'__csim_rackFetchAsyncAbort' => ->(b, *a) { b.rack_fetch_async_abort(a[0]); nil },
|
|
71
74
|
# Cross-window references (window.open / opener / postMessage). Each
|
|
@@ -87,6 +90,8 @@ module Capybara
|
|
|
87
90
|
'__csim_blobUnregister' => ->(b, *a) { b.blob_unregister(a[0]); nil },
|
|
88
91
|
'__csim_transferStash' => ->(b, *a) { b.transfer_buffer_stash(a[0]) },
|
|
89
92
|
'__csim_transferFetch' => ->(b, *a) { b.transfer_buffer_fetch_for_js(a[0]) },
|
|
93
|
+
# Zero-copy postMessage transfer-token bookkeeping (see Browser#drop_pending_transfers).
|
|
94
|
+
'__csim_transferIssued' => ->(b, *a) { b.transfer_token_issued(a[0]); nil },
|
|
90
95
|
'__csim_decodeVideoFrame' => ->(b, *a) { b.decode_video_frame(a[0]) },
|
|
91
96
|
'__csim_encodeImage' => ->(b, *a) { b.encode_image(a[0], a[1], a[2], a[3], a[4]) },
|
|
92
97
|
# WebAuthn create / get raise `WebauthnState::Error` carrying
|
|
@@ -411,13 +411,20 @@ module Capybara
|
|
|
411
411
|
# keeps the new realm's `parent`/`top` wired to the owning realm. The
|
|
412
412
|
# Browser then re-points the iframe element at the new id (`__csimRebindFrameRealm`).
|
|
413
413
|
def reload_frame_realm(old_id, parent_id, url, body, content_type)
|
|
414
|
-
|
|
415
|
-
@realm_module_handles&.delete(old_id)
|
|
416
|
-
fr.dispose rescue nil
|
|
417
|
-
end
|
|
414
|
+
dispose_frame_realm(old_id)
|
|
418
415
|
create_frame_realm(ctx, url, body, content_type, parent_id)
|
|
419
416
|
end
|
|
420
417
|
|
|
418
|
+
# Tear down a single frame realm (e.g. a descendant frame destroyed when an
|
|
419
|
+
# ancestor frame re-navigates). No-op for nil/0/unknown ids.
|
|
420
|
+
def dispose_frame_realm(id)
|
|
421
|
+
return if id.nil? || id.zero?
|
|
422
|
+
@realm_module_handles&.delete(id)
|
|
423
|
+
fr = frame_realms.delete(id)
|
|
424
|
+
fr.dispose rescue nil if fr
|
|
425
|
+
nil
|
|
426
|
+
end
|
|
427
|
+
|
|
421
428
|
# One native microtask checkpoint — a checkpoint runs the queue until
|
|
422
429
|
# empty, and rusty already performs one at the end of every top-level
|
|
423
430
|
# eval/call (V8's default kAuto policy), so a single explicit checkpoint
|