@salve-software/react-native-nitro-jsdom 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/CMakeLists.txt +4 -0
- package/cpp/HybridHtmlSandbox.cpp +7 -3
- package/cpp/lexbor/LexborDocument.cpp +62 -0
- package/cpp/lexbor/LexborDocument.hpp +14 -0
- package/cpp/quickjs/DOMBindings.cpp +9 -1
- package/cpp/quickjs/DOMBindingsInternal.cpp +67 -0
- package/cpp/quickjs/DOMBindingsInternal.hpp +39 -0
- package/cpp/quickjs/QuickJSRuntime.cpp +13 -0
- package/cpp/quickjs/QuickJSRuntime.hpp +28 -0
- package/cpp/quickjs/bindings/AbortBindings.cpp +14 -0
- package/cpp/quickjs/bindings/BlobBindings.cpp +28 -1
- package/cpp/quickjs/bindings/BlobBindings.hpp +3 -3
- package/cpp/quickjs/bindings/CSSOMBindings.cpp +46 -0
- package/cpp/quickjs/bindings/CSSOMBindings.hpp +3 -1
- package/cpp/quickjs/bindings/DOMParserBindings.cpp +299 -0
- package/cpp/quickjs/bindings/DOMParserBindings.hpp +45 -0
- package/cpp/quickjs/bindings/DocumentBindings.cpp +166 -11
- package/cpp/quickjs/bindings/ElementBindings.cpp +296 -20
- package/cpp/quickjs/bindings/EventBindings.cpp +277 -5
- package/cpp/quickjs/bindings/EventBindings.hpp +3 -0
- package/cpp/quickjs/bindings/EventTargetBindings.cpp +75 -0
- package/cpp/quickjs/bindings/EventTargetBindings.hpp +24 -0
- package/cpp/quickjs/bindings/FetchBindings.cpp +43 -8
- package/cpp/quickjs/bindings/FormBindings.cpp +223 -0
- package/cpp/quickjs/bindings/FormBindings.hpp +9 -5
- package/cpp/quickjs/bindings/LayoutStubBindings.cpp +104 -0
- package/cpp/quickjs/bindings/LayoutStubBindings.hpp +28 -0
- package/cpp/quickjs/bindings/LiveCollectionBindings.cpp +45 -0
- package/cpp/quickjs/bindings/TimerBindings.cpp +79 -0
- package/cpp/quickjs/bindings/TreeWalkerBindings.cpp +306 -0
- package/cpp/quickjs/bindings/TreeWalkerBindings.hpp +28 -0
- package/cpp/quickjs/bindings/UrlBindings.cpp +9 -0
- package/cpp/quickjs/bindings/WindowBindings.cpp +286 -4
- package/cpp/quickjs/bindings/WindowBindings.hpp +3 -2
- package/package.json +17 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#include "WindowBindings.hpp"
|
|
2
2
|
#include "DOMExceptionBindings.hpp"
|
|
3
|
+
#include "EventBindings.hpp"
|
|
3
4
|
#include "../DOMBindingsInternal.hpp"
|
|
4
5
|
#include "../QuickJSRuntime.hpp"
|
|
6
|
+
#include <cstdlib>
|
|
5
7
|
#include <cstring>
|
|
6
8
|
#include <optional>
|
|
7
|
-
#include <random>
|
|
8
9
|
#include <string>
|
|
9
10
|
#include <vector>
|
|
10
11
|
|
|
@@ -191,6 +192,23 @@ JSValue js_console_method(JSContext* ctx, JSValue, int argc, JSValue* argv, int
|
|
|
191
192
|
return JS_UNDEFINED;
|
|
192
193
|
}
|
|
193
194
|
|
|
195
|
+
JSValue js_window_reportError(JSContext* ctx, JSValue, int argc, JSValue* argv) {
|
|
196
|
+
JSValue error_value = argc >= 1 ? argv[0] : JS_UNDEFINED;
|
|
197
|
+
std::string message = "Uncaught";
|
|
198
|
+
if (argc >= 1) {
|
|
199
|
+
JSValue msg_prop = JS_GetPropertyStr(ctx, argv[0], "message");
|
|
200
|
+
if (!JS_IsException(msg_prop) && !JS_IsUndefined(msg_prop)) {
|
|
201
|
+
const char* s = JS_ToCString(ctx, msg_prop);
|
|
202
|
+
if (s) { message = s; JS_FreeCString(ctx, s); }
|
|
203
|
+
} else if (JS_IsException(msg_prop)) {
|
|
204
|
+
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
205
|
+
}
|
|
206
|
+
JS_FreeValue(ctx, msg_prop);
|
|
207
|
+
}
|
|
208
|
+
EventBindings::dispatchErrorEvent(ctx, message, error_value);
|
|
209
|
+
return JS_UNDEFINED;
|
|
210
|
+
}
|
|
211
|
+
|
|
194
212
|
// ── window.alert / confirm / prompt ───────────────────────────────────────────
|
|
195
213
|
|
|
196
214
|
JSValue js_window_alert(JSContext* ctx, JSValue, int argc, JSValue* argv) {
|
|
@@ -346,12 +364,12 @@ JSValue js_native_random_bytes(JSContext* ctx, JSValue, int argc, JSValue* argv)
|
|
|
346
364
|
if (argc >= 1) JS_ToInt32(ctx, &count, argv[0]);
|
|
347
365
|
if (count < 0) count = 0;
|
|
348
366
|
|
|
349
|
-
|
|
350
|
-
|
|
367
|
+
std::vector<uint8_t> bytes(static_cast<size_t>(count));
|
|
368
|
+
if (count > 0) arc4random_buf(bytes.data(), bytes.size());
|
|
351
369
|
|
|
352
370
|
JSValue arr = JS_NewArray(ctx);
|
|
353
371
|
for (int32_t i = 0; i < count; i++) {
|
|
354
|
-
JS_SetPropertyUint32(ctx, arr, static_cast<uint32_t>(i), JS_NewInt32(ctx,
|
|
372
|
+
JS_SetPropertyUint32(ctx, arr, static_cast<uint32_t>(i), JS_NewInt32(ctx, bytes[static_cast<size_t>(i)]));
|
|
355
373
|
}
|
|
356
374
|
return arr;
|
|
357
375
|
}
|
|
@@ -373,6 +391,67 @@ const char* kCryptoBootstrapScript = R"JS(
|
|
|
373
391
|
for (var i = 0; i < bytes.length; i++) view[i] = bytes[i];
|
|
374
392
|
return typedArray;
|
|
375
393
|
};
|
|
394
|
+
globalThis.crypto.randomUUID = function() {
|
|
395
|
+
var bytes = __nativeRandomBytes(16);
|
|
396
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
397
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
398
|
+
var hex = [];
|
|
399
|
+
for (var i = 0; i < 16; i++) {
|
|
400
|
+
var h = bytes[i].toString(16);
|
|
401
|
+
hex.push(h.length === 1 ? '0' + h : h);
|
|
402
|
+
}
|
|
403
|
+
return hex.slice(0, 4).join('') + '-' + hex.slice(4, 6).join('') + '-' +
|
|
404
|
+
hex.slice(6, 8).join('') + '-' + hex.slice(8, 10).join('') + '-' + hex.slice(10, 16).join('');
|
|
405
|
+
};
|
|
406
|
+
})();
|
|
407
|
+
)JS";
|
|
408
|
+
|
|
409
|
+
// ── console ergonomics (group/table/assert/trace/count) ──────────────────────
|
|
410
|
+
// Layered in pure JS on top of the native log/warn/error/info/debug methods
|
|
411
|
+
// above rather than adding new native levels — none of these need anything
|
|
412
|
+
// the onConsole callback can't already receive as stringified args.
|
|
413
|
+
|
|
414
|
+
const char* kConsoleExtrasBootstrapScript = R"JS(
|
|
415
|
+
(function() {
|
|
416
|
+
var counts = Object.create(null);
|
|
417
|
+
|
|
418
|
+
console.group = function() {
|
|
419
|
+
console.log.apply(console, arguments);
|
|
420
|
+
};
|
|
421
|
+
console.groupCollapsed = console.group;
|
|
422
|
+
console.groupEnd = function() {};
|
|
423
|
+
|
|
424
|
+
console.trace = function() {
|
|
425
|
+
var args = Array.prototype.slice.call(arguments);
|
|
426
|
+
args.unshift('Trace:');
|
|
427
|
+
console.log.apply(console, args);
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
console.assert = function(condition) {
|
|
431
|
+
if (condition) return;
|
|
432
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
433
|
+
args.unshift('Assertion failed:');
|
|
434
|
+
console.error.apply(console, args);
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
console.table = function(data) {
|
|
438
|
+
try {
|
|
439
|
+
console.log(JSON.stringify(data));
|
|
440
|
+
} catch (e) {
|
|
441
|
+
console.log(String(data));
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
console.count = function(label) {
|
|
446
|
+
label = label === undefined ? 'default' : String(label);
|
|
447
|
+
counts[label] = (counts[label] || 0) + 1;
|
|
448
|
+
console.log(label + ': ' + counts[label]);
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
console.countReset = function(label) {
|
|
452
|
+
label = label === undefined ? 'default' : String(label);
|
|
453
|
+
counts[label] = 0;
|
|
454
|
+
};
|
|
376
455
|
})();
|
|
377
456
|
)JS";
|
|
378
457
|
|
|
@@ -389,10 +468,184 @@ const char* kNavigatorBootstrapScript = R"JS(
|
|
|
389
468
|
cookieEnabled: false,
|
|
390
469
|
hardwareConcurrency: 1,
|
|
391
470
|
};
|
|
471
|
+
navigator.sendBeacon = function(url, data) {
|
|
472
|
+
try {
|
|
473
|
+
fetch(url, { method: 'POST', body: data }).catch(function() {});
|
|
474
|
+
} catch (e) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
return true;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
// jsdom itself doesn't implement the Clipboard API at all (no OS clipboard
|
|
481
|
+
// to back it, same reasoning as window.history/getSelection). This is an
|
|
482
|
+
// in-memory stand-in purely so 'copy discount code'-style embedded widgets
|
|
483
|
+
// that call navigator.clipboard.writeText() directly don't throw — reads
|
|
484
|
+
// back whatever was last written, nothing more.
|
|
485
|
+
var clipboardText = '';
|
|
486
|
+
navigator.clipboard = {
|
|
487
|
+
writeText: function(text) {
|
|
488
|
+
clipboardText = String(text);
|
|
489
|
+
return Promise.resolve();
|
|
490
|
+
},
|
|
491
|
+
readText: function() {
|
|
492
|
+
return Promise.resolve(clipboardText);
|
|
493
|
+
},
|
|
494
|
+
};
|
|
495
|
+
|
|
392
496
|
globalThis.navigator = navigator;
|
|
393
497
|
})();
|
|
394
498
|
)JS";
|
|
395
499
|
|
|
500
|
+
// ── structuredClone ────────────────────────────────────────────────────────
|
|
501
|
+
|
|
502
|
+
const char* kStructuredCloneBootstrapScript = R"JS(
|
|
503
|
+
(function() {
|
|
504
|
+
globalThis.structuredClone = function(value) {
|
|
505
|
+
var seen = new Map();
|
|
506
|
+
function clone(v) {
|
|
507
|
+
if (v === null || typeof v !== 'object') {
|
|
508
|
+
if (typeof v === 'function' || typeof v === 'symbol') {
|
|
509
|
+
throw new DOMException(String(v) + ' could not be cloned.', 'DataCloneError');
|
|
510
|
+
}
|
|
511
|
+
return v;
|
|
512
|
+
}
|
|
513
|
+
if (seen.has(v)) return seen.get(v);
|
|
514
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
515
|
+
if (v instanceof RegExp) return new RegExp(v.source, v.flags);
|
|
516
|
+
if (Array.isArray(v)) {
|
|
517
|
+
var arr = [];
|
|
518
|
+
seen.set(v, arr);
|
|
519
|
+
for (var i = 0; i < v.length; i++) arr.push(clone(v[i]));
|
|
520
|
+
return arr;
|
|
521
|
+
}
|
|
522
|
+
if (v instanceof Map) {
|
|
523
|
+
var m = new Map();
|
|
524
|
+
seen.set(v, m);
|
|
525
|
+
v.forEach(function(val, key) { m.set(clone(key), clone(val)); });
|
|
526
|
+
return m;
|
|
527
|
+
}
|
|
528
|
+
if (v instanceof Set) {
|
|
529
|
+
var s = new Set();
|
|
530
|
+
seen.set(v, s);
|
|
531
|
+
v.forEach(function(val) { s.add(clone(val)); });
|
|
532
|
+
return s;
|
|
533
|
+
}
|
|
534
|
+
if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView && ArrayBuffer.isView(v)) {
|
|
535
|
+
return new v.constructor(v);
|
|
536
|
+
}
|
|
537
|
+
if (typeof ArrayBuffer !== 'undefined' && v instanceof ArrayBuffer) {
|
|
538
|
+
return v.slice(0);
|
|
539
|
+
}
|
|
540
|
+
var proto = Object.getPrototypeOf(v);
|
|
541
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
542
|
+
throw new DOMException('The object could not be cloned.', 'DataCloneError');
|
|
543
|
+
}
|
|
544
|
+
var out = {};
|
|
545
|
+
seen.set(v, out);
|
|
546
|
+
for (var key in v) {
|
|
547
|
+
if (Object.prototype.hasOwnProperty.call(v, key)) out[key] = clone(v[key]);
|
|
548
|
+
}
|
|
549
|
+
return out;
|
|
550
|
+
}
|
|
551
|
+
return clone(value);
|
|
552
|
+
};
|
|
553
|
+
})();
|
|
554
|
+
)JS";
|
|
555
|
+
|
|
556
|
+
// ── window.history ────────────────────────────────────────────────────────
|
|
557
|
+
// No real page navigation exists in this sandbox, so History tracks its own
|
|
558
|
+
// in-memory entry stack rather than session history. pushState/replaceState
|
|
559
|
+
// never fire popstate (per spec); go/back/forward do, since those are the
|
|
560
|
+
// events CMS-widget routers actually listen for. `title` is accepted but
|
|
561
|
+
// ignored (same as jsdom — nothing renders a document title). State is
|
|
562
|
+
// structuredClone()'d on write (per spec — matches pushState/replaceState's
|
|
563
|
+
// documented "serializable" semantics), so callers mutating their object
|
|
564
|
+
// after the call can't leak into a stored entry. `go()`'s delta is truncated
|
|
565
|
+
// to an integer so a fractional/NaN input can't produce a non-integer
|
|
566
|
+
// `_index`.
|
|
567
|
+
|
|
568
|
+
const char* kHistoryBootstrapScript = R"JS(
|
|
569
|
+
(function() {
|
|
570
|
+
function History() {
|
|
571
|
+
this._entries = [null];
|
|
572
|
+
this._index = 0;
|
|
573
|
+
}
|
|
574
|
+
Object.defineProperty(History.prototype, 'length', {
|
|
575
|
+
get: function() { return this._entries.length; },
|
|
576
|
+
enumerable: true,
|
|
577
|
+
});
|
|
578
|
+
Object.defineProperty(History.prototype, 'state', {
|
|
579
|
+
get: function() { return this._entries[this._index]; },
|
|
580
|
+
enumerable: true,
|
|
581
|
+
});
|
|
582
|
+
function cloneState(state) {
|
|
583
|
+
return state === undefined ? null : structuredClone(state);
|
|
584
|
+
}
|
|
585
|
+
History.prototype.pushState = function(state, _title, url) {
|
|
586
|
+
this._entries = this._entries.slice(0, this._index + 1);
|
|
587
|
+
this._entries.push(cloneState(state));
|
|
588
|
+
this._index++;
|
|
589
|
+
if (url !== undefined && url !== null) location.href = url;
|
|
590
|
+
};
|
|
591
|
+
History.prototype.replaceState = function(state, _title, url) {
|
|
592
|
+
this._entries[this._index] = cloneState(state);
|
|
593
|
+
if (url !== undefined && url !== null) location.href = url;
|
|
594
|
+
};
|
|
595
|
+
History.prototype.go = function(delta) {
|
|
596
|
+
delta = delta === undefined ? 0 : Math.trunc(Number(delta) || 0);
|
|
597
|
+
if (delta === 0) return;
|
|
598
|
+
var next = this._index + delta;
|
|
599
|
+
if (next < 0 || next > this._entries.length - 1) return;
|
|
600
|
+
this._index = next;
|
|
601
|
+
var ev = new Event('popstate');
|
|
602
|
+
ev.state = this._entries[this._index];
|
|
603
|
+
dispatchEvent(ev);
|
|
604
|
+
};
|
|
605
|
+
History.prototype.back = function() { this.go(-1); };
|
|
606
|
+
History.prototype.forward = function() { this.go(1); };
|
|
607
|
+
|
|
608
|
+
globalThis.History = History;
|
|
609
|
+
globalThis.history = new History();
|
|
610
|
+
})();
|
|
611
|
+
)JS";
|
|
612
|
+
|
|
613
|
+
// ── window.getSelection ──────────────────────────────────────────────────
|
|
614
|
+
// No layout engine backs this sandbox, so there is nothing to select — this
|
|
615
|
+
// mirrors matchMedia's stance: an always-empty Selection rather than a
|
|
616
|
+
// missing global, so defensive `window.getSelection().toString()` checks in
|
|
617
|
+
// third-party scripts don't crash the sandbox.
|
|
618
|
+
|
|
619
|
+
const char* kSelectionBootstrapScript = R"JS(
|
|
620
|
+
(function() {
|
|
621
|
+
function Selection() {}
|
|
622
|
+
Object.defineProperty(Selection.prototype, 'rangeCount', { get: function() { return 0; }, enumerable: true });
|
|
623
|
+
Object.defineProperty(Selection.prototype, 'isCollapsed', { get: function() { return true; }, enumerable: true });
|
|
624
|
+
Object.defineProperty(Selection.prototype, 'anchorNode', { get: function() { return null; }, enumerable: true });
|
|
625
|
+
Object.defineProperty(Selection.prototype, 'anchorOffset', { get: function() { return 0; }, enumerable: true });
|
|
626
|
+
Object.defineProperty(Selection.prototype, 'focusNode', { get: function() { return null; }, enumerable: true });
|
|
627
|
+
Object.defineProperty(Selection.prototype, 'focusOffset', { get: function() { return 0; }, enumerable: true });
|
|
628
|
+
Object.defineProperty(Selection.prototype, 'type', { get: function() { return 'None'; }, enumerable: true });
|
|
629
|
+
Selection.prototype.toString = function() { return ''; };
|
|
630
|
+
Selection.prototype.removeAllRanges = function() {};
|
|
631
|
+
Selection.prototype.collapse = function() {};
|
|
632
|
+
Selection.prototype.collapseToStart = function() {};
|
|
633
|
+
Selection.prototype.collapseToEnd = function() {};
|
|
634
|
+
Selection.prototype.selectAllChildren = function() {};
|
|
635
|
+
Selection.prototype.addRange = function() {};
|
|
636
|
+
Selection.prototype.containsNode = function() { return false; };
|
|
637
|
+
Selection.prototype.getRangeAt = function(index) {
|
|
638
|
+
throw new DOMException(
|
|
639
|
+
"Failed to execute 'getRangeAt' on 'Selection': " + index + ' is not a valid index.', 'IndexSizeError');
|
|
640
|
+
};
|
|
641
|
+
Selection.prototype.empty = Selection.prototype.removeAllRanges;
|
|
642
|
+
|
|
643
|
+
var selectionInstance = new Selection();
|
|
644
|
+
globalThis.Selection = Selection;
|
|
645
|
+
globalThis.getSelection = function() { return selectionInstance; };
|
|
646
|
+
})();
|
|
647
|
+
)JS";
|
|
648
|
+
|
|
396
649
|
// ── matchMedia ─────────────────────────────────────────────────────────────
|
|
397
650
|
// No layout engine backs this sandbox, so every query reports "no match" —
|
|
398
651
|
// mirrors jsdom's own stance that layout-dependent APIs return inert defaults
|
|
@@ -435,6 +688,7 @@ void WindowBindings::install(JSContext* ctx) {
|
|
|
435
688
|
JS_SetPropertyStr(ctx, global, "alert", JS_NewCFunction(ctx, js_window_alert, "alert", 1));
|
|
436
689
|
JS_SetPropertyStr(ctx, global, "confirm", JS_NewCFunction(ctx, js_window_confirm, "confirm", 1));
|
|
437
690
|
JS_SetPropertyStr(ctx, global, "prompt", JS_NewCFunction(ctx, js_window_prompt, "prompt", 2));
|
|
691
|
+
JS_SetPropertyStr(ctx, global, "reportError", JS_NewCFunction(ctx, js_window_reportError, "reportError", 1));
|
|
438
692
|
JS_SetPropertyStr(ctx, global, "atob", JS_NewCFunction(ctx, js_window_atob, "atob", 1));
|
|
439
693
|
JS_SetPropertyStr(ctx, global, "btoa", JS_NewCFunction(ctx, js_window_btoa, "btoa", 1));
|
|
440
694
|
|
|
@@ -456,6 +710,27 @@ void WindowBindings::install(JSContext* ctx) {
|
|
|
456
710
|
}
|
|
457
711
|
JS_FreeValue(ctx, location_result);
|
|
458
712
|
|
|
713
|
+
JSValue history_result = JS_Eval(ctx, kHistoryBootstrapScript, strlen(kHistoryBootstrapScript),
|
|
714
|
+
"<history-bootstrap>", JS_EVAL_TYPE_GLOBAL);
|
|
715
|
+
if (JS_IsException(history_result)) {
|
|
716
|
+
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
717
|
+
}
|
|
718
|
+
JS_FreeValue(ctx, history_result);
|
|
719
|
+
|
|
720
|
+
JSValue selection_result = JS_Eval(ctx, kSelectionBootstrapScript, strlen(kSelectionBootstrapScript),
|
|
721
|
+
"<selection-bootstrap>", JS_EVAL_TYPE_GLOBAL);
|
|
722
|
+
if (JS_IsException(selection_result)) {
|
|
723
|
+
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
724
|
+
}
|
|
725
|
+
JS_FreeValue(ctx, selection_result);
|
|
726
|
+
|
|
727
|
+
JSValue console_extras_result = JS_Eval(ctx, kConsoleExtrasBootstrapScript, strlen(kConsoleExtrasBootstrapScript),
|
|
728
|
+
"<console-extras-bootstrap>", JS_EVAL_TYPE_GLOBAL);
|
|
729
|
+
if (JS_IsException(console_extras_result)) {
|
|
730
|
+
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
731
|
+
}
|
|
732
|
+
JS_FreeValue(ctx, console_extras_result);
|
|
733
|
+
|
|
459
734
|
JSValue crypto_result = JS_Eval(ctx, kCryptoBootstrapScript, strlen(kCryptoBootstrapScript),
|
|
460
735
|
"<crypto-bootstrap>", JS_EVAL_TYPE_GLOBAL);
|
|
461
736
|
if (JS_IsException(crypto_result)) {
|
|
@@ -476,6 +751,13 @@ void WindowBindings::install(JSContext* ctx) {
|
|
|
476
751
|
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
477
752
|
}
|
|
478
753
|
JS_FreeValue(ctx, match_media_result);
|
|
754
|
+
|
|
755
|
+
JSValue structured_clone_result = JS_Eval(ctx, kStructuredCloneBootstrapScript, strlen(kStructuredCloneBootstrapScript),
|
|
756
|
+
"<structured-clone-bootstrap>", JS_EVAL_TYPE_GLOBAL);
|
|
757
|
+
if (JS_IsException(structured_clone_result)) {
|
|
758
|
+
JS_FreeValue(ctx, JS_GetException(ctx));
|
|
759
|
+
}
|
|
760
|
+
JS_FreeValue(ctx, structured_clone_result);
|
|
479
761
|
}
|
|
480
762
|
|
|
481
763
|
} // namespace margelo::nitro::nitrojsdom
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
// window.alert/confirm/prompt (bridged to onAlert/onConfirm/onPrompt native
|
|
4
|
-
// callbacks), console.log/warn/error/info/debug, and the window.location
|
|
5
|
-
//
|
|
4
|
+
// callbacks), console.log/warn/error/info/debug, and the window.location,
|
|
5
|
+
// window.history, window.getSelection, crypto, navigator, matchMedia, and
|
|
6
|
+
// structuredClone bootstrap scripts.
|
|
6
7
|
|
|
7
8
|
#include "quickjs.h"
|
|
8
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salve-software/react-native-nitro-jsdom",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"packageManager": "yarn@4.9.1",
|
|
5
5
|
"description": "A headless HTML/DOM environment for React Native.",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
@@ -24,7 +24,22 @@
|
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"react-native",
|
|
27
|
-
"
|
|
27
|
+
"react-native-jsdom",
|
|
28
|
+
"react-native-nitro-jsdom",
|
|
29
|
+
"nitro-modules",
|
|
30
|
+
"nitro",
|
|
31
|
+
"expo",
|
|
32
|
+
"jsdom",
|
|
33
|
+
"dom",
|
|
34
|
+
"html",
|
|
35
|
+
"html-parser",
|
|
36
|
+
"quickjs",
|
|
37
|
+
"lexbor",
|
|
38
|
+
"sandbox",
|
|
39
|
+
"headless-browser",
|
|
40
|
+
"webview-alternative",
|
|
41
|
+
"ios",
|
|
42
|
+
"android"
|
|
28
43
|
],
|
|
29
44
|
"files": [
|
|
30
45
|
"src",
|