pyodide/emsdk/patches/0002-Add-BigInt64Array-shim...

163 lines
6.5 KiB
Diff

From 458c78230e6dd45d724b04904f15628c570ae904 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Wed, 8 Jun 2022 19:08:18 -0700
Subject: [PATCH 2/4] Add BigInt64Array shim for Safari 14
---
src/polyfill/bigint64array.js | 94 +++++++++++++++++++++++++++++++++++
src/preamble.js | 2 +-
src/settings.js | 4 ++
src/shell.js | 7 ++-
4 files changed, 105 insertions(+), 2 deletions(-)
create mode 100644 src/polyfill/bigint64array.js
diff --git a/src/polyfill/bigint64array.js b/src/polyfill/bigint64array.js
new file mode 100644
index 000000000..448a2d2a4
--- /dev/null
+++ b/src/polyfill/bigint64array.js
@@ -0,0 +1,94 @@
+// BigInt ==> globalThis so we can use globalThis.
+var BigInt64Array;
+var BigUint64Array;
+if (typeof globalThis.BigInt64Array !== "undefined") {
+ BigInt64Array = globalThis.BigInt64Array;
+ BigUint64Array = globalThis.BigUint64Array;
+} else {
+ // BigInt64Array polyfill for Safari versions between v14.0 and v15.0.
+ // All browsers other than Safari added BigInt and BigInt64Array at the same
+ // time, but Safari introduced BigInt in v14.0 and introduced BigInt64Array in
+ // v15.0
+
+ function partsToBigIntSigned(lower, upper) {
+ return BigInt(lower) | (BigInt(upper + 2 * (upper & 0x80000000)) << BigInt(32));
+ }
+
+ function partsToBigIntUnsigned(lower, upper) {
+ return BigInt(lower) | (BigInt(upper) << BigInt(32));
+ }
+
+ function bigIntToParts(value) {
+ var lower = Number(BigInt(value) & BigInt(0xffffffff)) | 0;
+ var upper = (Number(BigInt(value) >> BigInt(32)) | 0);
+ return [lower, upper];
+ }
+
+ function createBigIntArrayShim(partsToBigInt) {
+ function createBigInt64Array(array) {
+ if(!ArrayBuffer.isView(array)){
+ array = new Uint32Array(array);
+ }
+ let proxy = new Proxy({
+ slice: function(min, max) {
+ var new_buf = array.slice(min * 2, max *2);
+ return createBigInt64Array(new_buf);
+ },
+ subarray: function(min, max) {
+ var new_buf = array.subarray(min * 2, max *2);
+ return createBigInt64Array(new_buf);
+ },
+ [Symbol.iterator]: function*() {
+ for (var i = 0; i < (array.length)/2; i++) {
+ yield partsToBigInt(array[2*i], array[2*i+1]);
+ }
+ },
+ buffer : array.buffer,
+ byteLength : array.byteLength,
+ offset : array.byteOffset / 2,
+ copyWithin: function(target, start, end) {
+ array.copyWithin(target*2, start * 2, end*2);
+ return proxy;
+ },
+ set: function(source, targetOffset) {
+ if (2*(source.length + targetOffset) > array.length) {
+ // This is the Chrome error message
+ // Firefox: "invalid or out-of-range index"
+ throw new RangeError("offset is out of bounds");
+ }
+ for (var i = 0; i < array.length; i++) {
+ var value = source[i];
+ var pair = bigIntToParts(BigInt(value));
+ array.set(pair, 2*(targetOffset + i));
+ }
+ }
+ }, {
+ get: function(target, idx, receiver) {
+ if (typeof idx !== "string" || !/^\d+$/.test(idx)) {
+ return Reflect.get(target, idx, receiver);
+ }
+ var lower = array[idx * 2];
+ var upper = array[idx * 2 + 1];
+ return partsToBigInt(lower, upper);
+ },
+ set: function(target, idx, value, receiver) {
+ if (typeof idx !== "string" || !/^\d+$/.test(idx)) {
+ return Reflect.set(target, idx, value, receiver);
+ }
+ if (typeof value !== "bigint") {
+ // Chrome error message, Firefox has no "a" in front if "BigInt".
+ throw new TypeError(`Cannot convert ${value} to a BigInt`);
+ }
+ var pair = bigIntToParts(value);
+ array.set(pair, 2*idx);
+ return true;
+ }
+ });
+ return proxy;
+ }
+ return createBigInt64Array;
+ }
+
+ var BigUint64Array = createBigIntArrayShim(partsToBigIntUnsigned);
+ var BigInt64Array = createBigIntArrayShim(partsToBigIntSigned);
+}
diff --git a/src/preamble.js b/src/preamble.js
index ce24d8456..618ccd2ac 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -297,7 +297,7 @@ function updateGlobalBufferAndViews(buf) {
#if WASM_BIGINT
Module['HEAP64'] = HEAP64 = new BigInt64Array(buf);
Module['HEAPU64'] = HEAPU64 = new BigUint64Array(buf);
-#endif
+#endif // WASM_BIGINT
}
var TOTAL_STACK = {{{ TOTAL_STACK }}};
diff --git a/src/settings.js b/src/settings.js
index 1a8b7f1fe..be5964519 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -1341,6 +1341,10 @@ var DYNCALLS = false;
// WebAssembly integration with JavaScript BigInt. When enabled we don't need
// to legalize i64s into pairs of i32s, as the wasm VM will use a BigInt where
// an i64 is used.
+// If WASM_BIGINT is present, the default minimum browser versions increase to
+// Safari v15.0, Firefox v68, and Edge v79. It is possible to use WASM_BIGINT
+// with Safari >= v14.0, in that case Emscripten will polyfill BigInt64Array.
+// Use `-sMIN_SAFARI_VERSION=140000` to request this.
// [link]
var WASM_BIGINT = false;
diff --git a/src/shell.js b/src/shell.js
index 22fac7f69..9d7558340 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -51,7 +51,12 @@ var Module = typeof {{{ EXPORT_NAME }}} != 'undefined' ? {{{ EXPORT_NAME }}} : {
#if MIN_CHROME_VERSION < 45 || MIN_EDGE_VERSION < 12 || MIN_FIREFOX_VERSION < 34 || MIN_IE_VERSION != TARGET_NOT_SUPPORTED || MIN_SAFARI_VERSION < 90000
#include "polyfill/objassign.js"
#endif
-#endif // POLYFILL
+#endif
+
+// See https://caniuse.com/mdn-javascript_builtins_bigint64array
+#if WASM_BIGINT && MIN_SAFARI_VERSION < 150000
+#include "polyfill/bigint64array.js"
+#endif // MIN_SAFARI_VERSION < 15000// POLYFILL
#if MODULARIZE
// Set up the promise that indicates the Module is initialized
--
2.25.1