Skip to content
This repository was archived by the owner on Jun 22, 2023. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 73 additions & 10 deletions polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,90 @@
helpers.push(h);
}

function ToBigInt64(value) {
let n = BigInt(value);
let int64bit = n % (2n ** 64n);
if (int64bit > (2n ** 63n)) {
return int64bit - (2n ** 64n);
}
return int64bit;
}

function ToInteger(value) {
let number = Number(value);
if (number !== number) {
return 0;
}
if (number === 0 || !Number.isFinite(number)) {
return number;
}

return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
}

function ToLength(value) {
var len = ToInteger(value);
if (len <= 0) {
return 0;
}
if (len > Number.MAX_SAFE_INTEGER) {
return Number.MAX_SAFE_INTEGER;
}
return len;
}

function ToIndex(value) {
let index;
if (value === undefined) {
index = 0;
} else {
let integerIndex = ToInteger(value);
if (integerIndex < 0) {
throw new RangeError('Index out of range');
}
index = ToLength(integerIndex);
if (integerIndex !== index) {
throw new RangeError('Index out of range');
}
}
return index;
}

function ValidateAtomicAccess(typedArray, requestIndex) {
let accessIndex;
try {
accessIndex = ToIndex(requestIndex);
} catch (error) {
if (error instanceof RangeError) {
throw new RangeError('Invalid atomic access index');
}
}
let length = typedArray.length;
if (accessIndex >= length) {
throw new RangeError('Invalid atomic access index');
}
return accessIndex;
}

// Atomics.waitAsync always returns a promise. Throws standard errors
// for parameter validation. The promise is resolved with a string as from
// Atomics.wait, or, in the case something went completely wrong, it is
// rejected with an error string.

function waitAsync(ia, index_, value_, timeout_) {
if (typeof ia != "object" || !(ia instanceof Int32Array) || !(ia.buffer instanceof SharedArrayBuffer))
throw new TypeError("Expected shared memory");
if (typeof ia != "object" ||
(!(ia instanceof Int32Array) && !(ia instanceof BigInt64Array)) ||
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ia instanceof TypedArray line should use:

TypedArrayProto_getToStringTag(ia) !== undefined

Which is defined using:

var TypedArrayProto_getToStringTag = Function.prototype.call.bind(
	Object.getOwnPropertyDescriptor(
		Object.getPrototypeOf(Uint8Array.prototype),
		Symbol.toStringTag,
	).get,
);

Refs: https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag

!(ia.buffer instanceof SharedArrayBuffer)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the ia.buffer instanceof SharedArrayBuffer line should instead use:

IsSharedArrayBuffer(ia.buffer)

Which is defined using:

var SharedArrayBufferProto_getByteLength = Function.prototype.call.bind(
	Object.getOwnPropertyDescriptor(
		SharedArrayBuffer.prototype,
		"byteLength",
	).get,
);

function IsSharedArrayBuffer(obj) {
	try {
		SharedArrayBufferProto_getByteLength(obj);
		return true;
	} catch (e) {
		return false;
	}
}

throw new TypeError("Expected shared memory");
}

// These conversions only approximate the desired semantics but are
// close enough for the polyfill.

let index = index_|0;
let value = value_|0;
let index = ValidateAtomicAccess(ia, index_);
let coersion = ia instanceof BigInt64Array ? (v => ToBigInt64(v)) : (v => v|0);
let value = coersion(value_);
let timeout = timeout_ === undefined ? Infinity : +timeout_;

// Range checking for the index.

ia[index];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is replaced by ValidateAtomicAccess(...)


// Optimization, avoid the helper thread in this common case.

if (Atomics.load(ia, index) != value)
Expand Down Expand Up @@ -136,4 +200,3 @@
writable: true,
});
})();