icecat: add release icecat-140.10.1-1gnu1 for ecne
This commit is contained in:
parent
a5f93cb214
commit
ff85d7c623
1256 changed files with 63469 additions and 24141 deletions
|
|
@ -169,8 +169,14 @@ JSObject* ModuleLoaderBase::HostResolveImportedModule(
|
|||
bool ModuleLoaderBase::ImportMetaResolve(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedValue modulePrivate(
|
||||
cx, js::GetFunctionNativeReserved(&args.callee(), ModulePrivateSlot));
|
||||
RootedValue moduleValue(
|
||||
cx, js::GetFunctionNativeReserved(
|
||||
&args.callee(),
|
||||
static_cast<size_t>(ModuleRecordSlot)));
|
||||
MOZ_ASSERT(!moduleValue.isUndefined());
|
||||
RootedObject moduleRecord(cx, &moduleValue.toObject());
|
||||
RootedValue modulePrivate(cx, GetModulePrivate(moduleRecord));
|
||||
MOZ_ASSERT(!modulePrivate.isUndefined());
|
||||
|
||||
// https://html.spec.whatwg.org/#hostgetimportmetaproperties
|
||||
// Step 4.1. Set specifier to ? ToString(specifier).
|
||||
|
|
@ -280,10 +286,15 @@ bool ModuleLoaderBase::HostPopulateImportMeta(
|
|||
}
|
||||
|
||||
// Store the 'active script' of the meta object into the function slot.
|
||||
// https://html.spec.whatwg.org/#active-script
|
||||
// See https://html.spec.whatwg.org/#active-script
|
||||
//
|
||||
// Note: Hold a reference to the module record which in turn keeps the
|
||||
// ModuleScript alive when import.resolve is called.
|
||||
RootedObject resolveFuncObj(aCx, JS_GetFunctionObject(resolveFunc));
|
||||
js::SetFunctionNativeReserved(resolveFuncObj, ModulePrivateSlot,
|
||||
aReferencingPrivate);
|
||||
RootedObject moduleRecord(aCx, script->ModuleRecord());
|
||||
js::SetFunctionNativeReserved(
|
||||
resolveFuncObj, static_cast<size_t>(ModuleRecordSlot),
|
||||
JS::ObjectValue(*moduleRecord));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -557,7 +557,7 @@ class ModuleLoaderBase : public nsISupports {
|
|||
bool IsFetchingAndHasWaitingRequest(ModuleLoadRequest* aRequest);
|
||||
|
||||
// The slot stored in ImportMetaResolve function.
|
||||
enum { ModulePrivateSlot = 0, SlotCount };
|
||||
enum { ModuleRecordSlot = 0, SlotCount };
|
||||
|
||||
// The number of args in ImportMetaResolve.
|
||||
static const uint32_t ImportMetaResolveNumArgs = 1;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,12 @@ inline void SetObjectISupports(JSObject* obj, void* nsISupportsValue) {
|
|||
SetReservedSlot(obj, 0, PrivateValue(nsISupportsValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the native object has own named properties, i.e. user-added
|
||||
* properties (expandos). Must not be called on proxy objects.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool NativeObjectHasOwnProperties(const JSObject* obj);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
// JSObject* is an aligned pointer, but this information isn't available in the
|
||||
|
|
|
|||
25
icecat/js/public/friend/CycleCollector.h
Normal file
25
icecat/js/public/friend/CycleCollector.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* APIs for integration with the cycle collector.
|
||||
*/
|
||||
|
||||
#ifndef js_friend_CycleCollector_h
|
||||
#define js_friend_CycleCollector_h
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/HeapAPI.h" // JS::GCCellPtr
|
||||
|
||||
namespace JS {
|
||||
|
||||
using ShouldClearWeakRefTargetCallback = bool (*)(GCCellPtr ptr, void* data);
|
||||
|
||||
extern JS_PUBLIC_API void MaybeClearWeakRefTargets(
|
||||
JSRuntime* runtime, ShouldClearWeakRefTargetCallback callback, void* data);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_friend_CycleCollector_h
|
||||
|
|
@ -235,10 +235,10 @@ static BigInt* CreateBigInt(JSContext* cx,
|
|||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
if (y) {
|
||||
if (length > 1) {
|
||||
result->setDigit(1, y);
|
||||
}
|
||||
if (x) {
|
||||
if (length > 0) {
|
||||
result->setDigit(0, x);
|
||||
}
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1152,6 +1152,9 @@ bool DebugAPI::slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame,
|
|||
if (success && completion.get().suspending()) {
|
||||
Debugger::suspendGeneratorDebuggerFrames(cx, frame);
|
||||
} else {
|
||||
if (frame.isWasmDebugFrame()) {
|
||||
DebugEnvironments::onPopWasm(cx, frame);
|
||||
}
|
||||
Debugger::terminateDebuggerFrames(cx, frame);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "builtin/FinalizationRegistryObject.h"
|
||||
#include "builtin/WeakRefObject.h"
|
||||
#include "gc/GCRuntime.h"
|
||||
#include "gc/PublicIterators.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
|
|
@ -517,3 +518,34 @@ void FinalizationRegistryGlobalData::removeRecord(
|
|||
void FinalizationRegistryGlobalData::trace(JSTracer* trc) {
|
||||
recordSet.trace(trc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void JS::MaybeClearWeakRefTargets(
|
||||
JSRuntime* runtime, JS::ShouldClearWeakRefTargetCallback callback,
|
||||
void* data) {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime));
|
||||
AssertHeapIsIdle();
|
||||
runtime->gc.maybeClearWeakRefTargets(callback, data);
|
||||
}
|
||||
|
||||
void GCRuntime::maybeClearWeakRefTargets(
|
||||
JS::ShouldClearWeakRefTargetCallback callback, void* data) {
|
||||
for (AllZonesIter zone(this); !zone.done(); zone.next()) {
|
||||
FinalizationObservers* observers = zone->finalizationObservers();
|
||||
if (observers) {
|
||||
observers->maybeClearWeakRefTargets(callback, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinalizationObservers::maybeClearWeakRefTargets(
|
||||
JS::ShouldClearWeakRefTargetCallback callback, void* data) {
|
||||
for (auto iter = weakRefMap.modIter(); !iter.done(); iter.next()) {
|
||||
JSObject* target = iter.get().key();
|
||||
if (callback(JS::GCCellPtr(target), data)) {
|
||||
for (JSObject* obj : iter.get().value()) {
|
||||
updateForRemovedWeakRef(obj, UnwrapWeakRef(obj));
|
||||
}
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "gc/Barrier.h"
|
||||
#include "gc/WeakMap.h"
|
||||
#include "gc/ZoneAllocator.h"
|
||||
#include "js/friend/CycleCollector.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/GCVector.h"
|
||||
|
||||
|
|
@ -81,6 +82,8 @@ class FinalizationObservers {
|
|||
bool addWeakRefTarget(Handle<JSObject*> target, Handle<JSObject*> weakRef);
|
||||
void removeWeakRefTarget(Handle<JSObject*> target,
|
||||
Handle<WeakRefObject*> weakRef);
|
||||
void maybeClearWeakRefTargets(JS::ShouldClearWeakRefTargetCallback callback,
|
||||
void* data);
|
||||
|
||||
void unregisterWeakRefWrapper(JSObject* wrapper, WeakRefObject* weakRef);
|
||||
|
||||
|
|
|
|||
|
|
@ -2194,8 +2194,11 @@ void GCRuntime::decommitEmptyChunks(const bool& cancel, AutoLockGC& lock) {
|
|||
break;
|
||||
}
|
||||
|
||||
// Check whether something used the chunk while lock was released.
|
||||
if (!CanDecommitWholeChunk(chunk)) {
|
||||
// Check whether something used the chunk while the lock was released. The
|
||||
// chunk may have been taken from the empty chunks pool (e.g. adopted as
|
||||
// the current chunk, or repurposed as a nursery/buffer chunk), so we must
|
||||
// verify it is still a member of the pool before removing it.
|
||||
if (!emptyChunks(lock).contains(chunk) || !CanDecommitWholeChunk(chunk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "gc/Scheduling.h"
|
||||
#include "gc/Statistics.h"
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "js/friend/CycleCollector.h"
|
||||
#include "js/friend/PerformanceHint.h"
|
||||
#include "js/GCAnnotations.h"
|
||||
#include "js/UniquePtr.h"
|
||||
|
|
@ -108,13 +109,15 @@ class ChunkPool {
|
|||
|
||||
void sort();
|
||||
|
||||
// Linear time, use with caution.
|
||||
bool contains(ArenaChunk* chunk) const;
|
||||
|
||||
private:
|
||||
ArenaChunk* mergeSort(ArenaChunk* list, size_t count);
|
||||
bool isSorted() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
public:
|
||||
bool contains(ArenaChunk* chunk) const;
|
||||
bool verify() const;
|
||||
void verifyChunks() const;
|
||||
#endif
|
||||
|
|
@ -686,6 +689,9 @@ class GCRuntime {
|
|||
bool registerWeakRef(HandleObject target, HandleObject weakRef);
|
||||
void traceKeptObjects(JSTracer* trc);
|
||||
|
||||
void maybeClearWeakRefTargets(JS::ShouldClearWeakRefTargetCallback callback,
|
||||
void* data);
|
||||
|
||||
JS::GCReason lastStartReason() const { return initialReason; }
|
||||
|
||||
void updateAllocationRates();
|
||||
|
|
|
|||
|
|
@ -696,10 +696,11 @@ bool ChunkPool::isSorted() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
bool ChunkPool::contains(ArenaChunk* chunk) const {
|
||||
#ifdef DEBUG
|
||||
verify();
|
||||
#endif
|
||||
|
||||
for (ArenaChunk* cursor = head_; cursor; cursor = cursor->info.next) {
|
||||
if (cursor == chunk) {
|
||||
return true;
|
||||
|
|
@ -708,6 +709,8 @@ bool ChunkPool::contains(ArenaChunk* chunk) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
bool ChunkPool::verify() const {
|
||||
MOZ_ASSERT(bool(head_) == bool(count_));
|
||||
uint32_t count = 0;
|
||||
|
|
|
|||
17
icecat/js/src/jit-test/tests/arguments/bug2029316.js
Normal file
17
icecat/js/src/jit-test/tests/arguments/bug2029316.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
function makeArgs() {
|
||||
"use strict";
|
||||
return arguments;
|
||||
}
|
||||
function test() {
|
||||
for (var alloc = 1; alloc < 50; alloc++) {
|
||||
var args = makeArgs(1, 2, 3);
|
||||
oomAtAllocation(alloc);
|
||||
try {
|
||||
delete args[0];
|
||||
} catch (e) {}
|
||||
resetOOMFailure();
|
||||
args[0] = "x";
|
||||
assertEq(args[0], "x");
|
||||
}
|
||||
}
|
||||
test();
|
||||
25
icecat/js/src/jit-test/tests/arguments/bug2029317.js
Normal file
25
icecat/js/src/jit-test/tests/arguments/bug2029317.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
function test() {
|
||||
var f = function() { return arguments; };
|
||||
var template = new Array(9000).fill(0);
|
||||
|
||||
var a = f.apply(null, template);
|
||||
Object.defineProperty(a, 0, {value: "v1", writable: false, configurable: true});
|
||||
|
||||
for (var alloc = 4; alloc < 15; alloc++) {
|
||||
var args = null;
|
||||
var ok = false;
|
||||
oomAtAllocation(alloc);
|
||||
try {
|
||||
args = f.apply(null, template);
|
||||
ok = true;
|
||||
Object.defineProperty(args, 0, {value: "v1", writable: false, configurable: true});
|
||||
} catch (e) {}
|
||||
resetOOMFailure();
|
||||
|
||||
if (ok) {
|
||||
Object.defineProperty(args, 0, {value: "v2"});
|
||||
assertEq(args[0], "v2");
|
||||
}
|
||||
}
|
||||
}
|
||||
test();
|
||||
14
icecat/js/src/jit-test/tests/modules/bug-2027274.js
Normal file
14
icecat/js/src/jit-test/tests/modules/bug-2027274.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// |jit-test| slow; error: InternalError: too much recursion
|
||||
var leaf = parseModule("await 0; throw 1;", "l.js");
|
||||
registerModule("l", leaf);
|
||||
moduleLink(leaf);
|
||||
moduleEvaluate(leaf);
|
||||
var p = "l";
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
var m = parseModule("import '" + p + "'; if(0) await 0;", "m" + i + ".js");
|
||||
registerModule("m" + i, m);
|
||||
moduleLink(m);
|
||||
moduleEvaluate(m);
|
||||
p = "m" + i;
|
||||
}
|
||||
drainJobQueue();
|
||||
34
icecat/js/src/jit-test/tests/structured-clone/allobjs.js
Normal file
34
icecat/js/src/jit-test/tests/structured-clone/allobjs.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
var bytes = new BigUint64Array([
|
||||
0xfff1000000000002n, // SCTAG_HEADER (version=2)
|
||||
0xffff002200000000n, // SCTAG_ERROR_OBJECT
|
||||
0xffff000480000001n, // .message = SCTAG_STRING (length=1, Latin-1)
|
||||
0x0000000000000078n, // string data: "x"
|
||||
0xffff000700000000n, // .hasCause = SCTAG_ARRAY_OBJECT (length=0) <-- INVALID!!!
|
||||
0xffff000480000002n, // .filename = SCTAG_STRING (length=2, Latin-1)
|
||||
0x000000000000652dn, // string data: "e-"
|
||||
0xffff000300000002n, // .lineNumber = SCTAG_INT32 (value=2)
|
||||
0xffff000300000011n, // .column = SCTAG_INT32 (value=17)
|
||||
0xffff000000000000n, // .cause = SCTAG_NULL
|
||||
0xffff000000000000n, // .errors = SCTAG_NULL
|
||||
0xffff0016ffff0018n, // .stack = SCTAG_SAVED_FRAME_OBJECT | SCTAG_NULL_JSPRINCIPALS
|
||||
0xffff000200000000n, // .mutedErrors = SCTAG_BOOLEAN (value=0)
|
||||
0xffff000480000002n, // .source = SCTAG_STRING (length=2, Latin-1)
|
||||
0x000000000000652dn, // string data: "e-"
|
||||
0xffff000300000002n, // .lineNumber = SCTAG_INT32 (value=2)
|
||||
0xffff000300000011n, // .columnNumber SCTAG_INT32 (value=17)
|
||||
0xffff000000000000n, // .functionDisplayName = SCTAG_NULL
|
||||
0xffff000000000000n, // .asyncCause = SCTAG_NULL
|
||||
0xffff000000000000n, // .parent = SCTAG_NULL
|
||||
0xffff001300000000n, // SCTAG_END_OF_KEYS
|
||||
0xffff001300000000n, // SCTAG_END_OF_KEYS
|
||||
]);
|
||||
var buf = serialize(null, undefined, {scope: 'DifferentProcess'});
|
||||
buf.arraybuffer = bytes.buffer;
|
||||
|
||||
var e;
|
||||
try {
|
||||
deserialize(buf);
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
assertEq(e.message.includes("hasCause must be a boolean"), true);
|
||||
177
icecat/js/src/jit-test/tests/wasm/bug2020378.js
Normal file
177
icecat/js/src/jit-test/tests/wasm/bug2020378.js
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
// |jit-test| skip-if: !wasmThreadsEnabled()
|
||||
|
||||
const m = new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(memory $m32 1 1)
|
||||
(memory $m64 i64 1 1)
|
||||
(memory $m32s 1 1 shared)
|
||||
(memory $m64s i64 1 1 shared)
|
||||
|
||||
${["", "s"].map(s => `
|
||||
(func (export "wait3232${s}") (param i32) (result i32)
|
||||
(memory.atomic.wait32 $m32${s}
|
||||
(local.get 0)
|
||||
(i32.const 0)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(func (export "wait3264${s}") (param i32) (result i32)
|
||||
(memory.atomic.wait64 $m32${s}
|
||||
(local.get 0)
|
||||
(i64.const 0)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(func (export "wait6432${s}") (param i64) (result i32)
|
||||
(memory.atomic.wait32 $m64${s}
|
||||
(local.get 0)
|
||||
(i32.const 0)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(func (export "wait6464${s}") (param i64) (result i32)
|
||||
(memory.atomic.wait64 $m64${s}
|
||||
(local.get 0)
|
||||
(i64.const 0)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(func (export "notify32${s}") (param i32) (result i32)
|
||||
(memory.atomic.notify $m32${s}
|
||||
(local.get 0)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
(func (export "notify64${s}") (param i64) (result i32)
|
||||
(memory.atomic.notify $m64${s}
|
||||
(local.get 0)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
`).join("\n")}
|
||||
)`));
|
||||
const {
|
||||
wait3232, wait3264,
|
||||
wait6432, wait6464,
|
||||
notify32, notify64,
|
||||
|
||||
wait3232s, wait3264s,
|
||||
wait6432s, wait6464s,
|
||||
notify32s, notify64s,
|
||||
} = new WebAssembly.Instance(m).exports;
|
||||
|
||||
//
|
||||
// Shared memories
|
||||
//
|
||||
|
||||
assertEq(wait3232s(0), 2);
|
||||
assertEq(wait3232s(65532), 2);
|
||||
assertErrorMessage(() => wait3232s(65533), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3232s(65536), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3232s(-8), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3232s(-4), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3232s(-3), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3232s(-2), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3232s(-1), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
assertEq(wait3264s(0), 2);
|
||||
assertEq(wait3264s(65528), 2);
|
||||
assertErrorMessage(() => wait3264s(65529), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(65536), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3264s(-16), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3264s(-8), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait3264s(-7), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-6), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-5), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-4), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-3), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-2), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264s(-1), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
assertEq(wait6432s(0n), 2);
|
||||
assertEq(wait6432s(65532n), 2);
|
||||
assertErrorMessage(() => wait6432s(65533n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6432s(65536n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n-4n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n-4n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(-4n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(-3n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6432s(-2n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6432s(-1n), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
assertEq(wait6464s(0n), 2);
|
||||
assertEq(wait6464s(65528n), 2);
|
||||
assertErrorMessage(() => wait6464s(65529n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(65536n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n-16n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**32n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n-16n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6432s(2n**33n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6464s(-16n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6464s(-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => wait6464s(-7n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-6n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-5n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-4n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-3n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-2n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464s(-1n), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
assertEq(notify32s(65532), 0);
|
||||
assertErrorMessage(() => notify32s(65533), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify32s(65536), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify32s(-8), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify32s(-4), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify32s(-3), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify32s(-2), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify32s(-1), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
assertEq(notify64s(65532n), 0);
|
||||
assertErrorMessage(() => notify64s(65533n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify64s(65536n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify64s(-8n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify64s(-4n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify64s(-3n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify64s(-2n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify64s(-1n), WebAssembly.RuntimeError, /unaligned/);
|
||||
|
||||
//
|
||||
// Non-shared memories
|
||||
//
|
||||
|
||||
assertErrorMessage(() => wait3232(65532), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait3232(65533), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3232(65536), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait3232(-4), WebAssembly.RuntimeError, /non-shared/);
|
||||
|
||||
assertErrorMessage(() => wait3264(65528), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait3264(65529), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait3264(65536), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait3264(-8), WebAssembly.RuntimeError, /non-shared/);
|
||||
|
||||
assertErrorMessage(() => wait6432(65532n), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait6432(65533n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6432(65536n), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait6432(-4n), WebAssembly.RuntimeError, /non-shared/);
|
||||
|
||||
assertErrorMessage(() => wait6464(65528n), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait6464(65529n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => wait6464(65536n), WebAssembly.RuntimeError, /non-shared/);
|
||||
assertErrorMessage(() => wait6464(-8n), WebAssembly.RuntimeError, /non-shared/);
|
||||
|
||||
assertEq(notify32(65532), 0);
|
||||
assertErrorMessage(() => notify32(65533), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify32(65536), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify32(-4), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
|
||||
assertEq(notify64(65532n), 0);
|
||||
assertErrorMessage(() => notify64(65533n), WebAssembly.RuntimeError, /unaligned/);
|
||||
assertErrorMessage(() => notify64(65536n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
assertErrorMessage(() => notify64(-4n), WebAssembly.RuntimeError, /index out of bounds/);
|
||||
|
|
@ -178,3 +178,26 @@ const { i31GetU_null, i31GetS_null } = wasmEvalText(`(module
|
|||
|
||||
assertErrorMessage(() => i31GetU_null(), WebAssembly.RuntimeError, /dereferencing null pointer/);
|
||||
assertErrorMessage(() => i31GetS_null(), WebAssembly.RuntimeError, /dereferencing null pointer/);
|
||||
|
||||
// Test i31.get_s and i31.get_u operations with some cornercases.
|
||||
let { f } = new WebAssembly.Instance(
|
||||
new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(func (export "f") (param i32) (result i32)
|
||||
(local i31ref)
|
||||
local.get 0
|
||||
ref.i31
|
||||
local.tee 1
|
||||
i31.get_s
|
||||
local.get 1
|
||||
i31.get_u
|
||||
i32.eq
|
||||
)
|
||||
)`))).exports;
|
||||
|
||||
assertEq(f(-1), 0);
|
||||
assertEq(f(-2), 0);
|
||||
assertEq(f(-0x40000000), 0);
|
||||
assertEq(f(0), 1);
|
||||
assertEq(f(1), 1);
|
||||
assertEq(f(0x3FFFFFFF), 1);
|
||||
|
|
|
|||
11
icecat/js/src/jit-test/tests/wasm/regress/bug2029735.js
Normal file
11
icecat/js/src/jit-test/tests/wasm/regress/bug2029735.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
var dummy = {abc: 1};
|
||||
// Non-Latin1 UTF-8 function name that hash-collides with the Latin1 "abc" atom.
|
||||
// The unreachable trap exercises UTF8EqualsChars when building the error message.
|
||||
var bytes = wasmTextToBinary('(module (func $"\\ee\\96\\95\\ea\\b5\\81\\04" (export "f") unreachable))');
|
||||
var ex = null;
|
||||
try {
|
||||
new WebAssembly.Instance(new WebAssembly.Module(bytes)).exports.f();
|
||||
} catch (e) {
|
||||
ex = e;
|
||||
}
|
||||
assertEq(ex.stack.includes("\uE595\uAD41\x04@"), true);
|
||||
|
|
@ -311,6 +311,16 @@ bool MAsmJSLoadHeap::congruentTo(const MDefinition* ins) const {
|
|||
return load->accessType() == accessType() && congruentIfOperandsEqual(load);
|
||||
}
|
||||
|
||||
bool MWasmI31RefGet::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isWasmI31RefGet()) {
|
||||
return false;
|
||||
}
|
||||
// Make sure that we have a signed/signed or unsigned/unsigned pair to be
|
||||
// considered congruent.
|
||||
return congruentIfOperandsEqual(ins) &&
|
||||
ins->toWasmI31RefGet()->wideningOp() == wideningOp();
|
||||
}
|
||||
|
||||
MDefinition::AliasType MWasmLoadInstanceDataField::mightAlias(
|
||||
const MDefinition* def) const {
|
||||
if (def->isWasmStoreInstanceDataField()) {
|
||||
|
|
|
|||
|
|
@ -6549,6 +6549,34 @@ MDefinition* MGuardNumberToIntPtrIndex::foldsTo(TempAllocator& alloc) {
|
|||
return MConstant::NewIntPtr(alloc, intptr_t(ival));
|
||||
}
|
||||
|
||||
AliasSet MLoadScriptedProxyHandler::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MGuardIsNativeObject::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MGuardIsProxy::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MGuardIsNotProxy::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MGuardIsNotDOMProxy::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MGuardHasProxyHandler::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MIsConstructor::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
MDefinition* MIsObject::foldsTo(TempAllocator& alloc) {
|
||||
MDefinition* input = object();
|
||||
if (!input->isBox()) {
|
||||
|
|
|
|||
|
|
@ -9051,7 +9051,9 @@ class MIsCallable : public MUnaryInstruction,
|
|||
}
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
};
|
||||
|
||||
class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
|
||||
|
|
@ -9072,7 +9074,9 @@ class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
|
|||
const JSClass* getClass() const { return class_; }
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!ins->isHasClass()) {
|
||||
return false;
|
||||
|
|
@ -9112,7 +9116,9 @@ class MGuardToClass : public MUnaryInstruction,
|
|||
}
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!ins->isGuardToClass()) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@
|
|||
result_type: Object
|
||||
guard: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
generate_lir: true
|
||||
|
||||
#ifdef JS_PUNBOX64
|
||||
|
|
@ -825,7 +825,7 @@
|
|||
wideningOp: wasm::FieldWideningOp
|
||||
type_policy: none
|
||||
result_type: Int32
|
||||
congruent_to: if_operands_equal
|
||||
congruent_to: custom
|
||||
alias_set: none
|
||||
generate_lir: true
|
||||
|
||||
|
|
@ -2161,7 +2161,7 @@
|
|||
guard: true
|
||||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardGlobalGeneration
|
||||
arguments:
|
||||
|
|
@ -2180,7 +2180,7 @@
|
|||
guard: true
|
||||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardIsNotDOMProxy
|
||||
operands:
|
||||
|
|
@ -2189,7 +2189,7 @@
|
|||
guard: true
|
||||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardIsNotProxy
|
||||
operands:
|
||||
|
|
@ -2199,7 +2199,7 @@
|
|||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
folds_to: custom
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
|
||||
- name: ProxyGet
|
||||
operands:
|
||||
|
|
@ -2401,7 +2401,7 @@
|
|||
guard: true
|
||||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
|
||||
# Loads a specific JSObject* that was originally nursery-allocated.
|
||||
# See also WarpObjectField.
|
||||
|
|
@ -2965,7 +2965,7 @@
|
|||
result_type: Boolean
|
||||
movable: true
|
||||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
alias_set: custom
|
||||
generate_lir: true
|
||||
|
||||
- name: IsCrossRealmArrayConstructor
|
||||
|
|
|
|||
|
|
@ -5765,6 +5765,7 @@ static ReturnCallTrampolineData MakeReturnCallTrampoline(MacroAssembler& masm) {
|
|||
masm.loadPtr(
|
||||
Address(masm.getStackPointer(), WasmCallerInstanceOffsetBeforeCall),
|
||||
InstanceReg);
|
||||
masm.loadWasmPinnedRegsFromInstance(mozilla::Nothing());
|
||||
masm.switchToWasmInstanceRealm(ABINonArgReturnReg0, ABINonArgReturnReg1);
|
||||
masm.moveToStackPtr(FramePointer);
|
||||
#ifdef JS_CODEGEN_ARM64
|
||||
|
|
|
|||
|
|
@ -3044,11 +3044,7 @@ class WasmStructMemoryView : public MDefinitionVisitorDefaultNoop {
|
|||
bool mergeIntoSuccessorState(MBasicBlock* curr, MBasicBlock* succ,
|
||||
BlockState** pSuccState);
|
||||
|
||||
#ifdef DEBUG
|
||||
void assertSuccess();
|
||||
#else
|
||||
void assertSuccess() {}
|
||||
#endif
|
||||
|
||||
bool oom() const { return oom_; }
|
||||
|
||||
|
|
@ -3065,15 +3061,13 @@ void WasmStructMemoryView::setEntryBlockState(BlockState* state) {
|
|||
state_ = state;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void WasmStructMemoryView::assertSuccess() {
|
||||
// Make sure that the undefined value used as a placeholder is not used.
|
||||
MOZ_ASSERT(!undefinedVal_->hasUses());
|
||||
MOZ_RELEASE_ASSERT(!undefinedVal_->hasUses());
|
||||
|
||||
// Make sure that the MWasmNewStruct instruction is not used anymore.
|
||||
MOZ_ASSERT(!struct_->hasUses());
|
||||
MOZ_RELEASE_ASSERT(!struct_->hasUses());
|
||||
}
|
||||
#endif
|
||||
|
||||
MBasicBlock* WasmStructMemoryView::startingBlock() { return startBlock_; }
|
||||
|
||||
|
|
@ -3323,7 +3317,7 @@ static bool IsWasmStructEscaped(MDefinition* ins, MInstruction* newStruct) {
|
|||
}
|
||||
case MDefinition::Opcode::WasmStoreFieldRef: {
|
||||
// Escaped if it's stored into another struct.
|
||||
if (def->toWasmStoreFieldRef()->value() == newStruct) {
|
||||
if (def->toWasmStoreFieldRef()->value() == ins) {
|
||||
JitSpewDef(JitSpew_Escape, "is escaped by\n", def);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,6 +479,10 @@ void JS::detail::SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
|
|||
}
|
||||
}
|
||||
|
||||
bool JS::NativeObjectHasOwnProperties(const JSObject* obj) {
|
||||
return !obj->as<NativeObject>().empty();
|
||||
}
|
||||
|
||||
void js::SetPreserveWrapperCallbacks(
|
||||
JSContext* cx, PreserveWrapperCallback preserveWrapper,
|
||||
HasReleasedWrapperCallback hasReleasedWrapper) {
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ EXPORTS.js.experimental += [
|
|||
# a clean design. Use this only if you absolutely must, and feel free to
|
||||
# propose clean APIs to replace what's here!
|
||||
EXPORTS.js.friend += [
|
||||
"../public/friend/CycleCollector.h",
|
||||
"../public/friend/DOMProxy.h",
|
||||
"../public/friend/DumpFunctions.h",
|
||||
"../public/friend/ErrorMessages.h",
|
||||
|
|
|
|||
|
|
@ -425,7 +425,9 @@ bool js::ProxyHas(JSContext* cx, HandleObject proxy, HandleValue idVal,
|
|||
if (!ToPropertyKey(cx, idVal, &id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(!proxy->is<ProxyObject>())) {
|
||||
return HasProperty(cx, proxy, id, result);
|
||||
}
|
||||
return Proxy::has(cx, proxy, id, result);
|
||||
}
|
||||
|
||||
|
|
@ -466,7 +468,9 @@ bool js::ProxyHasOwn(JSContext* cx, HandleObject proxy, HandleValue idVal,
|
|||
if (!ToPropertyKey(cx, idVal, &id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(!proxy->is<ProxyObject>())) {
|
||||
return HasOwnProperty(cx, proxy, id, result);
|
||||
}
|
||||
return Proxy::hasOwn(cx, proxy, id, result);
|
||||
}
|
||||
|
||||
|
|
@ -548,6 +552,9 @@ bool js::ProxyGetPropertyByValue(JSContext* cx, HandleObject proxy,
|
|||
}
|
||||
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
if (MOZ_UNLIKELY(!proxy->is<ProxyObject>())) {
|
||||
return GetProperty(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
return Proxy::getInternal(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
|
|
@ -621,7 +628,11 @@ bool js::ProxySetPropertyByValue(JSContext* cx, HandleObject proxy,
|
|||
|
||||
ObjectOpResult result;
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
if (!Proxy::setInternal(cx, proxy, id, val, receiver, result)) {
|
||||
if (MOZ_UNLIKELY(!proxy->is<ProxyObject>())) {
|
||||
if (!SetProperty(cx, proxy, id, val, receiver, result)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!Proxy::setInternal(cx, proxy, id, val, receiver, result)) {
|
||||
return false;
|
||||
}
|
||||
return result.checkStrictModeError(cx, proxy, id, strict);
|
||||
|
|
|
|||
|
|
@ -864,6 +864,12 @@ bool MappedArgumentsObject::obj_defineProperty(JSContext* cx, HandleObject obj,
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure the arguments object has RareArgumentsData so that step 8 is
|
||||
// infallible.
|
||||
if (isMapped && !argsobj->getOrCreateRareData(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 6. NativeDefineProperty will lookup [[Value]] for us.
|
||||
if (defineMapped) {
|
||||
if (!DefineMappedIndex(cx, argsobj, id, &newArgDesc, result)) {
|
||||
|
|
@ -884,17 +890,15 @@ bool MappedArgumentsObject::obj_defineProperty(JSContext* cx, HandleObject obj,
|
|||
if (isMapped) {
|
||||
unsigned arg = unsigned(id.toInt());
|
||||
if (desc.isAccessorDescriptor()) {
|
||||
if (!argsobj->markElementDeleted(cx, arg)) {
|
||||
return false;
|
||||
}
|
||||
bool ok = argsobj->markElementDeleted(cx, arg);
|
||||
MOZ_RELEASE_ASSERT(ok, "shouldn't fail after getOrCreateRareData");
|
||||
} else {
|
||||
if (desc.hasValue()) {
|
||||
argsobj->setElement(arg, desc.value());
|
||||
}
|
||||
if (desc.hasWritable() && !desc.writable()) {
|
||||
if (!argsobj->markElementDeleted(cx, arg)) {
|
||||
return false;
|
||||
}
|
||||
bool ok = argsobj->markElementDeleted(cx, arg);
|
||||
MOZ_RELEASE_ASSERT(ok, "shouldn't fail after getOrCreateRareData");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -940,7 +944,7 @@ bool js::UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id,
|
|||
|
||||
if (id.isInt()) {
|
||||
unsigned arg = unsigned(id.toInt());
|
||||
if (arg < argsobj->initialLength()) {
|
||||
if (argsobj->isElement(arg)) {
|
||||
argsobj->setElement(arg, v);
|
||||
return result.succeed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,9 +316,8 @@ static bool AsyncModuleExecutionRejectedHandler(JSContext* cx, unsigned argc,
|
|||
cx, &func.getExtendedSlot(FunctionExtended::MODULE_SLOT)
|
||||
.toObject()
|
||||
.as<ModuleObject>());
|
||||
AsyncModuleExecutionRejected(cx, module, args.get(0));
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
return AsyncModuleExecutionRejected(cx, module, args.get(0));
|
||||
}
|
||||
|
||||
AsyncFunctionGeneratorObject* AsyncFunctionGeneratorObject::create(
|
||||
|
|
|
|||
|
|
@ -536,21 +536,14 @@ bool GetUTF8AtomizationData(JSContext* cx, const JS::UTF8Chars& utf8,
|
|||
|
||||
template <typename CharT>
|
||||
bool UTF8EqualsChars(const JS::UTF8Chars& utfChars, const CharT* chars) {
|
||||
static_assert(std::is_same_v<CharT, JS::Latin1Char> ||
|
||||
std::is_same_v<CharT, char16_t>);
|
||||
|
||||
size_t ind = 0;
|
||||
bool isEqual = true;
|
||||
|
||||
auto checkEqual = [&isEqual, &ind, chars](char16_t c) -> LoopDisposition {
|
||||
#ifdef DEBUG
|
||||
JS::SmallestEncoding encoding = JS::SmallestEncoding::ASCII;
|
||||
UpdateSmallestEncodingForChar(c, &encoding);
|
||||
if (std::is_same_v<CharT, JS::Latin1Char>) {
|
||||
MOZ_ASSERT(encoding <= JS::SmallestEncoding::Latin1);
|
||||
} else if (!std::is_same_v<CharT, char16_t>) {
|
||||
MOZ_CRASH("Invalid character type in UTF8EqualsChars");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CharT(c) != chars[ind]) {
|
||||
if (c != char16_t(chars[ind])) {
|
||||
isEqual = false;
|
||||
return LoopDisposition::Break;
|
||||
}
|
||||
|
|
@ -559,7 +552,7 @@ bool UTF8EqualsChars(const JS::UTF8Chars& utfChars, const CharT* chars) {
|
|||
return LoopDisposition::Continue;
|
||||
};
|
||||
|
||||
// To get here, you must have checked your work.
|
||||
// The caller must have already validated UTF-8 well-formedness.
|
||||
InflateUTF8ToUTF16<OnUTF8Error::Crash>(/* cx = */ nullptr, utfChars,
|
||||
checkEqual);
|
||||
|
||||
|
|
|
|||
|
|
@ -3081,6 +3081,30 @@ void DebugEnvironments::onPopModule(JSContext* cx, const EnvironmentIter& ei) {
|
|||
onPopGeneric<ModuleEnvironmentObject, ModuleScope>(cx, ei);
|
||||
}
|
||||
|
||||
void DebugEnvironments::onPopWasm(JSContext* cx, AbstractFramePtr frame) {
|
||||
MOZ_ASSERT(frame.isWasmDebugFrame());
|
||||
|
||||
DebugEnvironments* envs = cx->realm()->debugEnvs();
|
||||
if (!envs) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rooted<WasmInstanceObject*> instance(cx, frame.wasmInstance()->object());
|
||||
uint32_t funcIndex = frame.asWasmDebugFrame()->funcIndex();
|
||||
Rooted<Scope*> wasmFunctionScope(
|
||||
cx, instance->getExistingFunctionScope(funcIndex));
|
||||
if (!wasmFunctionScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
MissingEnvironmentKey key(frame, wasmFunctionScope);
|
||||
if (MissingEnvironmentMap::Ptr p = envs->missingEnvs.lookup(key)) {
|
||||
EnvironmentObject& env = p->value()->environment();
|
||||
envs->liveEnvs.remove(&env);
|
||||
envs->missingEnvs.remove(p);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugEnvironments::onRealmUnsetIsDebuggee(Realm* realm) {
|
||||
if (DebugEnvironments* envs = realm->debugEnvs()) {
|
||||
envs->proxiedEnvs.clear();
|
||||
|
|
|
|||
|
|
@ -1518,6 +1518,7 @@ class DebugEnvironments {
|
|||
const jsbytecode* pc);
|
||||
static void onPopWith(AbstractFramePtr frame);
|
||||
static void onPopModule(JSContext* cx, const EnvironmentIter& ei);
|
||||
static void onPopWasm(JSContext* cx, AbstractFramePtr frame);
|
||||
static void onRealmUnsetIsDebuggee(Realm* realm);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,10 @@ class MatchPairs {
|
|||
friend class RegExpShared;
|
||||
friend class RegExpStatics;
|
||||
|
||||
void forgetArray() { pairs_ = nullptr; }
|
||||
void forgetArray() {
|
||||
pairs_ = nullptr;
|
||||
pairCount_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
void checkAgainst(size_t inputLength) {
|
||||
|
|
|
|||
|
|
@ -1973,7 +1973,9 @@ static void RejectExecutionWithPendingException(JSContext* cx,
|
|||
std::ignore = cx->getPendingException(&exception);
|
||||
}
|
||||
cx->clearPendingException();
|
||||
AsyncModuleExecutionRejected(cx, module, exception);
|
||||
if (!AsyncModuleExecutionRejected(cx, module, exception)) {
|
||||
MOZ_ASSERT(cx->isThrowingOverRecursed());
|
||||
}
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#sec-async-module-execution-fulfilled
|
||||
|
|
@ -2112,25 +2114,30 @@ void js::AsyncModuleExecutionFulfilled(JSContext* cx,
|
|||
|
||||
// https://tc39.es/ecma262/#sec-async-module-execution-rejected
|
||||
// ES2023 16.2.1.5.2.5 AsyncModuleExecutionRejected
|
||||
void js::AsyncModuleExecutionRejected(JSContext* cx,
|
||||
bool js::AsyncModuleExecutionRejected(JSContext* cx,
|
||||
Handle<ModuleObject*> module,
|
||||
HandleValue error) {
|
||||
AutoCheckRecursionLimit recursion(cx);
|
||||
if (!recursion.check(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 1. If module.[[Status]] is evaluated, then:
|
||||
if (module->status() == ModuleStatus::Evaluated) {
|
||||
// Step 1.a. Assert: module.[[EvaluationError]] is not empty
|
||||
MOZ_ASSERT(module->hadEvaluationError());
|
||||
|
||||
// Step 1.b. Return unused.
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 2. Assert: module.[[Status]] is evaluating-async.
|
||||
MOZ_ASSERT(module->status() == ModuleStatus::EvaluatingAsync);
|
||||
|
||||
// Step 3. Assert: module.[[AsyncEvaluation]] is true.
|
||||
// Step 3. Assert: module.[[AsyncEvaluationOrder]] is an integer.
|
||||
MOZ_ASSERT(module->isAsyncEvaluating());
|
||||
|
||||
// Step 4. 4. Assert: module.[[EvaluationError]] is empty.
|
||||
// Step 4. Assert: module.[[EvaluationError]] is empty.
|
||||
MOZ_ASSERT(!module->hadEvaluationError());
|
||||
|
||||
ModuleObject::onTopLevelEvaluationFinished(module);
|
||||
|
|
@ -2141,25 +2148,15 @@ void js::AsyncModuleExecutionRejected(JSContext* cx,
|
|||
// Step 6. Set module.[[Status]] to evaluated.
|
||||
MOZ_ASSERT(module->status() == ModuleStatus::Evaluated);
|
||||
|
||||
// Step 7. Set module.[[AsyncEvaluationOrder]] to done.
|
||||
module->clearAsyncEvaluatingPostOrder();
|
||||
|
||||
// Step 7. For each Cyclic Module Record m of module.[[AsyncParentModules]],
|
||||
// do:
|
||||
Rooted<ListObject*> parents(cx, module->asyncParentModules());
|
||||
Rooted<ModuleObject*> parent(cx);
|
||||
for (uint32_t i = 0; i < parents->length(); i++) {
|
||||
parent = &parents->get(i).toObject().as<ModuleObject>();
|
||||
|
||||
// Step 7.a. Perform AsyncModuleExecutionRejected(m, error).
|
||||
AsyncModuleExecutionRejected(cx, parent, error);
|
||||
}
|
||||
|
||||
// Step 8. If module.[[TopLevelCapability]] is not empty, then:
|
||||
// Step 9. If module.[[TopLevelCapability]] is not empty, then:
|
||||
if (module->hasTopLevelCapability()) {
|
||||
// Step 8.a. Assert: module.[[CycleRoot]] is module.
|
||||
// Step 9.a. Assert: module.[[CycleRoot]] is module.
|
||||
MOZ_ASSERT(module->getCycleRoot() == module);
|
||||
|
||||
// Step 8.b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]],
|
||||
// Step 9.b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]],
|
||||
// undefined, error).
|
||||
if (!ModuleObject::topLevelCapabilityReject(cx, module, error)) {
|
||||
// If Reject fails, there's nothing more we can do here.
|
||||
|
|
@ -2167,5 +2164,19 @@ void js::AsyncModuleExecutionRejected(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
// Step 9. Return unused.
|
||||
// Step 10. For each Cyclic Module Record m of module.[[AsyncParentModules]],
|
||||
// do:
|
||||
Rooted<ListObject*> parents(cx, module->asyncParentModules());
|
||||
Rooted<ModuleObject*> parent(cx);
|
||||
for (uint32_t i = 0; i < parents->length(); i++) {
|
||||
parent = &parents->get(i).toObject().as<ModuleObject>();
|
||||
|
||||
// Step 10.a. Perform AsyncModuleExecutionRejected(m, error).
|
||||
if (!AsyncModuleExecutionRejected(cx, parent, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 11. Return unused.
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ ModuleNamespaceObject* GetOrCreateModuleNamespace(JSContext* cx,
|
|||
|
||||
void AsyncModuleExecutionFulfilled(JSContext* cx, Handle<ModuleObject*> module);
|
||||
|
||||
void AsyncModuleExecutionRejected(JSContext* cx, Handle<ModuleObject*> module,
|
||||
// This function recusively calls AsyncModuleExecutionRejected on async parent
|
||||
// modules. It returns false if the stack recusion limit is exceeded.
|
||||
bool AsyncModuleExecutionRejected(JSContext* cx, Handle<ModuleObject*> module,
|
||||
HandleValue error);
|
||||
|
||||
} // namespace js
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ inline bool RegExpStatics::updateFromMatchPairs(JSContext* cx,
|
|||
|
||||
if (!matches.initArrayFrom(newPairs)) {
|
||||
ReportOutOfMemory(cx);
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1582,6 +1582,7 @@ bool JSStructuredCloneWriter::writeSharedWasmMemory(HandleObject obj) {
|
|||
|
||||
Rooted<WasmMemoryObject*> memoryObj(context(),
|
||||
&obj->unwrapAs<WasmMemoryObject>());
|
||||
JSAutoRealm ar(context(), memoryObj);
|
||||
Rooted<SharedArrayBufferObject*> sab(
|
||||
context(), &memoryObj->buffer().as<SharedArrayBufferObject>());
|
||||
|
||||
|
|
@ -2989,6 +2990,12 @@ bool JSStructuredCloneReader::readSharedWasmMemory(uint32_t nbytes,
|
|||
if (!startRead(&isHuge)) {
|
||||
return false;
|
||||
}
|
||||
if (!isHuge.isBoolean()) {
|
||||
JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA,
|
||||
"isHuge must be a boolean");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the SharedArrayBuffer object.
|
||||
RootedValue payload(cx);
|
||||
|
|
@ -3807,7 +3814,13 @@ JSObject* JSStructuredCloneReader::readErrorHeader(uint32_t type) {
|
|||
if (!startRead(&val)) {
|
||||
return nullptr;
|
||||
}
|
||||
bool hasCause = ToBoolean(val);
|
||||
if (!val.isBoolean()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA,
|
||||
"hasCause must be a boolean");
|
||||
return nullptr;
|
||||
}
|
||||
bool hasCause = val.toBoolean();
|
||||
Rooted<Maybe<Value>> cause(cx, mozilla::Nothing());
|
||||
if (hasCause) {
|
||||
cause = mozilla::Some(BooleanValue(true));
|
||||
|
|
@ -3873,6 +3886,12 @@ bool JSStructuredCloneReader::readErrorFields(Handle<ErrorObject*> errorObj,
|
|||
}
|
||||
|
||||
if (errorObj->type() == JSEXN_AGGREGATEERR) {
|
||||
if (!errors.isObject() || !errors.toObject().is<ArrayObject>()) {
|
||||
JS_ReportErrorNumberASCII(
|
||||
cx, GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA,
|
||||
"AggregateError 'errors' field must be an Array");
|
||||
return false;
|
||||
}
|
||||
if (!DefineDataProperty(context(), errorObj, cx->names().errors, errors,
|
||||
0)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -393,18 +393,18 @@ static int32_t PerformWait(Instance* instance, uint32_t memoryIndex,
|
|||
PtrT byteOffset, ValT value, int64_t timeout_ns) {
|
||||
JSContext* cx = instance->cx();
|
||||
|
||||
if (!instance->memory(memoryIndex)->isShared()) {
|
||||
ReportTrapError(cx, JSMSG_WASM_NONSHARED_WAIT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (byteOffset & (sizeof(ValT) - 1)) {
|
||||
ReportTrapError(cx, JSMSG_WASM_UNALIGNED_ACCESS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (byteOffset + sizeof(ValT) >
|
||||
instance->memory(memoryIndex)->volatileMemoryLength()) {
|
||||
if (!instance->memory(memoryIndex)->isShared()) {
|
||||
ReportTrapError(cx, JSMSG_WASM_NONSHARED_WAIT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t memSizeBytes = instance->memory(memoryIndex)->volatileMemoryLength();
|
||||
if (memSizeBytes < sizeof(ValT) || byteOffset > memSizeBytes - sizeof(ValT)) {
|
||||
ReportTrapError(cx, JSMSG_WASM_OUT_OF_BOUNDS);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -468,16 +468,14 @@ static int32_t PerformWake(Instance* instance, PtrT byteOffset, int32_t count,
|
|||
uint32_t memoryIndex) {
|
||||
JSContext* cx = instance->cx();
|
||||
|
||||
// The alignment guard is not in the wasm spec as of 2017-11-02, but is
|
||||
// considered likely to appear, as 4-byte alignment is required for WAKE by
|
||||
// the spec's validation algorithm.
|
||||
|
||||
if (byteOffset & 3) {
|
||||
ReportTrapError(cx, JSMSG_WASM_UNALIGNED_ACCESS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (byteOffset >= instance->memory(memoryIndex)->volatileMemoryLength()) {
|
||||
size_t memSizeBytes = instance->memory(memoryIndex)->volatileMemoryLength();
|
||||
if (memSizeBytes < sizeof(int32_t) ||
|
||||
byteOffset > memSizeBytes - sizeof(int32_t)) {
|
||||
ReportTrapError(cx, JSMSG_WASM_OUT_OF_BOUNDS);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2009,6 +2009,15 @@ JSObject& WasmInstanceObject::exportsObj() const {
|
|||
return getReservedSlot(EXPORTS_OBJ_SLOT).toObject();
|
||||
}
|
||||
|
||||
WasmFunctionScope* WasmInstanceObject::getExistingFunctionScope(
|
||||
uint32_t funcIndex) const {
|
||||
if (auto p = scopes().asWasmFunctionScopeMap().lookup(funcIndex)) {
|
||||
return p->value();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WasmInstanceObject::UnspecifiedScopeMap& WasmInstanceObject::scopes() const {
|
||||
return *(UnspecifiedScopeMap*)(getReservedSlot(SCOPES_SLOT).toPrivate());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ class WasmInstanceObject : public NativeObject {
|
|||
|
||||
wasm::Instance& instance() const;
|
||||
JSObject& exportsObj() const;
|
||||
WasmFunctionScope* getExistingFunctionScope(uint32_t funcIndex) const;
|
||||
|
||||
[[nodiscard]] static bool getExportedFunction(
|
||||
JSContext* cx, Handle<WasmInstanceObject*> instanceObj,
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ bool NewFunctionForwarder(JSContext* cx, HandleId idArg, HandleObject callable,
|
|||
FunctionForwarderOptions& options,
|
||||
MutableHandleValue vp) {
|
||||
RootedId id(cx, idArg);
|
||||
if (id.isVoid()) {
|
||||
if (!id.isString()) {
|
||||
id = GetJSIDByIndex(cx, XPCJSContext::IDX_EMPTYSTRING);
|
||||
}
|
||||
|
||||
|
|
@ -501,7 +501,7 @@ bool ExportFunction(JSContext* cx, HandleValue vfunction, HandleValue vscope,
|
|||
}
|
||||
}
|
||||
if (!funName) {
|
||||
funName = JS_AtomizeAndPinString(cx, "");
|
||||
funName = JS_GetEmptyString(cx);
|
||||
}
|
||||
JS_MarkCrossZoneIdValue(cx, StringValue(funName));
|
||||
|
||||
|
|
@ -511,7 +511,11 @@ bool ExportFunction(JSContext* cx, HandleValue vfunction, HandleValue vscope,
|
|||
} else {
|
||||
JS_MarkCrossZoneId(cx, id);
|
||||
}
|
||||
MOZ_ASSERT(id.isString());
|
||||
|
||||
if (!id.isString()) {
|
||||
JS_ReportErrorASCII(cx, "defineAs must be a string");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The function forwarder will live in the target compartment. Since
|
||||
// this function will be referenced from its private slot, to avoid a
|
||||
|
|
|
|||
|
|
@ -956,6 +956,8 @@ void XPCJSRuntime::WeakPointerZonesCallback(JSTracer* trc, void* data) {
|
|||
|
||||
self->mWrappedJSMap->UpdateWeakPointersAfterGC(trc);
|
||||
self->mUAWidgetScopeMap.traceWeak(trc);
|
||||
|
||||
BrowsingContext::SweepWindowProxies(trc);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue