-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add BigInt64Array shim for Safari 14 #17103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kripken
merged 50 commits into
emscripten-core:main
from
hoodmane:bigint64array-safari14-shim
Jun 27, 2022
Merged
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
9e78b25
Add BigInt64Array shim for Safari 14
hoodmane 65ea16c
Fix test
hoodmane bf504bc
Move polyfill to a separate file, add some comments
hoodmane 7649692
Fix support for indented include in parseTools.js:preprocess
hoodmane c44bc67
Address review comments
hoodmane b2a401e
Remove extra closing brace, formatting fixes
hoodmane ab54574
Polyfill BigInt64Array and BigUint64Array
hoodmane 76be232
Add newline at end of file
hoodmane 1b83731
Unindent
hoodmane 9b00c8b
Use var instead of globalThis
hoodmane 6e5df7a
Trigger CI
hoodmane 7b96688
Remove !POLYFILL guard
hoodmane 7e3c36d
Revert "Remove !POLYFILL guard"
hoodmane cd0191a
Trigger CI
hoodmane 0a4992f
Update src/polyfill/bigint64array.js
hoodmane b0fe37a
Update src/preamble.js
hoodmane c0b6169
Move polyfill to shell.js, fix buggy scope handling
hoodmane d848fad
Revert fix to parseTools
hoodmane 9991238
Try modifying default min browser settings when WASM_BIGINT is present
hoodmane 5973cc1
Add comment
hoodmane d760a5a
Fix flake8
hoodmane 07b3168
Merge branch 'main' into bigint64array-safari14-shim
hoodmane 57cd5f9
Return true from set handler
hoodmane 8ff2a51
Merge branch 'main' into bigint64array-safari14-shim
hoodmane d9cf852
Merge branch 'main' into bigint64array-safari14-shim
hoodmane e48a295
Remove uneeded stuff
hoodmane 50a642f
reduce diff
hoodmane f3af0f7
Reduce diff
hoodmane a7c9e90
Update comment
hoodmane 550664b
Update indentation
hoodmane aa60069
Remove unneeded vars
hoodmane b93d672
Remove comment
hoodmane 374b9e5
Apply sbc100's suggestion
hoodmane 134aa3e
Address sbc100's review comments
hoodmane ce8f3c4
Use BigInt constant notation
hoodmane 61a3022
Update changelog
hoodmane c964738
Add tests
hoodmane 3181088
Merge branch 'main' into bigint64array-safari14-shim
hoodmane 7ee6b31
Fix flake8
hoodmane b932ec7
Fix indentation
hoodmane d9a73d5
Merge branch 'main' into bigint64array-safari14-shim
hoodmane 5da883f
Move changelog entry
hoodmane 7f45581
Add !POLYFILL guard
hoodmane d381d6e
Remove blank line
hoodmane e6883db
Fix indentation in test
hoodmane 119a84f
Rearrange tests a bit
hoodmane 35936ce
Address some of sbc100's review comments
hoodmane a3b872c
More adjustments
hoodmane d45b70c
Use single quotes
hoodmane bb818df
Use single quotes for js strings too
hoodmane File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#if !POLYFILL | ||
assert(false, "this file should never be included unless POLYFILL is set"); | ||
#endif | ||
|
||
if (typeof globalThis.BigInt64Array === "undefined") { | ||
hoodmane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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)) << 32n); | ||
} | ||
|
||
function partsToBigIntUnsigned(lower, upper) { | ||
return BigInt(lower) | (BigInt(upper) << 32n); | ||
} | ||
|
||
function bigIntToParts(value) { | ||
var lower = Number(BigInt(value) & BigInt(0xffffffff)) | 0; | ||
var upper = Number(BigInt(value) >> 32n) | 0; | ||
return [lower, upper]; | ||
} | ||
|
||
function createBigIntArrayShim(partsToBigInt) { | ||
function createBigInt64Array(array) { | ||
if (typeof array === "number") { | ||
array = new Uint32Array(2 * array); | ||
} | ||
var orig_array; | ||
if (!ArrayBuffer.isView(array)) { | ||
if (array.constructor && array.constructor.name === "ArrayBuffer") { | ||
array = new Uint32Array(array); | ||
} else { | ||
orig_array = array; | ||
array = new Uint32Array(array.length * 2); | ||
} | ||
} | ||
var proxy = new Proxy( | ||
{ | ||
slice: function (min, max) { | ||
if (max === undefined) { | ||
max = array.length; | ||
} | ||
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]); | ||
} | ||
}, | ||
BYTES_PER_ELEMENT: 2 * array.BYTES_PER_ELEMENT, | ||
buffer: array.buffer, | ||
byteLength: array.byteLength, | ||
byteOffset: array.byteOffset, | ||
length: array.length / 2, | ||
copyWithin: function (target, start, end) { | ||
array.copyWithin(target * 2, start * 2, end * 2); | ||
return proxy; | ||
}, | ||
set: function (source, targetOffset) { | ||
if (targetOffset === undefined) { | ||
targetOffset = 0; | ||
} | ||
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 < source.length; i++) { | ||
var value = source[i]; | ||
var pair = bigIntToParts(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; | ||
}, | ||
} | ||
); | ||
if (orig_array) { | ||
proxy.set(orig_array); | ||
} | ||
return proxy; | ||
} | ||
return createBigInt64Array; | ||
} | ||
|
||
globalThis.BigUint64Array = createBigIntArrayShim(partsToBigIntUnsigned); | ||
globalThis.BigInt64Array = createBigIntArrayShim(partsToBigIntSigned); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
let result = {}; | ||
result.BigInt64Array_name = BigInt64Array.name; | ||
let arr2signed = new BigInt64Array(arr1signed.buffer); | ||
let arr2unsigned = new BigUint64Array(arr1unsigned.buffer); | ||
|
||
result.arr1_to_arr1_signed = []; | ||
for(let x of bigint_list){ | ||
arr1signed[0] = x; | ||
result.arr1_to_arr1_signed.push(arr1signed[0]); | ||
} | ||
|
||
result.arr1_to_arr1_unsigned = []; | ||
for(let x of bigint_list){ | ||
arr1unsigned[0] = x; | ||
result.arr1_to_arr1_unsigned.push(arr1unsigned[0]); | ||
} | ||
|
||
result.arr1_to_arr2_signed = []; | ||
for(let x of bigint_list){ | ||
arr1signed[0] = x; | ||
result.arr1_to_arr2_signed.push(arr2signed[0]); | ||
} | ||
|
||
result.arr1_to_arr2_unsigned = []; | ||
for(let x of bigint_list){ | ||
arr1unsigned[0] = x; | ||
result.arr1_to_arr2_unsigned.push(arr2unsigned[0]); | ||
} | ||
|
||
result.arr2_to_arr1_signed = []; | ||
for(let x of bigint_list){ | ||
arr2signed[0] = x; | ||
result.arr2_to_arr1_signed.push(arr1signed[0]); | ||
} | ||
|
||
result.arr2_to_arr1_unsigned = []; | ||
for(let x of bigint_list){ | ||
arr2unsigned[0] = x; | ||
result.arr2_to_arr1_unsigned.push(arr1unsigned[0]); | ||
} | ||
|
||
|
||
result.assertEquals = []; | ||
function assertEqual(cb){ | ||
result.assertEquals.push([cb.toString(), cb()]); | ||
} | ||
|
||
let arr1 = arr1unsigned; | ||
let arr2 = arr2unsigned; | ||
assertEqual(() => [arr2.BYTES_PER_ELEMENT, arr1.BYTES_PER_ELEMENT]); | ||
assertEqual(() => [arr2.byteLength, arr1.byteLength]); | ||
assertEqual(() => [arr2.length, arr1.length]); | ||
assertEqual(() => [arr2.slice().length, arr1.slice().length]); | ||
assertEqual(() => [arr2.slice(1, 5).length, arr1.slice(1, 5).length]); | ||
|
||
arr1[0] = 1n; arr1[1] = 2n; arr1[2] = 3n; arr1[3] = 4n; arr1[4] = 5n; | ||
|
||
result.arr2_slice = Array.from(arr2.slice(1, 5)); | ||
result.arr2_subarray = Array.from(arr2.subarray(1, 5)); | ||
let reducer = (k, v) => typeof v === 'bigint' ? v.toString() + 'n' : v; | ||
function arraytostring(arr){ | ||
return JSON.stringify(Array.from(Array.from(arr)), reducer); | ||
} | ||
|
||
let sub = arr2.subarray(1, 5); | ||
assertEqual(() => [sub.byteOffset, 8]); | ||
sub[0] = 7n; sub[1] = 77n; sub[2] = 3n; sub[3] = 66n; | ||
assertEqual(() => [arraytostring(arr1.slice(0, 5)), '["1n","7n","77n","3n","66n"]']); | ||
|
||
arr1[2] = 62n; | ||
assertEqual(() => [sub[1], 62n]); | ||
|
||
let slice = arr2.slice(1, 5); | ||
assertEqual(() => [slice.byteOffset, 0]); | ||
|
||
slice[0] = 777n; slice[1] = 666n; slice[2] = 555n; | ||
assertEqual(() => [arraytostring(arr1.slice(0, 5)), '["1n","7n","62n","3n","66n"]']); | ||
|
||
arr2.set([2n, 4n, 8n]); | ||
assertEqual(() => [arraytostring(arr1.slice(0, 3)), '["2n","4n","8n"]']); | ||
|
||
arr2.set([1n, 3n, 7n], 6); | ||
assertEqual(() => [arraytostring(arr1.slice(6, 9)), '["1n","3n","7n"]']); | ||
|
||
arr1[15] = 111n; arr1[18] = 171n; arr1[19] = 629n; | ||
|
||
assertEqual(() => [arraytostring(arr2.slice(-1)), '["629n"]']); | ||
assertEqual(() => [arraytostring(arr2.slice(-5, -1)), '["111n","0n","0n","171n"]']); | ||
assertEqual(() => [arraytostring(arr2.slice(-5, -6)), '[]']); | ||
|
||
arr3 = new BigUint64Array(Array.from({length:5}, (_, idx) => BigInt(idx))); | ||
assertEqual(() => [arraytostring(arr3), '["0n","1n","2n","3n","4n"]']); | ||
arr3.copyWithin(0, 2, 10); | ||
assertEqual(() => [arraytostring(arr3), '["2n","3n","4n","3n","4n"]']); | ||
|
||
console.log(JSON.stringify(result, reducer)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.