mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
68.14.5 - js
This commit is contained in:
parent
dad6ce97e1
commit
4ccbd6ec3b
@ -24,7 +24,7 @@ DIRS += [
|
||||
'/mozglue',
|
||||
]
|
||||
|
||||
if CONFIG['USE_ICU']:
|
||||
if CONFIG['JS_HAS_INTL_API']:
|
||||
DIRS += [
|
||||
'/config/external/icu',
|
||||
]
|
||||
|
@ -10,8 +10,8 @@ def force_system_ffi(target):
|
||||
|
||||
imply_option('--with-system-ffi', force_system_ffi, "target")
|
||||
|
||||
js_option('--with-system-ffi',
|
||||
help='Use system libffi (located with pkgconfig)')
|
||||
option('--with-system-ffi',
|
||||
help='Use system libffi (located with pkgconfig)')
|
||||
|
||||
use_system_ffi = depends_if('--with-system-ffi')(lambda _: True)
|
||||
|
||||
|
852
js/moz.configure
852
js/moz.configure
File diff suppressed because it is too large
Load Diff
@ -185,6 +185,21 @@ class TempAllocPolicy : public AllocPolicyBase {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A replacement for MallocAllocPolicy that allocates in the JS heap and adds no
|
||||
* extra behaviours.
|
||||
*
|
||||
* This is currently used for allocating source buffers for parsing. Since these
|
||||
* are temporary and will not be freed by GC, the memory is not tracked by the
|
||||
* usual accounting.
|
||||
*/
|
||||
class MallocAllocPolicy : public AllocPolicyBase {
|
||||
public:
|
||||
void reportAllocOverflow() const {}
|
||||
|
||||
[[nodiscard]] bool checkSimulatedOOM() const { return true; }
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_AllocPolicy_h */
|
||||
|
@ -25,7 +25,7 @@ namespace JS {
|
||||
/**
|
||||
* Create a new ArrayBuffer with the given byte length.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewArrayBuffer(JSContext* cx, uint32_t nbytes);
|
||||
extern JS_PUBLIC_API JSObject* NewArrayBuffer(JSContext* cx, size_t nbytes);
|
||||
|
||||
/**
|
||||
* Create a new ArrayBuffer with the given |contents|, which may be null only
|
||||
@ -196,7 +196,7 @@ extern JS_PUBLIC_API JSObject* UnwrapArrayBuffer(JSObject* obj);
|
||||
* |*data|.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* GetObjectAsArrayBuffer(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
uint8_t** data);
|
||||
|
||||
/**
|
||||
@ -206,7 +206,7 @@ extern JS_PUBLIC_API JSObject* GetObjectAsArrayBuffer(JSObject* obj,
|
||||
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
|
||||
* ArrayBuffer, and the unwrapping will succeed.
|
||||
*/
|
||||
extern JS_PUBLIC_API uint32_t GetArrayBufferByteLength(JSObject* obj);
|
||||
extern JS_PUBLIC_API size_t GetArrayBufferByteLength(JSObject* obj);
|
||||
|
||||
// This one isn't inlined because there are a bunch of different ArrayBuffer
|
||||
// classes that would have to be individually handled here.
|
||||
@ -214,7 +214,7 @@ extern JS_PUBLIC_API uint32_t GetArrayBufferByteLength(JSObject* obj);
|
||||
// There is an isShared out argument for API consistency (eases use from DOM).
|
||||
// It will always be set to false.
|
||||
extern JS_PUBLIC_API void GetArrayBufferLengthAndData(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
uint8_t** data);
|
||||
|
||||
@ -258,6 +258,12 @@ extern JS_PUBLIC_API bool DetachArrayBuffer(JSContext* cx,
|
||||
extern JS_PUBLIC_API void* StealArrayBufferContents(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
|
||||
/**
|
||||
* Enable or disable support for large (>= 2 GB) ArrayBuffers on 64-bit builds.
|
||||
* Has no effect on 32-bit builds.
|
||||
*/
|
||||
extern JS_PUBLIC_API void SetLargeArrayBuffersEnabled(bool enable);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_ArrayBuffer_h */
|
||||
|
@ -62,7 +62,7 @@ extern JS_PUBLIC_API JSObject* UnwrapArrayBufferMaybeShared(JSObject* obj);
|
||||
* |*data| will be set to a pointer to the bytes in the buffer.
|
||||
*/
|
||||
extern JS_PUBLIC_API void GetArrayBufferMaybeSharedLengthAndData(
|
||||
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
|
||||
/**
|
||||
* Return a pointer to the start of the array buffer's data, and indicate
|
||||
@ -88,6 +88,14 @@ extern JS_PUBLIC_API void GetArrayBufferMaybeSharedLengthAndData(
|
||||
extern JS_PUBLIC_API uint8_t* GetArrayBufferMaybeSharedData(
|
||||
JSObject* obj, bool* isSharedMemory, const AutoRequireNoGC&);
|
||||
|
||||
/**
|
||||
* Returns whether the passed array buffer is 'large': its byteLength >= 2 GB.
|
||||
* See also SetLargeArrayBuffersEnabled.
|
||||
*
|
||||
* |obj| must pass a JS::IsArrayBufferObjectMaybeShared test.
|
||||
*/
|
||||
extern JS_FRIEND_API bool IsLargeArrayBufferMaybeShared(JSObject* obj);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_ArrayBufferMaybeShared_h */
|
||||
|
@ -11,8 +11,6 @@
|
||||
#ifndef js_BuildId_h
|
||||
#define js_BuildId_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/Vector.h" // js::Vector
|
||||
@ -56,7 +54,7 @@ extern JS_PUBLIC_API void SetProcessBuildIdOp(BuildIdOp buildIdOp);
|
||||
* on having consistent buildId *and* on the CPU supporting features identical
|
||||
* to those in play when the cached data was computed.
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool GetOptimizedEncodingBuildId(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool GetOptimizedEncodingBuildId(
|
||||
BuildIdCharVector* buildId);
|
||||
|
||||
/**
|
||||
@ -75,7 +73,7 @@ extern MOZ_MUST_USE JS_PUBLIC_API bool GetOptimizedEncodingBuildId(
|
||||
* Embedders should use this function to tag transcoded bytecode.
|
||||
* See Transcoding.h.
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool GetScriptTranscodingBuildId(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool GetScriptTranscodingBuildId(
|
||||
BuildIdCharVector* buildId);
|
||||
|
||||
} // namespace JS
|
||||
|
@ -70,7 +70,7 @@ namespace JS {
|
||||
*
|
||||
* Users don't have to call `result.report()`; another possible ending is:
|
||||
*
|
||||
* argv.rval().setBoolean(result.reallyOk());
|
||||
* argv.rval().setBoolean(result.ok());
|
||||
* return true;
|
||||
*/
|
||||
class ObjectOpResult {
|
||||
@ -89,25 +89,16 @@ class ObjectOpResult {
|
||||
public:
|
||||
enum SpecialCodes : uintptr_t { OkCode = 0, Uninitialized = uintptr_t(-1) };
|
||||
|
||||
static const uintptr_t SoftFailBit = uintptr_t(1)
|
||||
<< (sizeof(uintptr_t) * 8 - 1);
|
||||
|
||||
ObjectOpResult() : code_(Uninitialized) {}
|
||||
|
||||
/* Return true if succeed() or failSoft() was called. */
|
||||
bool ok() const {
|
||||
MOZ_ASSERT(code_ != Uninitialized);
|
||||
return code_ == OkCode || (code_ & SoftFailBit);
|
||||
}
|
||||
|
||||
explicit operator bool() const { return ok(); }
|
||||
|
||||
/* Return true if succeed() was called. */
|
||||
bool reallyOk() const {
|
||||
bool ok() const {
|
||||
MOZ_ASSERT(code_ != Uninitialized);
|
||||
return code_ == OkCode;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return ok(); }
|
||||
|
||||
/* Set this ObjectOpResult to true and return true. */
|
||||
bool succeed() {
|
||||
code_ = OkCode;
|
||||
@ -128,26 +119,10 @@ class ObjectOpResult {
|
||||
*/
|
||||
bool fail(uint32_t msg) {
|
||||
MOZ_ASSERT(msg != OkCode);
|
||||
MOZ_ASSERT((msg & SoftFailBit) == 0);
|
||||
code_ = msg;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* DEPRECATED: This is a non-standard compatibility hack.
|
||||
*
|
||||
* Set this ObjectOpResult to true, but remembers an error code.
|
||||
* This is used for situations where we really want to fail,
|
||||
* but can't for legacy reasons.
|
||||
*
|
||||
* Always returns true, as a convenience.
|
||||
*/
|
||||
bool failSoft(uint32_t msg) {
|
||||
// The msg code is currently never extracted again.
|
||||
code_ = msg | SoftFailBit;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool failCantRedefineProp();
|
||||
JS_PUBLIC_API bool failReadOnly();
|
||||
JS_PUBLIC_API bool failGetterOnly();
|
||||
@ -813,7 +788,19 @@ struct alignas(js::gc::JSClassAlignBytes) JSClass {
|
||||
*/
|
||||
static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
|
||||
|
||||
bool isNative() const { return !(flags & NON_NATIVE); }
|
||||
// A JSObject created from a JSClass extends from one of:
|
||||
// - js::NativeObject
|
||||
// - js::ProxyObject
|
||||
//
|
||||
// While it is possible to introduce new families of objects, it is strongly
|
||||
// discouraged. The JITs would be entirely unable to optimize them and testing
|
||||
// coverage is low. The existing NativeObject and ProxyObject are extremely
|
||||
// flexible and are able to represent the entire Gecko embedding requirements.
|
||||
//
|
||||
// NOTE: Internal to SpiderMonkey, there is an experimental js::TypedObject
|
||||
// object family for future WASM features.
|
||||
bool isNativeObject() const { return !(flags & NON_NATIVE); }
|
||||
bool isProxyObject() const { return flags & JSCLASS_IS_PROXY; }
|
||||
|
||||
bool hasPrivate() const { return !!(flags & JSCLASS_HAS_PRIVATE); }
|
||||
|
||||
@ -822,14 +809,12 @@ struct alignas(js::gc::JSClassAlignBytes) JSClass {
|
||||
bool isJSFunction() const { return this == js::FunctionClassPtr; }
|
||||
|
||||
bool nonProxyCallable() const {
|
||||
MOZ_ASSERT(!isProxy());
|
||||
MOZ_ASSERT(!isProxyObject());
|
||||
return isJSFunction() || getCall();
|
||||
}
|
||||
|
||||
bool isGlobal() const { return flags & JSCLASS_IS_GLOBAL; }
|
||||
|
||||
bool isProxy() const { return flags & JSCLASS_IS_PROXY; }
|
||||
|
||||
bool isDOMClass() const { return flags & JSCLASS_IS_DOMJSCLASS; }
|
||||
|
||||
bool shouldDelayMetadataBuilder() const {
|
||||
|
@ -51,7 +51,6 @@
|
||||
#ifndef js_CompileOptions_h
|
||||
#define js_CompileOptions_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
#include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
@ -131,6 +130,7 @@ class JS_PUBLIC_API TransitiveCompileOptions {
|
||||
bool nonSyntacticScope = false;
|
||||
bool privateClassFields = false;
|
||||
bool privateClassMethods = false;
|
||||
bool topLevelAwait = false;
|
||||
|
||||
// True if transcoding to XDR should use Stencil instead of JSScripts.
|
||||
bool useStencilXDR = false;
|
||||
|
@ -26,6 +26,10 @@ class JS_PUBLIC_API ContextOptions {
|
||||
wasmFunctionReferences_(false),
|
||||
wasmGc_(false),
|
||||
wasmMultiValue_(false),
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
wasmSimd_(false),
|
||||
#endif
|
||||
wasmExceptions_(false),
|
||||
testWasmAwaitTier2_(false),
|
||||
throwOnAsmJSValidationFailure_(false),
|
||||
disableIon_(false),
|
||||
@ -42,7 +46,8 @@ class JS_PUBLIC_API ContextOptions {
|
||||
#endif
|
||||
fuzzing_(false),
|
||||
privateClassFields_(false),
|
||||
privateClassMethods_(false) {
|
||||
privateClassMethods_(false),
|
||||
topLevelAwait_(false) {
|
||||
}
|
||||
|
||||
bool asmJS() const { return asmJS_; }
|
||||
@ -111,6 +116,16 @@ class JS_PUBLIC_API ContextOptions {
|
||||
// Defined out-of-line because it depends on a compile-time option
|
||||
ContextOptions& setWasmMultiValue(bool flag);
|
||||
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
bool wasmSimd() const { return wasmSimd_; }
|
||||
// Defined out-of-line because it depends on a compile-time option
|
||||
ContextOptions& setWasmSimd(bool flag);
|
||||
#endif
|
||||
|
||||
bool wasmExceptions() const { return wasmExceptions_; }
|
||||
// Defined out-of-line because it depends on a compile-time option
|
||||
ContextOptions& setWasmExceptions(bool flag);
|
||||
|
||||
bool throwOnAsmJSValidationFailure() const {
|
||||
return throwOnAsmJSValidationFailure_;
|
||||
}
|
||||
@ -144,6 +159,12 @@ class JS_PUBLIC_API ContextOptions {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool topLevelAwait() const { return topLevelAwait_; }
|
||||
ContextOptions& setTopLevelAwait(bool enabled) {
|
||||
topLevelAwait_ = enabled;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Override to allow disabling the eval restriction security checks for
|
||||
// this context.
|
||||
bool disableEvalSecurityChecks() const { return disableEvalSecurityChecks_; }
|
||||
@ -222,6 +243,9 @@ class JS_PUBLIC_API ContextOptions {
|
||||
void disableOptionsForSafeMode() {
|
||||
setAsmJS(false);
|
||||
setWasmBaseline(false);
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
setWasmSimd(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@ -235,6 +259,10 @@ class JS_PUBLIC_API ContextOptions {
|
||||
bool wasmFunctionReferences_ : 1;
|
||||
bool wasmGc_ : 1;
|
||||
bool wasmMultiValue_ : 1;
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
bool wasmSimd_ : 1;
|
||||
#endif
|
||||
bool wasmExceptions_ : 1;
|
||||
bool testWasmAwaitTier2_ : 1;
|
||||
bool throwOnAsmJSValidationFailure_ : 1;
|
||||
bool disableIon_ : 1;
|
||||
@ -252,6 +280,7 @@ class JS_PUBLIC_API ContextOptions {
|
||||
bool fuzzing_ : 1;
|
||||
bool privateClassFields_ : 1;
|
||||
bool privateClassMethods_ : 1;
|
||||
bool topLevelAwait_ : 1;
|
||||
};
|
||||
|
||||
JS_PUBLIC_API ContextOptions& ContextOptionsRef(JSContext* cx);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef js_ForOfIterator_h
|
||||
#define js_ForOfIterator_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE, MOZ_STACK_CLASS
|
||||
#include "mozilla/Attributes.h" // MOZ_STACK_CLASS
|
||||
|
||||
#include <stdint.h> // UINT32_MAX, uint32_t
|
||||
|
||||
@ -85,7 +85,7 @@ class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
|
||||
* return true instead of throwing. Callers must then check
|
||||
* valueIsIterable() before continuing with the iteration.
|
||||
*/
|
||||
MOZ_MUST_USE bool init(
|
||||
[[nodiscard]] bool init(
|
||||
Handle<Value> iterable,
|
||||
NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
|
||||
|
||||
@ -93,7 +93,7 @@ class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
|
||||
* Get the next value from the iterator. If false *done is true
|
||||
* after this call, do not examine val.
|
||||
*/
|
||||
MOZ_MUST_USE bool next(MutableHandle<Value> val, bool* done);
|
||||
[[nodiscard]] bool next(MutableHandle<Value> val, bool* done);
|
||||
|
||||
/**
|
||||
* Close the iterator.
|
||||
|
@ -28,20 +28,6 @@ struct Statistics;
|
||||
} // namespace gcstats
|
||||
} // namespace js
|
||||
|
||||
typedef enum JSGCMode {
|
||||
/** Perform only global GCs. */
|
||||
JSGC_MODE_GLOBAL = 0,
|
||||
|
||||
/** Perform per-zone GCs until too much garbage has accumulated. */
|
||||
JSGC_MODE_ZONE = 1,
|
||||
|
||||
/** Collect in short time slices rather than all at once. */
|
||||
JSGC_MODE_INCREMENTAL = 2,
|
||||
|
||||
/** Both of the above. */
|
||||
JSGC_MODE_ZONE_INCREMENTAL = 3,
|
||||
} JSGCMode;
|
||||
|
||||
/**
|
||||
* Kinds of js_GC invocation.
|
||||
*/
|
||||
@ -84,14 +70,21 @@ typedef enum JSGCParamKey {
|
||||
JSGC_NUMBER = 4,
|
||||
|
||||
/**
|
||||
* Select GC mode.
|
||||
* Whether incremental GC is enabled. If not, GC will always run to
|
||||
* completion.
|
||||
*
|
||||
* See: JSGCMode in GCAPI.h
|
||||
* prefs: javascript.options.mem.gc_per_zone and
|
||||
* javascript.options.mem.gc_incremental.
|
||||
* Default: JSGC_MODE_ZONE_INCREMENTAL
|
||||
* prefs: javascript.options.mem.gc_incremental.
|
||||
* Default: false
|
||||
*/
|
||||
JSGC_MODE = 6,
|
||||
JSGC_INCREMENTAL_GC_ENABLED = 5,
|
||||
|
||||
/**
|
||||
* Whether per-zone GC is enabled. If not, all zones are collected every time.
|
||||
*
|
||||
* prefs: javascript.options.mem.gc_per_zone
|
||||
* Default: false
|
||||
*/
|
||||
JSGC_PER_ZONE_GC_ENABLED = 6,
|
||||
|
||||
/** Number of cached empty GC chunks. */
|
||||
JSGC_UNUSED_CHUNKS = 7,
|
||||
@ -102,6 +95,8 @@ typedef enum JSGCParamKey {
|
||||
/**
|
||||
* Max milliseconds to spend in an incremental GC slice.
|
||||
*
|
||||
* A value of zero means there is no maximum.
|
||||
*
|
||||
* Pref: javascript.options.mem.gc_incremental_slice_ms
|
||||
* Default: DefaultTimeBudgetMS.
|
||||
*/
|
||||
@ -383,6 +378,22 @@ typedef enum JSGCParamKey {
|
||||
* nursery.)
|
||||
*/
|
||||
JSGC_PRETENURE_STRING_THRESHOLD = 42,
|
||||
|
||||
/**
|
||||
* If the finalization rate of the tenured strings exceeds this threshold,
|
||||
* string will be allocated in nursery.
|
||||
*/
|
||||
JSGC_STOP_PRETENURE_STRING_THRESHOLD = 43,
|
||||
|
||||
/**
|
||||
* A number that is incremented on every major GC slice.
|
||||
*/
|
||||
JSGC_MAJOR_GC_NUMBER = 44,
|
||||
|
||||
/**
|
||||
* A number that is incremented on every minor GC.
|
||||
*/
|
||||
JSGC_MINOR_GC_NUMBER = 45,
|
||||
} JSGCParamKey;
|
||||
|
||||
/*
|
||||
@ -506,7 +517,7 @@ namespace JS {
|
||||
D(DOM_WINDOW_UTILS, FIRST_FIREFOX_REASON) \
|
||||
D(COMPONENT_UTILS, 34) \
|
||||
D(MEM_PRESSURE, 35) \
|
||||
D(CC_WAITING, 36) \
|
||||
D(CC_FINISHED, 36) \
|
||||
D(CC_FORCED, 37) \
|
||||
D(LOAD_END, 38) \
|
||||
D(UNUSED3, 39) \
|
||||
@ -571,7 +582,7 @@ extern JS_PUBLIC_API bool InternalGCReason(JS::GCReason reason);
|
||||
/**
|
||||
* Schedule the given zone to be collected as part of the next GC.
|
||||
*/
|
||||
extern JS_PUBLIC_API void PrepareZoneForGC(Zone* zone);
|
||||
extern JS_PUBLIC_API void PrepareZoneForGC(JSContext* cx, Zone* zone);
|
||||
|
||||
/**
|
||||
* Schedule all zones to be collected in the next GC.
|
||||
@ -595,7 +606,7 @@ extern JS_PUBLIC_API bool IsGCScheduled(JSContext* cx);
|
||||
* Undoes the effect of the Prepare methods above. The given zone will not be
|
||||
* collected in the next GC.
|
||||
*/
|
||||
extern JS_PUBLIC_API void SkipZoneForGC(Zone* zone);
|
||||
extern JS_PUBLIC_API void SkipZoneForGC(JSContext* cx, Zone* zone);
|
||||
|
||||
/*
|
||||
* Non-Incremental GC:
|
||||
@ -629,8 +640,7 @@ extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx,
|
||||
* must be met:
|
||||
* - The collection must be run by calling JS::IncrementalGC() rather than
|
||||
* JS_GC().
|
||||
* - The GC mode must have been set to JSGC_MODE_INCREMENTAL or
|
||||
* JSGC_MODE_ZONE_INCREMENTAL with JS_SetGCParameter().
|
||||
* - The GC parameter JSGC_INCREMENTAL_GC_ENABLED must be true.
|
||||
*
|
||||
* Note: Even if incremental GC is enabled and working correctly,
|
||||
* non-incremental collections can still happen when low on memory.
|
||||
|
@ -356,7 +356,7 @@ class MutableWrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
|
||||
|
||||
void clear() { set().clear(); }
|
||||
void clearAndCompact() { set().clearAndCompact(); }
|
||||
MOZ_MUST_USE bool reserve(uint32_t len) { return set().reserve(len); }
|
||||
[[nodiscard]] bool reserve(uint32_t len) { return set().reserve(len); }
|
||||
void remove(Ptr p) { set().remove(p); }
|
||||
void remove(const Lookup& l) { set().remove(l); }
|
||||
AddPtr lookupForAdd(const Lookup& l) { return set().lookupForAdd(l); }
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/GCPolicyAPI.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TracingAPI.h"
|
||||
@ -63,11 +64,11 @@ class GCVector {
|
||||
const T& back() const { return vector.back(); }
|
||||
|
||||
bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
|
||||
MOZ_MUST_USE bool reserve(size_t req) { return vector.reserve(req); }
|
||||
[[nodiscard]] bool reserve(size_t req) { return vector.reserve(req); }
|
||||
void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
|
||||
void shrinkTo(size_t newLen) { return vector.shrinkTo(newLen); }
|
||||
MOZ_MUST_USE bool growBy(size_t amount) { return vector.growBy(amount); }
|
||||
MOZ_MUST_USE bool resize(size_t newLen) { return vector.resize(newLen); }
|
||||
[[nodiscard]] bool growBy(size_t amount) { return vector.growBy(amount); }
|
||||
[[nodiscard]] bool resize(size_t newLen) { return vector.resize(newLen); }
|
||||
|
||||
void clear() { return vector.clear(); }
|
||||
void clearAndFree() { return vector.clearAndFree(); }
|
||||
@ -89,7 +90,7 @@ class GCVector {
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
MOZ_MUST_USE bool emplaceBack(Args&&... args) {
|
||||
[[nodiscard]] bool emplaceBack(Args&&... args) {
|
||||
return vector.emplaceBack(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@ -115,20 +116,25 @@ class GCVector {
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool appendAll(const U& aU) {
|
||||
[[nodiscard]] bool appendAll(const U& aU) {
|
||||
return vector.append(aU.begin(), aU.end());
|
||||
}
|
||||
template <typename T2, size_t MinInlineCapacity2, typename AllocPolicy2>
|
||||
[[nodiscard]] bool appendAll(
|
||||
GCVector<T2, MinInlineCapacity2, AllocPolicy2>&& aU) {
|
||||
return vector.appendAll(aU.begin(), aU.end());
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool appendN(const T& val, size_t count) {
|
||||
[[nodiscard]] bool appendN(const T& val, size_t count) {
|
||||
return vector.appendN(val, count);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
|
||||
[[nodiscard]] bool append(const U* aBegin, const U* aEnd) {
|
||||
return vector.append(aBegin, aEnd);
|
||||
}
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool append(const U* aBegin, size_t aLength) {
|
||||
[[nodiscard]] bool append(const U* aBegin, size_t aLength) {
|
||||
return vector.append(aBegin, aLength);
|
||||
}
|
||||
|
||||
@ -247,32 +253,34 @@ class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>,
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool initCapacity(size_t aRequest) {
|
||||
[[nodiscard]] bool initCapacity(size_t aRequest) {
|
||||
return vec().initCapacity(aRequest);
|
||||
}
|
||||
MOZ_MUST_USE bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
|
||||
[[nodiscard]] bool reserve(size_t aRequest) {
|
||||
return vec().reserve(aRequest);
|
||||
}
|
||||
void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
|
||||
MOZ_MUST_USE bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
|
||||
MOZ_MUST_USE bool resize(size_t aNewLength) {
|
||||
[[nodiscard]] bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
|
||||
[[nodiscard]] bool resize(size_t aNewLength) {
|
||||
return vec().resize(aNewLength);
|
||||
}
|
||||
MOZ_MUST_USE bool growByUninitialized(size_t aIncr) {
|
||||
[[nodiscard]] bool growByUninitialized(size_t aIncr) {
|
||||
return vec().growByUninitialized(aIncr);
|
||||
}
|
||||
void infallibleGrowByUninitialized(size_t aIncr) {
|
||||
vec().infallibleGrowByUninitialized(aIncr);
|
||||
}
|
||||
MOZ_MUST_USE bool resizeUninitialized(size_t aNewLength) {
|
||||
[[nodiscard]] bool resizeUninitialized(size_t aNewLength) {
|
||||
return vec().resizeUninitialized(aNewLength);
|
||||
}
|
||||
void clear() { vec().clear(); }
|
||||
void clearAndFree() { vec().clearAndFree(); }
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool append(U&& aU) {
|
||||
[[nodiscard]] bool append(U&& aU) {
|
||||
return vec().append(std::forward<U>(aU));
|
||||
}
|
||||
template <typename... Args>
|
||||
MOZ_MUST_USE bool emplaceBack(Args&&... aArgs) {
|
||||
[[nodiscard]] bool emplaceBack(Args&&... aArgs) {
|
||||
return vec().emplaceBack(std::forward<Args>(aArgs)...);
|
||||
}
|
||||
template <typename... Args>
|
||||
@ -280,18 +288,18 @@ class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>,
|
||||
vec().infallibleEmplaceBack(std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool appendAll(const U& aU) {
|
||||
[[nodiscard]] bool appendAll(U&& aU) {
|
||||
return vec().appendAll(aU);
|
||||
}
|
||||
MOZ_MUST_USE bool appendN(const T& aT, size_t aN) {
|
||||
[[nodiscard]] bool appendN(const T& aT, size_t aN) {
|
||||
return vec().appendN(aT, aN);
|
||||
}
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
|
||||
[[nodiscard]] bool append(const U* aBegin, const U* aEnd) {
|
||||
return vec().append(aBegin, aEnd);
|
||||
}
|
||||
template <typename U>
|
||||
MOZ_MUST_USE bool append(const U* aBegin, size_t aLength) {
|
||||
[[nodiscard]] bool append(const U* aBegin, size_t aLength) {
|
||||
return vec().append(aBegin, aLength);
|
||||
}
|
||||
template <typename U>
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define js_HeapAPI_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/BitSet.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <type_traits>
|
||||
@ -29,11 +30,16 @@ struct JSExternalStringCallbacks;
|
||||
/* These values are private to the JS engine. */
|
||||
namespace js {
|
||||
|
||||
class NurseryDecommitTask;
|
||||
|
||||
JS_FRIEND_API bool CurrentThreadCanAccessZone(JS::Zone* zone);
|
||||
|
||||
namespace gc {
|
||||
|
||||
class Arena;
|
||||
struct Cell;
|
||||
class TenuredChunk;
|
||||
class StoreBuffer;
|
||||
class TenuredCell;
|
||||
|
||||
const size_t ArenaShift = 12;
|
||||
@ -53,39 +59,114 @@ const size_t CellAlignBytes = size_t(1) << CellAlignShift;
|
||||
const size_t CellAlignMask = CellAlignBytes - 1;
|
||||
|
||||
const size_t CellBytesPerMarkBit = CellAlignBytes;
|
||||
const size_t MarkBitsPerCell = 2;
|
||||
|
||||
/*
|
||||
* We sometimes use an index to refer to a cell in an arena. The index for a
|
||||
* cell is found by dividing by the cell alignment so not all indicies refer to
|
||||
* valid cells.
|
||||
* The mark bitmap has one bit per each possible cell start position. This
|
||||
* wastes some space for larger GC things but allows us to avoid division by the
|
||||
* cell's size when accessing the bitmap.
|
||||
*/
|
||||
const size_t ArenaCellIndexBytes = CellAlignBytes;
|
||||
const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes;
|
||||
const size_t ArenaBitmapBits = ArenaSize / CellBytesPerMarkBit;
|
||||
const size_t ArenaBitmapBytes = HowMany(ArenaBitmapBits, 8);
|
||||
const size_t ArenaBitmapWords = HowMany(ArenaBitmapBits, JS_BITS_PER_WORD);
|
||||
|
||||
/* These are magic constants derived from actual offsets in gc/Heap.h. */
|
||||
// The base class for all GC chunks, either in the nursery or in the tenured
|
||||
// heap memory. This structure is locatable from any GC pointer by aligning to
|
||||
// the chunk size.
|
||||
class alignas(CellAlignBytes) ChunkBase {
|
||||
protected:
|
||||
ChunkBase(JSRuntime* rt, StoreBuffer* sb) : storeBuffer(sb), runtime(rt) {
|
||||
MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0);
|
||||
}
|
||||
|
||||
public:
|
||||
// The store buffer for pointers from tenured things to things in this
|
||||
// chunk. Will be non-null if and only if this is a nursery chunk.
|
||||
StoreBuffer* storeBuffer;
|
||||
|
||||
// Provide quick access to the runtime from absolutely anywhere.
|
||||
JSRuntime* runtime;
|
||||
};
|
||||
|
||||
// Information about tenured heap chunks.
|
||||
struct TenuredChunkInfo {
|
||||
private:
|
||||
friend class ChunkPool;
|
||||
TenuredChunk* next = nullptr;
|
||||
TenuredChunk* prev = nullptr;
|
||||
|
||||
public:
|
||||
/* List of free committed arenas, linked together with arena.next. */
|
||||
Arena* freeArenasHead;
|
||||
|
||||
/*
|
||||
* Decommitted arenas are tracked by a bitmap in the TenuredChunkBase. We use
|
||||
* this offset to start our search iteration close to a decommitted arena that
|
||||
* we can allocate.
|
||||
*/
|
||||
uint32_t lastDecommittedArenaOffset;
|
||||
|
||||
/* Number of free arenas, either committed or decommitted. */
|
||||
uint32_t numArenasFree;
|
||||
|
||||
/* Number of free, committed arenas. */
|
||||
uint32_t numArenasFreeCommitted;
|
||||
};
|
||||
|
||||
/*
|
||||
* Calculating ArenasPerChunk:
|
||||
*
|
||||
* To figure out how many Arenas will fit in a chunk we need to know how much
|
||||
* extra space is available after we allocate the header data. This is a problem
|
||||
* because the header size depends on the number of arenas in the chunk.
|
||||
*
|
||||
* The two dependent fields are bitmap and decommittedArenas. bitmap needs
|
||||
* ArenaBitmapBytes bytes per arena and decommittedArenas needs one bit per
|
||||
* arena.
|
||||
*
|
||||
* We can calculate an approximate value by dividing the number of bits of free
|
||||
* space in the chunk by the number of bits needed per arena. This is an
|
||||
* approximation because it doesn't take account of the fact that the variable
|
||||
* sized fields must be rounded up to a whole number of words, or any padding
|
||||
* the compiler adds between fields.
|
||||
*
|
||||
* Fortunately, for the chunk and arena size parameters we use this
|
||||
* approximation turns out to be correct. If it were not we might need to adjust
|
||||
* the arena count down by one to allow more space for the padding.
|
||||
*/
|
||||
const size_t BitsPerArenaWithHeaders =
|
||||
(ArenaSize + ArenaBitmapBytes) * CHAR_BIT + 1;
|
||||
const size_t ChunkBitsAvailable =
|
||||
(ChunkSize - sizeof(ChunkBase) - sizeof(TenuredChunkInfo)) * CHAR_BIT;
|
||||
const size_t ArenasPerChunk = ChunkBitsAvailable / BitsPerArenaWithHeaders;
|
||||
|
||||
const size_t CalculatedChunkSizeRequired =
|
||||
sizeof(ChunkBase) + sizeof(TenuredChunkInfo) +
|
||||
RoundUp(ArenasPerChunk * ArenaBitmapBytes, sizeof(uintptr_t)) +
|
||||
RoundUp(ArenasPerChunk, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT +
|
||||
ArenasPerChunk * ArenaSize;
|
||||
static_assert(CalculatedChunkSizeRequired <= ChunkSize,
|
||||
"Calculated ArenasPerChunk is too large");
|
||||
|
||||
const size_t CalculatedChunkPadSize = ChunkSize - CalculatedChunkSizeRequired;
|
||||
static_assert(CalculatedChunkPadSize * CHAR_BIT < BitsPerArenaWithHeaders,
|
||||
"Calculated ArenasPerChunk is too small");
|
||||
|
||||
// Define a macro for the expected number of arenas so its value appears in the
|
||||
// error message if the assertion fails.
|
||||
#ifdef JS_GC_SMALL_CHUNK_SIZE
|
||||
const size_t ChunkMarkBitmapOffset = 258104;
|
||||
const size_t ChunkMarkBitmapBits = 31744;
|
||||
# define EXPECTED_ARENA_COUNT 63
|
||||
#else
|
||||
const size_t ChunkMarkBitmapOffset = 1032352;
|
||||
const size_t ChunkMarkBitmapBits = 129024;
|
||||
# define EXPECTED_ARENA_COUNT 252
|
||||
#endif
|
||||
const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
|
||||
const size_t ChunkTrailerSize = 2 * sizeof(uintptr_t) + sizeof(uint64_t);
|
||||
const size_t ChunkLocationOffset = ChunkSize - ChunkTrailerSize;
|
||||
const size_t ChunkStoreBufferOffset =
|
||||
ChunkSize - ChunkTrailerSize + sizeof(uint64_t);
|
||||
const size_t ArenaZoneOffset = sizeof(size_t);
|
||||
const size_t ArenaHeaderSize =
|
||||
sizeof(size_t) + 2 * sizeof(uintptr_t) + sizeof(size_t) + sizeof(uintptr_t);
|
||||
static_assert(ArenasPerChunk == EXPECTED_ARENA_COUNT,
|
||||
"Do not accidentally change our heap's density.");
|
||||
#undef EXPECTED_ARENA_COUNT
|
||||
|
||||
// The first word of a GC thing has certain requirements from the GC and is used
|
||||
// to store flags in the low bits.
|
||||
const size_t CellFlagBitsReservedForGC = 3;
|
||||
|
||||
// The first word can be used to store JSClass pointers for some thing kinds, so
|
||||
// these must be suitably aligned.
|
||||
const size_t JSClassAlignBytes = size_t(1) << CellFlagBitsReservedForGC;
|
||||
// Mark bitmaps are atomic because they can be written by gray unmarking on the
|
||||
// main thread while read by sweeping on a background thread. The former does
|
||||
// not affect the result of the latter.
|
||||
using MarkBitmapWord = mozilla::Atomic<uintptr_t, mozilla::Relaxed>;
|
||||
|
||||
/*
|
||||
* Live objects are marked black or gray. Everything reachable from a JS root is
|
||||
@ -99,16 +180,83 @@ const size_t JSClassAlignBytes = size_t(1) << CellFlagBitsReservedForGC;
|
||||
*/
|
||||
enum class ColorBit : uint32_t { BlackBit = 0, GrayOrBlackBit = 1 };
|
||||
|
||||
/*
|
||||
* The "location" field in the Chunk trailer is a enum indicating various roles
|
||||
* of the chunk.
|
||||
*/
|
||||
enum class ChunkLocation : uint32_t {
|
||||
Invalid = 0,
|
||||
Nursery = 1,
|
||||
TenuredHeap = 2
|
||||
// Mark colors. Order is important here: the greater value the 'more marked' a
|
||||
// cell is.
|
||||
enum class MarkColor : uint8_t { Gray = 1, Black = 2 };
|
||||
|
||||
// Mark bitmap for a tenured heap chunk.
|
||||
struct MarkBitmap {
|
||||
static constexpr size_t WordCount = ArenaBitmapWords * ArenasPerChunk;
|
||||
MarkBitmapWord bitmap[WordCount];
|
||||
|
||||
inline void getMarkWordAndMask(const TenuredCell* cell, ColorBit colorBit,
|
||||
MarkBitmapWord** wordp, uintptr_t* maskp);
|
||||
|
||||
// The following are not exported and are defined in gc/Heap.h:
|
||||
inline bool markBit(const TenuredCell* cell, ColorBit colorBit);
|
||||
inline bool isMarkedAny(const TenuredCell* cell);
|
||||
inline bool isMarkedBlack(const TenuredCell* cell);
|
||||
inline bool isMarkedGray(const TenuredCell* cell);
|
||||
inline bool markIfUnmarked(const TenuredCell* cell, MarkColor color);
|
||||
inline void markBlack(const TenuredCell* cell);
|
||||
inline void copyMarkBit(TenuredCell* dst, const TenuredCell* src,
|
||||
ColorBit colorBit);
|
||||
inline void unmark(const TenuredCell* cell);
|
||||
inline void clear();
|
||||
inline MarkBitmapWord* arenaBits(Arena* arena);
|
||||
};
|
||||
|
||||
static_assert(ArenaBitmapBytes * ArenasPerChunk == sizeof(MarkBitmap),
|
||||
"Ensure our MarkBitmap actually covers all arenas.");
|
||||
|
||||
// Decommit bitmap for a heap chunk.
|
||||
using DecommitBitmap = mozilla::BitSet<ArenasPerChunk, uint32_t>;
|
||||
|
||||
// Base class containing data members for a tenured heap chunk.
|
||||
class TenuredChunkBase : public ChunkBase {
|
||||
public:
|
||||
TenuredChunkInfo info;
|
||||
MarkBitmap markBits;
|
||||
DecommitBitmap decommittedArenas;
|
||||
|
||||
protected:
|
||||
explicit TenuredChunkBase(JSRuntime* runtime) : ChunkBase(runtime, nullptr) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* We sometimes use an index to refer to a cell in an arena. The index for a
|
||||
* cell is found by dividing by the cell alignment so not all indices refer to
|
||||
* valid cells.
|
||||
*/
|
||||
const size_t ArenaCellIndexBytes = CellAlignBytes;
|
||||
const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes;
|
||||
|
||||
const size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT;
|
||||
|
||||
constexpr size_t FirstArenaAdjustmentBits =
|
||||
RoundUp(sizeof(gc::TenuredChunkBase), ArenaSize) / gc::CellBytesPerMarkBit;
|
||||
|
||||
static_assert((FirstArenaAdjustmentBits % MarkBitmapWordBits) == 0);
|
||||
constexpr size_t FirstArenaAdjustmentWords =
|
||||
FirstArenaAdjustmentBits / MarkBitmapWordBits;
|
||||
|
||||
const size_t ChunkRuntimeOffset = offsetof(ChunkBase, runtime);
|
||||
const size_t ChunkStoreBufferOffset = offsetof(ChunkBase, storeBuffer);
|
||||
const size_t ChunkMarkBitmapOffset = offsetof(TenuredChunkBase, markBits);
|
||||
|
||||
// Hardcoded offsets into Arena class.
|
||||
const size_t ArenaZoneOffset = sizeof(size_t);
|
||||
const size_t ArenaHeaderSize =
|
||||
sizeof(size_t) + 2 * sizeof(uintptr_t) + sizeof(size_t) + sizeof(uintptr_t);
|
||||
|
||||
// The first word of a GC thing has certain requirements from the GC and is used
|
||||
// to store flags in the low bits.
|
||||
const size_t CellFlagBitsReservedForGC = 3;
|
||||
|
||||
// The first word can be used to store JSClass pointers for some thing kinds, so
|
||||
// these must be suitably aligned.
|
||||
const size_t JSClassAlignBytes = size_t(1) << CellFlagBitsReservedForGC;
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
/* When downcasting, ensure we are actually the right type. */
|
||||
extern JS_FRIEND_API void AssertGCThingHasType(js::gc::Cell* cell,
|
||||
@ -118,6 +266,7 @@ inline void AssertGCThingHasType(js::gc::Cell* cell, JS::TraceKind kind) {}
|
||||
#endif
|
||||
|
||||
MOZ_ALWAYS_INLINE bool IsInsideNursery(const js::gc::Cell* cell);
|
||||
MOZ_ALWAYS_INLINE bool IsInsideNursery(const js::gc::TenuredCell* cell);
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
@ -333,36 +482,35 @@ inline bool operator!=(const JS::GCCellPtr& ptr1, const JS::GCCellPtr& ptr2) {
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
// Mark bitmaps are atomic because they can be written by gray unmarking on the
|
||||
// main thread while read by sweeping on a background thread. The former does
|
||||
// not affect the result of the latter.
|
||||
using MarkBitmapWord = mozilla::Atomic<uintptr_t, mozilla::Relaxed>;
|
||||
/* static */
|
||||
MOZ_ALWAYS_INLINE void MarkBitmap::getMarkWordAndMask(const TenuredCell* cell,
|
||||
ColorBit colorBit,
|
||||
MarkBitmapWord** wordp,
|
||||
uintptr_t* maskp) {
|
||||
// Note: the JIT pre-barrier trampolines inline this code. Update
|
||||
// MacroAssembler::emitPreBarrierFastPath code too when making changes here!
|
||||
|
||||
MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell);
|
||||
|
||||
size_t offset = uintptr_t(cell) & ChunkMask;
|
||||
const size_t bit = offset / CellBytesPerMarkBit + size_t(colorBit);
|
||||
size_t word = bit / MarkBitmapWordBits - FirstArenaAdjustmentWords;
|
||||
MOZ_ASSERT(word < WordCount);
|
||||
*wordp = &bitmap[word];
|
||||
*maskp = uintptr_t(1) << (bit % MarkBitmapWordBits);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
static MOZ_ALWAYS_INLINE MarkBitmapWord* GetGCThingMarkBitmap(
|
||||
const uintptr_t addr) {
|
||||
// Note: the JIT pre-barrier trampolines inline this code. Update that
|
||||
// code too when making changes here!
|
||||
MOZ_ASSERT(addr);
|
||||
const uintptr_t bmap_addr = (addr & ~ChunkMask) | ChunkMarkBitmapOffset;
|
||||
return reinterpret_cast<MarkBitmapWord*>(bmap_addr);
|
||||
static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) {
|
||||
MOZ_ASSERT(cell);
|
||||
return reinterpret_cast<ChunkBase*>(uintptr_t(cell) & ~ChunkMask);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void GetGCThingMarkWordAndMask(const uintptr_t addr,
|
||||
ColorBit colorBit,
|
||||
MarkBitmapWord** wordp,
|
||||
uintptr_t* maskp) {
|
||||
// Note: the JIT pre-barrier trampolines inline this code. Update that
|
||||
// code too when making changes here!
|
||||
MOZ_ASSERT(addr);
|
||||
const size_t bit = (addr & js::gc::ChunkMask) / js::gc::CellBytesPerMarkBit +
|
||||
static_cast<uint32_t>(colorBit);
|
||||
MOZ_ASSERT(bit < js::gc::ChunkMarkBitmapBits);
|
||||
MarkBitmapWord* bitmap = GetGCThingMarkBitmap(addr);
|
||||
const uintptr_t nbits = sizeof(*bitmap) * CHAR_BIT;
|
||||
*maskp = uintptr_t(1) << (bit % nbits);
|
||||
*wordp = &bitmap[bit / nbits];
|
||||
static MOZ_ALWAYS_INLINE TenuredChunkBase* GetCellChunkBase(
|
||||
const TenuredCell* cell) {
|
||||
MOZ_ASSERT(cell);
|
||||
return reinterpret_cast<TenuredChunkBase*>(uintptr_t(cell) & ~ChunkMask);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE JS::Zone* GetTenuredGCThingZone(const uintptr_t addr) {
|
||||
@ -371,23 +519,24 @@ static MOZ_ALWAYS_INLINE JS::Zone* GetTenuredGCThingZone(const uintptr_t addr) {
|
||||
return *reinterpret_cast<JS::Zone**>(zone_addr);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const Cell* cell) {
|
||||
static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const TenuredCell* cell) {
|
||||
// Return true if GrayOrBlackBit is set and BlackBit is not set.
|
||||
MOZ_ASSERT(cell);
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
|
||||
|
||||
MarkBitmapWord* grayWord;
|
||||
uintptr_t grayMask;
|
||||
js::gc::detail::GetGCThingMarkWordAndMask(
|
||||
uintptr_t(cell), js::gc::ColorBit::GrayOrBlackBit, &grayWord, &grayMask);
|
||||
TenuredChunkBase* chunk = GetCellChunkBase(cell);
|
||||
chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::GrayOrBlackBit,
|
||||
&grayWord, &grayMask);
|
||||
if (!(*grayWord & grayMask)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MarkBitmapWord* blackWord;
|
||||
uintptr_t blackMask;
|
||||
js::gc::detail::GetGCThingMarkWordAndMask(
|
||||
uintptr_t(cell), js::gc::ColorBit::BlackBit, &blackWord, &blackMask);
|
||||
chunk->markBits.getMarkWordAndMask(cell, js::gc::ColorBit::BlackBit,
|
||||
&blackWord, &blackMask);
|
||||
return !(*blackWord & blackMask);
|
||||
}
|
||||
|
||||
@ -396,7 +545,7 @@ static MOZ_ALWAYS_INLINE bool CellIsMarkedGray(const Cell* cell) {
|
||||
if (js::gc::IsInsideNursery(cell)) {
|
||||
return false;
|
||||
}
|
||||
return TenuredCellIsMarkedGray(cell);
|
||||
return TenuredCellIsMarkedGray(reinterpret_cast<const TenuredCell*>(cell));
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API bool CellIsMarkedGrayIfKnown(const Cell* cell);
|
||||
@ -407,18 +556,8 @@ extern JS_PUBLIC_API void AssertCellIsNotGray(const Cell* cell);
|
||||
extern JS_PUBLIC_API bool ObjectIsMarkedBlack(const JSObject* obj);
|
||||
#endif
|
||||
|
||||
MOZ_ALWAYS_INLINE ChunkLocation GetCellLocation(const void* cell) {
|
||||
uintptr_t addr = uintptr_t(cell);
|
||||
addr &= ~js::gc::ChunkMask;
|
||||
addr |= js::gc::ChunkLocationOffset;
|
||||
return *reinterpret_cast<ChunkLocation*>(addr);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool NurseryCellHasStoreBuffer(const void* cell) {
|
||||
uintptr_t addr = uintptr_t(cell);
|
||||
addr &= ~js::gc::ChunkMask;
|
||||
addr |= js::gc::ChunkStoreBufferOffset;
|
||||
return *reinterpret_cast<void**>(addr) != nullptr;
|
||||
MOZ_ALWAYS_INLINE bool CellHasStoreBuffer(const Cell* cell) {
|
||||
return GetCellChunkBase(cell)->storeBuffer;
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
@ -427,15 +566,12 @@ MOZ_ALWAYS_INLINE bool IsInsideNursery(const Cell* cell) {
|
||||
if (!cell) {
|
||||
return false;
|
||||
}
|
||||
auto location = detail::GetCellLocation(cell);
|
||||
MOZ_ASSERT(location == ChunkLocation::Nursery ||
|
||||
location == ChunkLocation::TenuredHeap);
|
||||
return location == ChunkLocation::Nursery;
|
||||
return detail::CellHasStoreBuffer(cell);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool IsInsideNursery(const TenuredCell* cell) {
|
||||
MOZ_ASSERT_IF(cell,
|
||||
detail::GetCellLocation(cell) == ChunkLocation::TenuredHeap);
|
||||
MOZ_ASSERT_IF(
|
||||
cell, !detail::CellHasStoreBuffer(reinterpret_cast<const Cell*>(cell)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -451,19 +587,18 @@ MOZ_ALWAYS_INLINE bool IsInsideNursery(const JS::BigInt* bi) {
|
||||
return IsInsideNursery(reinterpret_cast<const Cell*>(bi));
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool IsCellPointerValid(const void* cell) {
|
||||
auto addr = uintptr_t(cell);
|
||||
MOZ_ALWAYS_INLINE bool IsCellPointerValid(const void* ptr) {
|
||||
auto addr = uintptr_t(ptr);
|
||||
if (addr < ChunkSize || addr % CellAlignBytes != 0) {
|
||||
return false;
|
||||
}
|
||||
auto location = detail::GetCellLocation(cell);
|
||||
if (location == ChunkLocation::TenuredHeap) {
|
||||
return !!detail::GetTenuredGCThingZone(addr);
|
||||
|
||||
auto* cell = reinterpret_cast<const Cell*>(ptr);
|
||||
if (!IsInsideNursery(cell)) {
|
||||
return detail::GetTenuredGCThingZone(addr) != nullptr;
|
||||
}
|
||||
if (location == ChunkLocation::Nursery) {
|
||||
return detail::NurseryCellHasStoreBuffer(cell);
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool IsCellPointerValidOrNull(const void* cell) {
|
||||
@ -554,21 +689,12 @@ namespace gc {
|
||||
|
||||
extern JS_PUBLIC_API void PerformIncrementalReadBarrier(JS::GCCellPtr thing);
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool IsIncrementalBarrierNeededOnTenuredGCThing(
|
||||
const JS::GCCellPtr thing) {
|
||||
MOZ_ASSERT(thing);
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(thing.asCell()));
|
||||
|
||||
static MOZ_ALWAYS_INLINE void ExposeGCThingToActiveJS(JS::GCCellPtr thing) {
|
||||
// TODO: I'd like to assert !RuntimeHeapIsBusy() here but this gets
|
||||
// called while we are tracing the heap, e.g. during memory reporting
|
||||
// (see bug 1313318).
|
||||
MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
|
||||
|
||||
JS::Zone* zone = JS::GetTenuredGCThingZone(thing);
|
||||
return JS::shadow::Zone::from(zone)->needsIncrementalBarrier();
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void ExposeGCThingToActiveJS(JS::GCCellPtr thing) {
|
||||
// GC things residing in the nursery cannot be gray: they have no mark bits.
|
||||
// All live objects in the nursery are moved to tenured at the beginning of
|
||||
// each GC slice, so the gray marker never sees nursery things.
|
||||
@ -576,19 +702,22 @@ static MOZ_ALWAYS_INLINE void ExposeGCThingToActiveJS(JS::GCCellPtr thing) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* cell = reinterpret_cast<TenuredCell*>(thing.asCell());
|
||||
|
||||
// There's nothing to do for permanent GC things that might be owned by
|
||||
// another runtime.
|
||||
if (thing.mayBeOwnedByOtherRuntime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsIncrementalBarrierNeededOnTenuredGCThing(thing)) {
|
||||
auto* zone = JS::shadow::Zone::from(JS::GetTenuredGCThingZone(thing));
|
||||
if (zone->needsIncrementalBarrier()) {
|
||||
PerformIncrementalReadBarrier(thing);
|
||||
} else if (detail::TenuredCellIsMarkedGray(thing.asCell())) {
|
||||
JS::UnmarkGrayGCThingRecursively(thing);
|
||||
} else if (!zone->isGCPreparing() && detail::TenuredCellIsMarkedGray(cell)) {
|
||||
MOZ_ALWAYS_TRUE(JS::UnmarkGrayGCThingRecursively(thing));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!detail::TenuredCellIsMarkedGray(thing.asCell()));
|
||||
MOZ_ASSERT_IF(!zone->isGCPreparing(), !detail::TenuredCellIsMarkedGray(cell));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define js_MemoryFunctions_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
|
@ -626,7 +626,6 @@ struct ZoneStats {
|
||||
MACRO(Other, MallocHeap, scopesMallocHeap) \
|
||||
MACRO(Other, GCHeapUsed, regExpSharedsGCHeap) \
|
||||
MACRO(Other, MallocHeap, regExpSharedsMallocHeap) \
|
||||
MACRO(Other, MallocHeap, typePool) \
|
||||
MACRO(Other, MallocHeap, regexpZone) \
|
||||
MACRO(Other, MallocHeap, jitZone) \
|
||||
MACRO(Other, MallocHeap, baselineStubsOptimized) \
|
||||
@ -709,24 +708,21 @@ struct RealmStats {
|
||||
// actually guaranteed. But for Servo, at least, it's a moot point because
|
||||
// it doesn't provide an ObjectPrivateVisitor so the value will always be
|
||||
// zero.
|
||||
#define FOR_EACH_SIZE(MACRO) \
|
||||
MACRO(Private, MallocHeap, objectsPrivate) \
|
||||
MACRO(Other, GCHeapUsed, scriptsGCHeap) \
|
||||
MACRO(Other, MallocHeap, scriptsMallocHeapData) \
|
||||
MACRO(Other, MallocHeap, baselineData) \
|
||||
MACRO(Other, MallocHeap, baselineStubsFallback) \
|
||||
MACRO(Other, MallocHeap, ionData) \
|
||||
MACRO(Other, MallocHeap, jitScripts) \
|
||||
MACRO(Other, MallocHeap, typeInferenceAllocationSiteTables) \
|
||||
MACRO(Other, MallocHeap, typeInferenceArrayTypeTables) \
|
||||
MACRO(Other, MallocHeap, typeInferenceObjectTypeTables) \
|
||||
MACRO(Other, MallocHeap, realmObject) \
|
||||
MACRO(Other, MallocHeap, realmTables) \
|
||||
MACRO(Other, MallocHeap, innerViewsTable) \
|
||||
MACRO(Other, MallocHeap, objectMetadataTable) \
|
||||
MACRO(Other, MallocHeap, savedStacksSet) \
|
||||
MACRO(Other, MallocHeap, varNamesSet) \
|
||||
MACRO(Other, MallocHeap, nonSyntacticLexicalScopesTable) \
|
||||
#define FOR_EACH_SIZE(MACRO) \
|
||||
MACRO(Private, MallocHeap, objectsPrivate) \
|
||||
MACRO(Other, GCHeapUsed, scriptsGCHeap) \
|
||||
MACRO(Other, MallocHeap, scriptsMallocHeapData) \
|
||||
MACRO(Other, MallocHeap, baselineData) \
|
||||
MACRO(Other, MallocHeap, baselineStubsFallback) \
|
||||
MACRO(Other, MallocHeap, ionData) \
|
||||
MACRO(Other, MallocHeap, jitScripts) \
|
||||
MACRO(Other, MallocHeap, realmObject) \
|
||||
MACRO(Other, MallocHeap, realmTables) \
|
||||
MACRO(Other, MallocHeap, innerViewsTable) \
|
||||
MACRO(Other, MallocHeap, objectMetadataTable) \
|
||||
MACRO(Other, MallocHeap, savedStacksSet) \
|
||||
MACRO(Other, MallocHeap, varNamesSet) \
|
||||
MACRO(Other, MallocHeap, nonSyntacticLexicalScopesTable) \
|
||||
MACRO(Other, MallocHeap, jitRealm)
|
||||
|
||||
RealmStats() = default;
|
||||
|
@ -88,10 +88,24 @@ enum class DynamicImportStatus { Failed = 0, Ok };
|
||||
/**
|
||||
* This must be called after a dynamic import operation is complete.
|
||||
*
|
||||
* If |status| is Failed, any pending exception on the context will be used to
|
||||
* If |evaluationPromise| is rejected, the rejection reason will be used to
|
||||
* complete the user's promise.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool FinishDynamicModuleImport(
|
||||
JSContext* cx, Handle<JSObject*> evaluationPromise,
|
||||
Handle<Value> referencingPrivate, Handle<JSString*> specifier,
|
||||
Handle<JSObject*> promise);
|
||||
|
||||
/**
|
||||
* This must be called after a dynamic import operation is complete.
|
||||
*
|
||||
* This is used so that Top Level Await functionality can be turned off
|
||||
* entirely. It will be removed in bug#1676612.
|
||||
*
|
||||
* If |status| is Failed, any pending exception on the context will be used to
|
||||
* complete the user's promise.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool FinishDynamicModuleImport_NoTLA(
|
||||
JSContext* cx, DynamicImportStatus status, Handle<Value> referencingPrivate,
|
||||
Handle<JSString*> specifier, Handle<JSObject*> promise);
|
||||
|
||||
@ -135,16 +149,32 @@ extern JS_PUBLIC_API bool ModuleInstantiate(JSContext* cx,
|
||||
Handle<JSObject*> moduleRecord);
|
||||
|
||||
/*
|
||||
* Perform the ModuleEvaluate operation on the given source text module record.
|
||||
* Perform the ModuleEvaluate operation on the given source text module record
|
||||
* and returns a bool. A result value is returned in result and is either
|
||||
* undefined (and ignored) or a promise (if Top Level Await is enabled).
|
||||
*
|
||||
* This does nothing if this module has already been evaluated. Otherwise, it
|
||||
* transitively evaluates all dependences of this module and then evaluates this
|
||||
* module.
|
||||
* If this module has already been evaluated, it returns the evaluation
|
||||
* promise. Otherwise, it transitively evaluates all dependences of this module
|
||||
* and then evaluates this module.
|
||||
*
|
||||
* ModuleInstantiate must have completed prior to calling this.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool ModuleEvaluate(JSContext* cx,
|
||||
Handle<JSObject*> moduleRecord);
|
||||
Handle<JSObject*> moduleRecord,
|
||||
MutableHandleValue rval);
|
||||
|
||||
/*
|
||||
* If a module evaluation fails, unwrap the resulting evaluation promise
|
||||
* and rethrow.
|
||||
*
|
||||
* This does nothing if this module succeeds in evaluation. Otherwise, it
|
||||
* takes the reason for the module throwing, unwraps it and throws it as a
|
||||
* regular error rather than as an uncaught promise.
|
||||
*
|
||||
* ModuleEvaluate must have completed prior to calling this.
|
||||
*/
|
||||
extern JS_PUBLIC_API bool ThrowOnModuleEvaluationFailure(
|
||||
JSContext* cx, Handle<JSObject*> evaluationPromise);
|
||||
|
||||
/*
|
||||
* Get a list of the module specifiers used by a source text module
|
||||
|
@ -59,19 +59,19 @@ using OffThreadCompileCallback = void (*)(OffThreadToken* token,
|
||||
extern JS_PUBLIC_API bool CanCompileOffThread(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
|
||||
|
||||
extern JS_PUBLIC_API bool CompileOffThread(
|
||||
extern JS_PUBLIC_API OffThreadToken* CompileOffThread(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceText<char16_t>& srcBuf, OffThreadCompileCallback callback,
|
||||
void* callbackData, OffThreadToken** tokenOut = nullptr);
|
||||
void* callbackData);
|
||||
|
||||
// NOTE: Unlike for the normal sync compilation functions, this function NEVER
|
||||
// INFLATES TO UTF-16. Therefore, it is ALWAYS invoking experimental
|
||||
// UTF-8 support. Inflate to UTF-16 yourself and use the other overload
|
||||
// if you're unable to take a risk using unstable functionality.
|
||||
extern JS_PUBLIC_API bool CompileOffThread(
|
||||
extern JS_PUBLIC_API OffThreadToken* CompileOffThread(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceText<mozilla::Utf8Unit>& srcBuf, OffThreadCompileCallback callback,
|
||||
void* callbackData, OffThreadToken** tokenOut = nullptr);
|
||||
void* callbackData);
|
||||
|
||||
// Finish the off-thread parse/decode task and return the script. Return the
|
||||
// script on success, or return null on failure (usually with an error reported)
|
||||
@ -93,19 +93,19 @@ extern JS_PUBLIC_API JSScript* FinishOffThreadScriptAndStartIncrementalEncoding(
|
||||
extern JS_PUBLIC_API void CancelOffThreadScript(JSContext* cx,
|
||||
OffThreadToken* token);
|
||||
|
||||
extern JS_PUBLIC_API bool CompileOffThreadModule(
|
||||
extern JS_PUBLIC_API OffThreadToken* CompileOffThreadModule(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceText<char16_t>& srcBuf, OffThreadCompileCallback callback,
|
||||
void* callbackData, OffThreadToken** tokenOut = nullptr);
|
||||
void* callbackData);
|
||||
|
||||
// NOTE: Unlike for the normal sync compilation functions, this function NEVER
|
||||
// INFLATES TO UTF-16. Therefore, it is ALWAYS invoking experimental
|
||||
// UTF-8 support. Inflate to UTF-16 yourself and use the other overload
|
||||
// if you're unable to take a risk using unstable functionality.
|
||||
extern JS_PUBLIC_API bool CompileOffThreadModule(
|
||||
extern JS_PUBLIC_API OffThreadToken* CompileOffThreadModule(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceText<mozilla::Utf8Unit>& srcBuf, OffThreadCompileCallback callback,
|
||||
void* callbackData, OffThreadToken** tokenOut = nullptr);
|
||||
void* callbackData);
|
||||
|
||||
extern JS_PUBLIC_API JSObject* FinishOffThreadModule(JSContext* cx,
|
||||
OffThreadToken* token);
|
||||
@ -121,17 +121,26 @@ extern JS_PUBLIC_API bool CanDecodeOffThread(
|
||||
//
|
||||
// If options.useOffThreadParseGlobal is false,
|
||||
// decode stencil from the buffer and instantiate JSScript from it.
|
||||
extern JS_PUBLIC_API bool DecodeOffThreadScript(
|
||||
//
|
||||
// The start of `buffer` and `cursor` should meet
|
||||
// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned.
|
||||
// (This should be handled while encoding).
|
||||
//
|
||||
// `buffer` should be alive until the end of `FinishOffThreadScriptDecoder`.
|
||||
extern JS_PUBLIC_API OffThreadToken* DecodeOffThreadScript(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
|
||||
OffThreadCompileCallback callback, void* callbackData,
|
||||
OffThreadToken** tokenOut = nullptr);
|
||||
OffThreadCompileCallback callback, void* callbackData);
|
||||
|
||||
extern JS_PUBLIC_API bool DecodeOffThreadScript(
|
||||
// The start of `range` should be meet IsTranscodingBytecodeAligned and
|
||||
// AlignTranscodingBytecodeOffset.
|
||||
// (This should be handled while encoding).
|
||||
//
|
||||
// `range` should be alive until the end of `FinishOffThreadScriptDecoder`.
|
||||
extern JS_PUBLIC_API OffThreadToken* DecodeOffThreadScript(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
|
||||
OffThreadCompileCallback callback, void* callbackData,
|
||||
OffThreadToken** tokenOut = nullptr);
|
||||
OffThreadCompileCallback callback, void* callbackData);
|
||||
|
||||
extern JS_PUBLIC_API JSScript* FinishOffThreadScriptDecoder(
|
||||
JSContext* cx, OffThreadToken* token);
|
||||
@ -140,7 +149,7 @@ extern JS_PUBLIC_API void CancelOffThreadScriptDecoder(JSContext* cx,
|
||||
OffThreadToken* token);
|
||||
|
||||
// Decode multiple JSScript from the sources.
|
||||
extern JS_PUBLIC_API bool DecodeMultiOffThreadScripts(
|
||||
extern JS_PUBLIC_API OffThreadToken* DecodeMultiOffThreadScripts(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
mozilla::Vector<TranscodeSource>& sources,
|
||||
OffThreadCompileCallback callback, void* callbackData);
|
||||
|
@ -119,6 +119,8 @@
|
||||
REAL(WasmMemory, OCLASP(WasmMemory)) \
|
||||
REAL(WasmTable, OCLASP(WasmTable)) \
|
||||
REAL(WasmGlobal, OCLASP(WasmGlobal)) \
|
||||
REAL(WasmException, OCLASP(WasmException)) \
|
||||
REAL(WasmRuntimeException, OCLASP(WasmRuntimeException)) \
|
||||
REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \
|
||||
REAL(WeakRef, OCLASP(WeakRef)) \
|
||||
REAL(Iterator, OCLASP(Iterator)) \
|
||||
|
@ -369,7 +369,7 @@ class JS_FRIEND_API BaseProxyHandler {
|
||||
extern JS_FRIEND_DATA const JSClass ProxyClass;
|
||||
|
||||
inline bool IsProxy(const JSObject* obj) {
|
||||
return JS::GetClass(obj)->isProxy();
|
||||
return JS::GetClass(obj)->isProxyObject();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@ -581,10 +581,6 @@ JS_FRIEND_API JSObject* NewProxyObject(
|
||||
JSContext* cx, const BaseProxyHandler* handler, JS::HandleValue priv,
|
||||
JSObject* proto, const ProxyOptions& options = ProxyOptions());
|
||||
|
||||
JS_FRIEND_API JSObject* NewSingletonProxyObject(
|
||||
JSContext* cx, const BaseProxyHandler* handler, JS::HandleValue priv,
|
||||
JSObject* proto, const ProxyOptions& options = ProxyOptions());
|
||||
|
||||
JSObject* RenewProxyObject(JSContext* cx, JSObject* obj,
|
||||
BaseProxyHandler* handler, const JS::Value& priv);
|
||||
|
||||
|
@ -46,6 +46,9 @@ enum class CompartmentSpecifier {
|
||||
|
||||
// Create a new realm in an existing compartment.
|
||||
ExistingCompartment,
|
||||
|
||||
// Internal use only. Create the self-hosting compartment.
|
||||
NewCompartmentInSelfHostingZone,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -93,6 +96,7 @@ class JS_PUBLIC_API RealmCreationOptions {
|
||||
RealmCreationOptions& setNewCompartmentAndZone();
|
||||
RealmCreationOptions& setExistingCompartment(JSObject* obj);
|
||||
RealmCreationOptions& setExistingCompartment(Compartment* compartment);
|
||||
RealmCreationOptions& setNewCompartmentInSelfHostingZone();
|
||||
|
||||
// Certain compartments are implementation details of the embedding, and
|
||||
// references to them should never leak out to script. This flag causes this
|
||||
@ -349,9 +353,11 @@ extern JS_PUBLIC_API const RealmCreationOptions& RealmCreationOptionsRef(
|
||||
extern JS_PUBLIC_API const RealmCreationOptions& RealmCreationOptionsRef(
|
||||
JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API RealmBehaviors& RealmBehaviorsRef(Realm* realm);
|
||||
extern JS_PUBLIC_API const RealmBehaviors& RealmBehaviorsRef(Realm* realm);
|
||||
|
||||
extern JS_PUBLIC_API RealmBehaviors& RealmBehaviorsRef(JSContext* cx);
|
||||
extern JS_PUBLIC_API const RealmBehaviors& RealmBehaviorsRef(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API void SetRealmNonLive(Realm* realm);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace JS {
|
||||
/**
|
||||
* Regular expression flag values, suitable for initializing a collection of
|
||||
* regular expression flags as defined below in |RegExpFlags|. Flags are listed
|
||||
* in alphabetical order by syntax -- /g, /i, /m, /s, /u, /y.
|
||||
* in alphabetical order by syntax -- /d, /g, /i, /m, /s, /u, /y.
|
||||
*/
|
||||
class RegExpFlag {
|
||||
// WARNING TO SPIDERMONKEY HACKERS (embedders must assume these values can
|
||||
@ -28,35 +28,40 @@ class RegExpFlag {
|
||||
// ascending order) unless you also add a translation layer.
|
||||
|
||||
public:
|
||||
/**
|
||||
* Add .indices property to the match result, i.e. /d
|
||||
*/
|
||||
static constexpr uint8_t HasIndices = 0b100'0000;
|
||||
|
||||
/**
|
||||
* Act globally and find *all* matches (rather than stopping after just the
|
||||
* first one), i.e. /g.
|
||||
*/
|
||||
static constexpr uint8_t Global = 0b00'0010;
|
||||
static constexpr uint8_t Global = 0b000'0010;
|
||||
|
||||
/**
|
||||
* Interpret regular expression source text case-insensitively by folding
|
||||
* uppercase letters to lowercase, i.e. /i.
|
||||
*/
|
||||
static constexpr uint8_t IgnoreCase = 0b00'0001;
|
||||
static constexpr uint8_t IgnoreCase = 0b000'0001;
|
||||
|
||||
/** Treat ^ and $ as begin and end of line, i.e. /m. */
|
||||
static constexpr uint8_t Multiline = 0b00'0100;
|
||||
static constexpr uint8_t Multiline = 0b000'0100;
|
||||
|
||||
/* Allow . to match newline characters, i.e. /s. */
|
||||
static constexpr uint8_t DotAll = 0b10'0000;
|
||||
static constexpr uint8_t DotAll = 0b010'0000;
|
||||
|
||||
/** Use Unicode semantics, i.e. /u. */
|
||||
static constexpr uint8_t Unicode = 0b01'0000;
|
||||
static constexpr uint8_t Unicode = 0b001'0000;
|
||||
|
||||
/** Only match starting from <regular expression>.lastIndex, i.e. /y. */
|
||||
static constexpr uint8_t Sticky = 0b00'1000;
|
||||
static constexpr uint8_t Sticky = 0b000'1000;
|
||||
|
||||
/** No regular expression flags. */
|
||||
static constexpr uint8_t NoFlags = 0b00'0000;
|
||||
static constexpr uint8_t NoFlags = 0b000'0000;
|
||||
|
||||
/** All regular expression flags. */
|
||||
static constexpr uint8_t AllFlags = 0b11'1111;
|
||||
static constexpr uint8_t AllFlags = 0b111'1111;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -106,6 +111,7 @@ class RegExpFlags {
|
||||
return RegExpFlags(~flags_ & RegExpFlag::AllFlags);
|
||||
}
|
||||
|
||||
bool hasIndices() const { return flags_ & RegExpFlag::HasIndices; }
|
||||
bool global() const { return flags_ & RegExpFlag::Global; }
|
||||
bool ignoreCase() const { return flags_ & RegExpFlag::IgnoreCase; }
|
||||
bool multiline() const { return flags_ & RegExpFlag::Multiline; }
|
||||
|
@ -212,9 +212,6 @@ struct UnusedZero {
|
||||
|
||||
static constexpr bool value = true;
|
||||
static constexpr StorageType nullValue = 0;
|
||||
static constexpr StorageType GetDefaultValue() {
|
||||
return T::ErrorKind::Unspecified;
|
||||
}
|
||||
|
||||
static constexpr void AssertValid(StorageType aValue) {}
|
||||
static constexpr T Inspect(const StorageType& aValue) {
|
||||
|
@ -923,15 +923,22 @@ enum class AutoGCRooterKind : uint8_t {
|
||||
Limit
|
||||
};
|
||||
|
||||
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
|
||||
// instantiation of MapTypeToRootKind.
|
||||
namespace detail {
|
||||
// Dummy type to store root list entry pointers as. This code does not just use
|
||||
// the actual type, because then eg JSObject* and JSFunction* would be assumed
|
||||
// to never alias but they do (they are stored in the same list). Also, do not
|
||||
// use `void*` so that `Rooted<void*>` is a compile error.
|
||||
struct RootListEntry;
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
struct MapTypeToRootKind<void*> {
|
||||
struct MapTypeToRootKind<detail::RootListEntry*> {
|
||||
static const RootKind kind = RootKind::Traceable;
|
||||
};
|
||||
|
||||
using RootedListHeads =
|
||||
mozilla::EnumeratedArray<RootKind, RootKind::Limit, Rooted<void*>*>;
|
||||
mozilla::EnumeratedArray<RootKind, RootKind::Limit,
|
||||
Rooted<detail::RootListEntry*>*>;
|
||||
|
||||
using AutoRooterListHeads =
|
||||
mozilla::EnumeratedArray<AutoGCRooterKind, AutoGCRooterKind::Limit,
|
||||
@ -1071,7 +1078,7 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
|
||||
inline void registerWithRootLists(RootedListHeads& roots) {
|
||||
this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
|
||||
this->prev = *stack;
|
||||
*stack = reinterpret_cast<Rooted<void*>*>(this);
|
||||
*stack = reinterpret_cast<Rooted<detail::RootListEntry*>*>(this);
|
||||
}
|
||||
|
||||
inline RootedListHeads& rootLists(RootingContext* cx) {
|
||||
@ -1121,7 +1128,8 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
|
||||
}
|
||||
|
||||
~Rooted() {
|
||||
MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
|
||||
MOZ_ASSERT(*stack ==
|
||||
reinterpret_cast<Rooted<detail::RootListEntry*>*>(this));
|
||||
*stack = prev;
|
||||
}
|
||||
|
||||
@ -1153,12 +1161,12 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
|
||||
|
||||
private:
|
||||
/*
|
||||
* These need to be templated on void* to avoid aliasing issues between, for
|
||||
* example, Rooted<JSObject> and Rooted<JSFunction>, which use the same
|
||||
* stack head pointer for different classes.
|
||||
* These need to be templated on RootListEntry* to avoid aliasing issues
|
||||
* between, for example, Rooted<JSObject*> and Rooted<JSFunction*>, which use
|
||||
* the same stack head pointer for different classes.
|
||||
*/
|
||||
Rooted<void*>** stack;
|
||||
Rooted<void*>* prev;
|
||||
Rooted<detail::RootListEntry*>** stack;
|
||||
Rooted<detail::RootListEntry*>* prev;
|
||||
|
||||
Ptr ptr;
|
||||
|
||||
@ -1287,11 +1295,13 @@ inline MutableHandle<T>::MutableHandle(PersistentRooted<T>* root) {
|
||||
ptr = root->address();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void AddPersistentRoot(RootingContext* cx, RootKind kind,
|
||||
PersistentRooted<void*>* root);
|
||||
JS_PUBLIC_API void AddPersistentRoot(
|
||||
RootingContext* cx, RootKind kind,
|
||||
PersistentRooted<detail::RootListEntry*>* root);
|
||||
|
||||
JS_PUBLIC_API void AddPersistentRoot(JSRuntime* rt, RootKind kind,
|
||||
PersistentRooted<void*>* root);
|
||||
JS_PUBLIC_API void AddPersistentRoot(
|
||||
JSRuntime* rt, RootKind kind,
|
||||
PersistentRooted<detail::RootListEntry*>* root);
|
||||
|
||||
/**
|
||||
* A copyable, assignable global GC root type with arbitrary lifetime, an
|
||||
@ -1340,15 +1350,17 @@ class PersistentRooted
|
||||
void registerWithRootLists(RootingContext* cx) {
|
||||
MOZ_ASSERT(!initialized());
|
||||
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
|
||||
AddPersistentRoot(cx, kind,
|
||||
reinterpret_cast<JS::PersistentRooted<void*>*>(this));
|
||||
AddPersistentRoot(
|
||||
cx, kind,
|
||||
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
|
||||
}
|
||||
|
||||
void registerWithRootLists(JSRuntime* rt) {
|
||||
MOZ_ASSERT(!initialized());
|
||||
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
|
||||
AddPersistentRoot(rt, kind,
|
||||
reinterpret_cast<JS::PersistentRooted<void*>*>(this));
|
||||
AddPersistentRoot(
|
||||
rt, kind,
|
||||
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1476,7 +1488,7 @@ class MutableWrappedPtrOperations<UniquePtr<T, D>, Container>
|
||||
UniquePtr<T, D>& uniquePtr() { return static_cast<Container*>(this)->get(); }
|
||||
|
||||
public:
|
||||
MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() {
|
||||
[[nodiscard]] typename UniquePtr<T, D>::Pointer release() {
|
||||
return uniquePtr().release();
|
||||
}
|
||||
void reset(T* ptr = T()) { uniquePtr().reset(ptr); }
|
||||
|
@ -15,9 +15,8 @@ namespace js {
|
||||
|
||||
namespace Scalar {
|
||||
|
||||
// Scalar types that can appear in typed arrays and typed objects.
|
||||
// Scalar types that can appear in typed arrays.
|
||||
// The enum values must be kept in sync with:
|
||||
// * the JS_SCALARTYPEREPR constants
|
||||
// * the TYPEDARRAY_KIND constants
|
||||
// * the SCTAG_TYPED_ARRAY constants
|
||||
// * JS_FOR_EACH_TYPEDARRAY
|
||||
@ -119,6 +118,42 @@ static inline bool isBigIntType(Type atype) {
|
||||
MOZ_CRASH("invalid scalar type");
|
||||
}
|
||||
|
||||
static inline const char* name(Type atype) {
|
||||
switch (atype) {
|
||||
case Int8:
|
||||
return "Int8";
|
||||
case Uint8:
|
||||
return "Uint8";
|
||||
case Int16:
|
||||
return "Int16";
|
||||
case Uint16:
|
||||
return "Uint16";
|
||||
case Int32:
|
||||
return "Int32";
|
||||
case Uint32:
|
||||
return "Uint32";
|
||||
case Float32:
|
||||
return "Float32";
|
||||
case Float64:
|
||||
return "Float64";
|
||||
case Uint8Clamped:
|
||||
return "Uint8Clamped";
|
||||
case BigInt64:
|
||||
return "BigInt64";
|
||||
case BigUint64:
|
||||
return "BigUint64";
|
||||
case MaxTypedArrayViewType:
|
||||
return "MaxTypedArrayViewType";
|
||||
case Int64:
|
||||
return "Int64";
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
case Simd128:
|
||||
return "Simd128";
|
||||
#endif
|
||||
}
|
||||
MOZ_CRASH("invalid scalar type");
|
||||
}
|
||||
|
||||
} // namespace Scalar
|
||||
|
||||
} // namespace js
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define js_SharedArrayBuffer_h
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdint.h> // uint32_t
|
||||
#include <stdint.h> // uint8_t
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
@ -28,7 +28,7 @@ namespace JS {
|
||||
* true.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewSharedArrayBuffer(JSContext* cx,
|
||||
uint32_t nbytes);
|
||||
size_t nbytes);
|
||||
|
||||
// TYPE TESTING
|
||||
|
||||
@ -44,7 +44,7 @@ extern JS_PUBLIC_API bool IsSharedArrayBufferObject(JSObject* obj);
|
||||
|
||||
extern JS_PUBLIC_API JSObject* UnwrapSharedArrayBuffer(JSObject* obj);
|
||||
|
||||
extern JS_PUBLIC_API uint32_t GetSharedArrayBufferByteLength(JSObject* obj);
|
||||
extern JS_PUBLIC_API size_t GetSharedArrayBufferByteLength(JSObject* obj);
|
||||
|
||||
extern JS_PUBLIC_API uint8_t* GetSharedArrayBufferData(JSObject* obj,
|
||||
bool* isSharedMemory,
|
||||
@ -55,7 +55,7 @@ extern JS_PUBLIC_API uint8_t* GetSharedArrayBufferData(JSObject* obj,
|
||||
// There is an isShared out argument for API consistency (eases use from DOM).
|
||||
// It will always be set to true.
|
||||
extern JS_PUBLIC_API void GetSharedArrayBufferLengthAndData(
|
||||
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
|
||||
/**
|
||||
* Returns true if there are any live SharedArrayBuffer objects, including those
|
||||
|
@ -5,7 +5,9 @@
|
||||
#ifndef js_SliceBudget_h
|
||||
#define js_SliceBudget_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -14,77 +16,69 @@
|
||||
namespace js {
|
||||
|
||||
struct JS_PUBLIC_API TimeBudget {
|
||||
int64_t budget;
|
||||
const int64_t budget;
|
||||
mozilla::TimeStamp deadline; // Calculated when SliceBudget is constructed.
|
||||
|
||||
explicit TimeBudget(int64_t milliseconds) { budget = milliseconds; }
|
||||
explicit TimeBudget(int64_t milliseconds) : budget(milliseconds) {}
|
||||
};
|
||||
|
||||
struct JS_PUBLIC_API WorkBudget {
|
||||
int64_t budget;
|
||||
const int64_t budget;
|
||||
|
||||
explicit WorkBudget(int64_t work) { budget = work; }
|
||||
explicit WorkBudget(int64_t work) : budget(work) {}
|
||||
};
|
||||
|
||||
struct UnlimitedBudget {};
|
||||
|
||||
/*
|
||||
* This class records how much work has been done in a given collection slice,
|
||||
* so that we can return before pausing for too long. Some slices are allowed
|
||||
* to run for unlimited time, and others are bounded. To reduce the number of
|
||||
* gettimeofday calls, we only check the time every 1000 operations.
|
||||
* This class describes a limit to the amount of work to be performed in a GC
|
||||
* slice, so that we can return to the mutator without pausing for too long. The
|
||||
* budget may be based on a deadline time or an amount of work to be performed,
|
||||
* or may be unlimited.
|
||||
*
|
||||
* To reduce the number of gettimeofday calls, we only check the time every 1000
|
||||
* operations.
|
||||
*/
|
||||
class JS_PUBLIC_API SliceBudget {
|
||||
static mozilla::TimeStamp unlimitedDeadline;
|
||||
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
|
||||
static const intptr_t UnlimitedCounter = INTPTR_MAX;
|
||||
|
||||
mozilla::Variant<TimeBudget, WorkBudget, UnlimitedBudget> budget;
|
||||
int64_t counter;
|
||||
|
||||
SliceBudget() : budget(UnlimitedBudget()), counter(UnlimitedCounter) {}
|
||||
|
||||
bool checkOverBudget();
|
||||
|
||||
SliceBudget();
|
||||
|
||||
public:
|
||||
// Memory of the originally requested budget. If isUnlimited, neither of
|
||||
// these are in use. If deadline==0, then workBudget is valid. Otherwise
|
||||
// timeBudget is valid.
|
||||
TimeBudget timeBudget;
|
||||
WorkBudget workBudget;
|
||||
static const intptr_t StepsPerTimeCheck = 1000;
|
||||
|
||||
mozilla::TimeStamp deadline;
|
||||
intptr_t counter;
|
||||
|
||||
static const intptr_t CounterReset = 1000;
|
||||
|
||||
static const int64_t UnlimitedTimeBudget = -1;
|
||||
static const int64_t UnlimitedWorkBudget = -1;
|
||||
|
||||
/* Use to create an unlimited budget. */
|
||||
// Use to create an unlimited budget.
|
||||
static SliceBudget unlimited() { return SliceBudget(); }
|
||||
|
||||
/* Instantiate as SliceBudget(TimeBudget(n)). */
|
||||
// Instantiate as SliceBudget(TimeBudget(n)).
|
||||
explicit SliceBudget(TimeBudget time);
|
||||
|
||||
/* Instantiate as SliceBudget(WorkBudget(n)). */
|
||||
// Instantiate as SliceBudget(WorkBudget(n)).
|
||||
explicit SliceBudget(WorkBudget work);
|
||||
|
||||
void makeUnlimited() {
|
||||
MOZ_ASSERT(unlimitedDeadline);
|
||||
deadline = unlimitedDeadline;
|
||||
counter = unlimitedStartCounter;
|
||||
explicit SliceBudget(mozilla::TimeDuration time)
|
||||
: SliceBudget(TimeBudget(time.ToMilliseconds())) {}
|
||||
|
||||
void step(uint64_t steps = 1) {
|
||||
MOZ_ASSERT(steps > 0);
|
||||
counter -= steps;
|
||||
}
|
||||
|
||||
void step(intptr_t amt = 1) { counter -= amt; }
|
||||
bool isOverBudget() { return counter <= 0 && checkOverBudget(); }
|
||||
|
||||
bool isOverBudget() {
|
||||
if (counter > 0) {
|
||||
return false;
|
||||
}
|
||||
return checkOverBudget();
|
||||
}
|
||||
bool isWorkBudget() const { return budget.is<WorkBudget>(); }
|
||||
bool isTimeBudget() const { return budget.is<TimeBudget>(); }
|
||||
bool isUnlimited() const { return budget.is<UnlimitedBudget>(); }
|
||||
|
||||
bool isWorkBudget() const { return deadline.IsNull(); }
|
||||
bool isTimeBudget() const { return !deadline.IsNull() && !isUnlimited(); }
|
||||
bool isUnlimited() const { return deadline == unlimitedDeadline; }
|
||||
int64_t timeBudget() const { return budget.as<TimeBudget>().budget; }
|
||||
int64_t workBudget() const { return budget.as<WorkBudget>().budget; }
|
||||
|
||||
int describe(char* buffer, size_t maxlen) const;
|
||||
|
||||
static void Init();
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
@ -47,7 +47,7 @@
|
||||
#define js_SourceText_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_COLD, MOZ_IS_CLASS_INIT, MOZ_MUST_USE
|
||||
#include "mozilla/Attributes.h" // MOZ_COLD, MOZ_IS_CLASS_INIT
|
||||
#include "mozilla/Likely.h" // MOZ_UNLIKELY
|
||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||
|
||||
@ -137,9 +137,9 @@ class SourceText final {
|
||||
* |units| may be null if |unitsLength == 0|; if so, this will silently be
|
||||
* initialized using non-null, unowned units.
|
||||
*/
|
||||
MOZ_IS_CLASS_INIT MOZ_MUST_USE bool init(JSContext* cx, const Unit* units,
|
||||
size_t unitsLength,
|
||||
SourceOwnership ownership) {
|
||||
[[nodiscard]] MOZ_IS_CLASS_INIT bool init(JSContext* cx, const Unit* units,
|
||||
size_t unitsLength,
|
||||
SourceOwnership ownership) {
|
||||
MOZ_ASSERT_IF(units == nullptr, unitsLength == 0);
|
||||
|
||||
// Ideally we'd use |Unit| and not cast below, but the risk of a static
|
||||
@ -181,9 +181,9 @@ class SourceText final {
|
||||
template <typename Char,
|
||||
typename = std::enable_if_t<std::is_same_v<Char, CharT> &&
|
||||
!std::is_same_v<Char, Unit>>>
|
||||
MOZ_IS_CLASS_INIT MOZ_MUST_USE bool init(JSContext* cx, const Char* chars,
|
||||
size_t charsLength,
|
||||
SourceOwnership ownership) {
|
||||
[[nodiscard]] MOZ_IS_CLASS_INIT bool init(JSContext* cx, const Char* chars,
|
||||
size_t charsLength,
|
||||
SourceOwnership ownership) {
|
||||
return init(cx, reinterpret_cast<const Unit*>(chars), charsLength,
|
||||
ownership);
|
||||
}
|
||||
@ -191,9 +191,9 @@ class SourceText final {
|
||||
/**
|
||||
* Initialize this using source units transferred out of |data|.
|
||||
*/
|
||||
MOZ_MUST_USE bool init(JSContext* cx,
|
||||
js::UniquePtr<Unit[], JS::FreePolicy> data,
|
||||
size_t dataLength) {
|
||||
[[nodiscard]] bool init(JSContext* cx,
|
||||
js::UniquePtr<Unit[], JS::FreePolicy> data,
|
||||
size_t dataLength) {
|
||||
return init(cx, data.release(), dataLength, SourceOwnership::TakeOwnership);
|
||||
}
|
||||
|
||||
@ -209,9 +209,9 @@ class SourceText final {
|
||||
template <typename Char,
|
||||
typename = std::enable_if_t<std::is_same_v<Char, CharT> &&
|
||||
!std::is_same_v<Char, Unit>>>
|
||||
MOZ_MUST_USE bool init(JSContext* cx,
|
||||
js::UniquePtr<Char[], JS::FreePolicy> data,
|
||||
size_t dataLength) {
|
||||
[[nodiscard]] bool init(JSContext* cx,
|
||||
js::UniquePtr<Char[], JS::FreePolicy> data,
|
||||
size_t dataLength) {
|
||||
return init(cx, data.release(), dataLength, SourceOwnership::TakeOwnership);
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,9 @@
|
||||
#define js_StableStringChars_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS, MOZ_MUST_USE
|
||||
#include "mozilla/Maybe.h" // mozilla::Maybe
|
||||
#include "mozilla/Range.h" // mozilla::Range
|
||||
#include "mozilla/Attributes.h" // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS
|
||||
#include "mozilla/Maybe.h" // mozilla::Maybe
|
||||
#include "mozilla/Range.h" // mozilla::Range
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdint.h> // uint8_t
|
||||
@ -59,10 +59,10 @@ class MOZ_STACK_CLASS JS_FRIEND_API AutoStableStringChars final {
|
||||
explicit AutoStableStringChars(JSContext* cx)
|
||||
: s_(cx), state_(Uninitialized) {}
|
||||
|
||||
MOZ_MUST_USE bool init(JSContext* cx, JSString* s);
|
||||
[[nodiscard]] bool init(JSContext* cx, JSString* s);
|
||||
|
||||
/* Like init(), but Latin1 chars are inflated to TwoByte. */
|
||||
MOZ_MUST_USE bool initTwoByte(JSContext* cx, JSString* s);
|
||||
[[nodiscard]] bool initTwoByte(JSContext* cx, JSString* s);
|
||||
|
||||
bool isLatin1() const { return state_ == Latin1; }
|
||||
bool isTwoByte() const { return state_ == TwoByte; }
|
||||
|
@ -500,6 +500,8 @@ class JS_PUBLIC_API WritableStreamUnderlyingSink {
|
||||
virtual void finalize() = 0;
|
||||
};
|
||||
|
||||
// ReadableStream.prototype.pipeTo SUPPORT
|
||||
|
||||
/**
|
||||
* The signature of a function that, when passed an |AbortSignal| instance, will
|
||||
* return the value of its "aborted" flag.
|
||||
@ -509,17 +511,18 @@ class JS_PUBLIC_API WritableStreamUnderlyingSink {
|
||||
using AbortSignalIsAborted = bool (*)(JSObject* signal);
|
||||
|
||||
/**
|
||||
* Dictate all details of handling of |AbortSignal| objects for SpiderMonkey to
|
||||
* use. This should only be performed once, for a single context associated
|
||||
* with a |JSRuntime|.
|
||||
* Dictate embedder-specific details necessary to implement certain aspects of
|
||||
* the |ReadableStream.prototype.pipeTo| function. This should be performed
|
||||
* exactly once, for a single context associated with a |JSRuntime|.
|
||||
*
|
||||
* The |ReadableStream.prototype.pipeTo| function accepts a |signal| argument
|
||||
* that may be used to abort the piping operation. This argument must be either
|
||||
* |undefined| (in other words, the piping operation can't be aborted) or an
|
||||
* |AbortSignal| instance. |AbortSignal| is defined by WebIDL and the DOM in
|
||||
* the web embedding. Therefore, embedders must use this function to specify
|
||||
* how such objects can be recognized and how to perform various essential
|
||||
* actions upon them.
|
||||
* |AbortSignal| instance (that may be aborted using the signal's associated
|
||||
* |AbortController|). |AbortSignal| is defined by WebIDL and the DOM in the
|
||||
* web embedding. Therefore, embedders must use this function to specify how
|
||||
* such objects can be recognized and how to perform various essential actions
|
||||
* upon them.
|
||||
*
|
||||
* The provided |isAborted| function will be called with an unwrapped
|
||||
* |AbortSignal| instance, while that instance's realm has been entered.
|
||||
@ -528,8 +531,9 @@ using AbortSignalIsAborted = bool (*)(JSObject* signal);
|
||||
* |AbortSignal|?" question must be asked, that question will simply be answered
|
||||
* "no".
|
||||
*/
|
||||
extern JS_PUBLIC_API void InitAbortSignalHandling(
|
||||
const JSClass* clasp, AbortSignalIsAborted isAborted, JSContext* cx);
|
||||
extern JS_PUBLIC_API void InitPipeToHandling(const JSClass* abortSignalClass,
|
||||
AbortSignalIsAborted isAborted,
|
||||
JSContext* cx);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "js/shadow/String.h" // JS::shadow::String
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE, MOZ_MUST_USE
|
||||
#include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE
|
||||
#include "mozilla/Likely.h" // MOZ_LIKELY
|
||||
|
||||
#include <algorithm> // std::copy_n
|
||||
@ -191,9 +191,9 @@ MOZ_ALWAYS_INLINE void LossyCopyLinearStringChars(char* dest, JSLinearString* s,
|
||||
* This function is fallible. If you already have a linear string, use the
|
||||
* infallible |JS::CopyLinearStringChars| above instead.
|
||||
*/
|
||||
inline MOZ_MUST_USE bool CopyStringChars(JSContext* cx, char16_t* dest,
|
||||
JSString* s, size_t len,
|
||||
size_t start = 0) {
|
||||
[[nodiscard]] inline bool CopyStringChars(JSContext* cx, char16_t* dest,
|
||||
JSString* s, size_t len,
|
||||
size_t start = 0) {
|
||||
JSLinearString* linear = StringToLinearString(cx, s);
|
||||
if (!linear) {
|
||||
return false;
|
||||
@ -210,9 +210,9 @@ inline MOZ_MUST_USE bool CopyStringChars(JSContext* cx, char16_t* dest,
|
||||
* This function is fallible. If you already have a linear string, use the
|
||||
* infallible |JS::LossyCopyLinearStringChars| above instead.
|
||||
*/
|
||||
inline MOZ_MUST_USE bool LossyCopyStringChars(JSContext* cx, char* dest,
|
||||
JSString* s, size_t len,
|
||||
size_t start = 0) {
|
||||
[[nodiscard]] inline bool LossyCopyStringChars(JSContext* cx, char* dest,
|
||||
JSString* s, size_t len,
|
||||
size_t start = 0) {
|
||||
JSLinearString* linear = StringToLinearString(cx, s);
|
||||
if (!linear) {
|
||||
return false;
|
||||
|
@ -379,9 +379,9 @@ class SharedArrayRawBufferRefs {
|
||||
SharedArrayRawBufferRefs& operator=(SharedArrayRawBufferRefs&& other);
|
||||
~SharedArrayRawBufferRefs();
|
||||
|
||||
MOZ_MUST_USE bool acquire(JSContext* cx, SharedArrayRawBuffer* rawbuf);
|
||||
MOZ_MUST_USE bool acquireAll(JSContext* cx,
|
||||
const SharedArrayRawBufferRefs& that);
|
||||
[[nodiscard]] bool acquire(JSContext* cx, SharedArrayRawBuffer* rawbuf);
|
||||
[[nodiscard]] bool acquireAll(JSContext* cx,
|
||||
const SharedArrayRawBufferRefs& that);
|
||||
void takeOwnership(SharedArrayRawBufferRefs&&);
|
||||
void releaseAll();
|
||||
|
||||
@ -456,7 +456,7 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData {
|
||||
ownTransferables_ = policy;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool Init(size_t initialCapacity = 0) {
|
||||
[[nodiscard]] bool Init(size_t initialCapacity = 0) {
|
||||
return bufList_.Init(0, initialCapacity);
|
||||
}
|
||||
|
||||
@ -486,24 +486,25 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData {
|
||||
|
||||
const Iterator Start() const { return bufList_.Iter(); }
|
||||
|
||||
MOZ_MUST_USE bool Advance(Iterator& iter, size_t distance) const {
|
||||
[[nodiscard]] bool Advance(Iterator& iter, size_t distance) const {
|
||||
return iter.AdvanceAcrossSegments(bufList_, distance);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool ReadBytes(Iterator& iter, char* buffer, size_t size) const {
|
||||
[[nodiscard]] bool ReadBytes(Iterator& iter, char* buffer,
|
||||
size_t size) const {
|
||||
return bufList_.ReadBytes(iter, buffer, size);
|
||||
}
|
||||
|
||||
// Append new data to the end of the buffer.
|
||||
MOZ_MUST_USE bool AppendBytes(const char* data, size_t size) {
|
||||
[[nodiscard]] bool AppendBytes(const char* data, size_t size) {
|
||||
MOZ_ASSERT(scope() != JS::StructuredCloneScope::Unassigned);
|
||||
return bufList_.WriteBytes(data, size);
|
||||
}
|
||||
|
||||
// Update data stored within the existing buffer. There must be at least
|
||||
// 'size' bytes between the position of 'iter' and the end of the buffer.
|
||||
MOZ_MUST_USE bool UpdateBytes(Iterator& iter, const char* data,
|
||||
size_t size) const {
|
||||
[[nodiscard]] bool UpdateBytes(Iterator& iter, const char* data,
|
||||
size_t size) const {
|
||||
MOZ_ASSERT(scope() != JS::StructuredCloneScope::Unassigned);
|
||||
while (size > 0) {
|
||||
size_t remaining = iter.RemainingInSegment();
|
||||
@ -553,7 +554,7 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData {
|
||||
}
|
||||
|
||||
// Append the entire contents of other's bufList_ to our own.
|
||||
MOZ_MUST_USE bool Append(const JSStructuredCloneData& other) {
|
||||
[[nodiscard]] bool Append(const JSStructuredCloneData& other) {
|
||||
MOZ_ASSERT(scope() == other.scope());
|
||||
return other.ForEachDataChunk(
|
||||
[&](const char* data, size_t size) { return AppendBytes(data, size); });
|
||||
|
@ -27,14 +27,9 @@ JS_FRIEND_API size_t GCTraceKindSize(JS::TraceKind kind);
|
||||
// Kinds of JSTracer.
|
||||
enum class TracerKind {
|
||||
// Marking path: a tracer used only for marking liveness of cells, not
|
||||
// for moving them. The kind will transition to WeakMarking after
|
||||
// everything reachable by regular edges has been marked.
|
||||
// for moving them.
|
||||
Marking,
|
||||
|
||||
// A tracer that traverses the graph for the purposes of moving objects
|
||||
// from the nursery to the tenured heap.
|
||||
Tenuring,
|
||||
|
||||
// Generic tracers: Internal tracers that have a different virtual method
|
||||
// called for each edge kind.
|
||||
//
|
||||
@ -42,6 +37,7 @@ enum class TracerKind {
|
||||
Generic,
|
||||
|
||||
// Specific kinds of generic tracer.
|
||||
Tenuring,
|
||||
Moving,
|
||||
GrayBuffering,
|
||||
ClearEdges,
|
||||
|
@ -41,24 +41,63 @@ struct TranscodeSource final {
|
||||
|
||||
using TranscodeSources = mozilla::Vector<TranscodeSource>;
|
||||
|
||||
enum TranscodeResult : uint8_t {
|
||||
enum class TranscodeResult : uint8_t {
|
||||
// Successful encoding / decoding.
|
||||
TranscodeResult_Ok = 0,
|
||||
Ok = 0,
|
||||
|
||||
// A warning message, is set to the message out-param.
|
||||
TranscodeResult_Failure = 0x10,
|
||||
TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
|
||||
TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
|
||||
TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
|
||||
TranscodeResult_Failure_BadDecode = TranscodeResult_Failure | 0x4,
|
||||
TranscodeResult_Failure_WrongCompileOption = TranscodeResult_Failure | 0x5,
|
||||
TranscodeResult_Failure_NotInterpretedFun = TranscodeResult_Failure | 0x6,
|
||||
Failure = 0x10,
|
||||
Failure_BadBuildId = Failure | 0x1,
|
||||
Failure_RunOnceNotSupported = Failure | 0x2,
|
||||
Failure_AsmJSNotSupported = Failure | 0x3,
|
||||
Failure_BadDecode = Failure | 0x4,
|
||||
Failure_WrongCompileOption = Failure | 0x5,
|
||||
Failure_NotInterpretedFun = Failure | 0x6,
|
||||
|
||||
// There is a pending exception on the context.
|
||||
TranscodeResult_Throw = 0x20
|
||||
Throw = 0x20
|
||||
};
|
||||
|
||||
inline bool IsTranscodeFailureResult(const TranscodeResult result) {
|
||||
uint8_t raw_result = static_cast<uint8_t>(result);
|
||||
uint8_t raw_failure = static_cast<uint8_t>(TranscodeResult::Failure);
|
||||
TranscodeResult masked =
|
||||
static_cast<TranscodeResult>(raw_result & raw_failure);
|
||||
return masked == TranscodeResult::Failure;
|
||||
}
|
||||
|
||||
static constexpr size_t BytecodeOffsetAlignment = 4;
|
||||
static_assert(BytecodeOffsetAlignment <= alignof(std::max_align_t),
|
||||
"Alignment condition requires a custom allocator.");
|
||||
|
||||
// Align the bytecode offset for transcoding for the requirement.
|
||||
inline size_t AlignTranscodingBytecodeOffset(size_t offset) {
|
||||
size_t extra = offset % BytecodeOffsetAlignment;
|
||||
if (extra == 0) {
|
||||
return offset;
|
||||
}
|
||||
size_t padding = BytecodeOffsetAlignment - extra;
|
||||
return offset + padding;
|
||||
}
|
||||
|
||||
inline bool IsTranscodingBytecodeOffsetAligned(size_t offset) {
|
||||
return offset % BytecodeOffsetAlignment == 0;
|
||||
}
|
||||
|
||||
inline bool IsTranscodingBytecodeAligned(void* offset) {
|
||||
return IsTranscodingBytecodeOffsetAligned(size_t(offset));
|
||||
}
|
||||
|
||||
// Encode JSScript into the buffer.
|
||||
//
|
||||
// If the `buffer` isn't empty, the start of the `buffer` should meet
|
||||
// IsTranscodingBytecodeAligned, and the length should meet
|
||||
// IsTranscodingBytecodeOffsetAligned.
|
||||
//
|
||||
// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means
|
||||
// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer,
|
||||
// IsTranscodingBytecodeAligned should be guaranteed to meet by
|
||||
// malloc, used by MallocAllocPolicy in mozilla::Vector.
|
||||
extern JS_PUBLIC_API TranscodeResult EncodeScript(JSContext* cx,
|
||||
TranscodeBuffer& buffer,
|
||||
Handle<JSScript*> script);
|
||||
@ -67,11 +106,20 @@ extern JS_PUBLIC_API TranscodeResult EncodeInterpretedFunction(
|
||||
JSContext* cx, TranscodeBuffer& buffer, Handle<JSObject*> funobj);
|
||||
|
||||
// Decode JSScript from the buffer.
|
||||
//
|
||||
// The start of `buffer` and `cursorIndex` should meet
|
||||
// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned.
|
||||
// (This should be handled while encoding).
|
||||
extern JS_PUBLIC_API TranscodeResult
|
||||
DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
|
||||
size_t cursorIndex = 0);
|
||||
|
||||
// Decode JSScript from the range.
|
||||
//
|
||||
// The start of `range` should meet IsTranscodingBytecodeAligned and
|
||||
// IsTranscodingBytecodeOffsetAligned.
|
||||
// (This should be handled while encoding).
|
||||
extern JS_PUBLIC_API TranscodeResult
|
||||
DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const TranscodeRange& range, MutableHandle<JSScript*> scriptp);
|
||||
@ -87,6 +135,10 @@ extern JS_PUBLIC_API TranscodeResult DecodeInterpretedFunction(
|
||||
// buffer and instantiate JSScript from it.
|
||||
//
|
||||
// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal.
|
||||
//
|
||||
// The start of `buffer` and `cursorIndex` should meet
|
||||
// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned.
|
||||
// (This should be handled while encoding).
|
||||
extern JS_PUBLIC_API TranscodeResult DecodeScriptMaybeStencil(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
|
||||
@ -104,6 +156,10 @@ extern JS_PUBLIC_API TranscodeResult DecodeScriptMaybeStencil(
|
||||
// See also JS::FinishIncrementalEncoding.
|
||||
//
|
||||
// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal.
|
||||
//
|
||||
// The start of `buffer` and `cursorIndex` should meet
|
||||
// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned.
|
||||
// (This should be handled while encoding).
|
||||
extern JS_PUBLIC_API TranscodeResult DecodeScriptAndStartIncrementalEncoding(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
|
||||
@ -125,6 +181,15 @@ extern JS_PUBLIC_API TranscodeResult DecodeScriptAndStartIncrementalEncoding(
|
||||
//
|
||||
// If js::UseOffThreadParseGlobal is false, |buffer| contains encoded
|
||||
// CompilationStencil.
|
||||
//
|
||||
// If the `buffer` isn't empty, the start of the `buffer` should meet
|
||||
// IsTranscodingBytecodeAligned, and the length should meet
|
||||
// IsTranscodingBytecodeOffsetAligned.
|
||||
//
|
||||
// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means
|
||||
// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer,
|
||||
// IsTranscodingBytecodeAligned should be guaranteed to meet by
|
||||
// malloc, used by MallocAllocPolicy in mozilla::Vector.
|
||||
extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx,
|
||||
Handle<JSScript*> script,
|
||||
TranscodeBuffer& buffer);
|
||||
|
@ -292,7 +292,7 @@ class BaseStackFrame {
|
||||
// simplifies the principals check into the boolean isSystem() state. This
|
||||
// is fine because we only expose JS::ubi::Stack to devtools and chrome
|
||||
// code, and not to the web platform.
|
||||
virtual MOZ_MUST_USE bool constructSavedFrameStack(
|
||||
[[nodiscard]] virtual bool constructSavedFrameStack(
|
||||
JSContext* cx, MutableHandleObject outSavedFrameStack) const = 0;
|
||||
|
||||
// Trace the concrete implementation of JS::ubi::StackFrame.
|
||||
@ -428,7 +428,7 @@ class StackFrame {
|
||||
StackFrame parent() const { return base()->parent(); }
|
||||
bool isSystem() const { return base()->isSystem(); }
|
||||
bool isSelfHosted(JSContext* cx) const { return base()->isSelfHosted(cx); }
|
||||
MOZ_MUST_USE bool constructSavedFrameStack(
|
||||
[[nodiscard]] bool constructSavedFrameStack(
|
||||
JSContext* cx, MutableHandleObject outSavedFrameStack) const {
|
||||
return base()->constructSavedFrameStack(cx, outSavedFrameStack);
|
||||
}
|
||||
@ -461,7 +461,7 @@ class ConcreteStackFrame<void> : public BaseStackFrame {
|
||||
|
||||
uint64_t identifier() const override { return 0; }
|
||||
void trace(JSTracer* trc) override {}
|
||||
MOZ_MUST_USE bool constructSavedFrameStack(
|
||||
[[nodiscard]] bool constructSavedFrameStack(
|
||||
JSContext* cx, MutableHandleObject out) const override {
|
||||
out.set(nullptr);
|
||||
return true;
|
||||
@ -483,7 +483,7 @@ class ConcreteStackFrame<void> : public BaseStackFrame {
|
||||
}
|
||||
};
|
||||
|
||||
MOZ_MUST_USE JS_PUBLIC_API bool ConstructSavedFrameStackSlow(
|
||||
[[nodiscard]] JS_PUBLIC_API bool ConstructSavedFrameStackSlow(
|
||||
JSContext* cx, JS::ubi::StackFrame& frame,
|
||||
MutableHandleObject outSavedFrameStack);
|
||||
|
||||
@ -996,15 +996,15 @@ class MOZ_STACK_CLASS JS_PUBLIC_API RootList {
|
||||
bool wantNames = false);
|
||||
|
||||
// Find all GC roots.
|
||||
MOZ_MUST_USE bool init();
|
||||
[[nodiscard]] bool init();
|
||||
// Find only GC roots in the provided set of |JS::Compartment|s. Note: it's
|
||||
// important to take a CompartmentSet and not a RealmSet: objects in
|
||||
// same-compartment realms can reference each other directly, without going
|
||||
// through CCWs, so if we used a RealmSet here we would miss edges.
|
||||
MOZ_MUST_USE bool init(CompartmentSet& debuggees);
|
||||
[[nodiscard]] bool init(CompartmentSet& debuggees);
|
||||
// Find only GC roots in the given Debugger object's set of debuggee
|
||||
// compartments.
|
||||
MOZ_MUST_USE bool init(HandleObject debuggees);
|
||||
[[nodiscard]] bool init(HandleObject debuggees);
|
||||
|
||||
// Returns true if the RootList has been initialized successfully, false
|
||||
// otherwise.
|
||||
@ -1013,7 +1013,7 @@ class MOZ_STACK_CLASS JS_PUBLIC_API RootList {
|
||||
// Explicitly add the given Node as a root in this RootList. If wantNames is
|
||||
// true, you must pass an edgeName. The RootList does not take ownership of
|
||||
// edgeName.
|
||||
MOZ_MUST_USE bool addRoot(Node node, const char16_t* edgeName = nullptr);
|
||||
[[nodiscard]] bool addRoot(Node node, const char16_t* edgeName = nullptr);
|
||||
};
|
||||
|
||||
/*** Concrete classes for ubi::Node referent types ****************************/
|
||||
|
@ -107,14 +107,14 @@ struct CountType {
|
||||
|
||||
// Implement the 'count' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual MOZ_MUST_USE bool count(CountBase& count,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
const Node& node) = 0;
|
||||
[[nodiscard]] virtual bool count(CountBase& count,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
const Node& node) = 0;
|
||||
|
||||
// Implement the 'report' method for counts returned by this CountType
|
||||
// instance's 'newCount' method.
|
||||
virtual MOZ_MUST_USE bool report(JSContext* cx, CountBase& count,
|
||||
MutableHandleValue report) = 0;
|
||||
[[nodiscard]] virtual bool report(JSContext* cx, CountBase& count,
|
||||
MutableHandleValue report) = 0;
|
||||
};
|
||||
|
||||
using CountTypePtr = js::UniquePtr<CountType>;
|
||||
@ -135,8 +135,8 @@ class CountBase {
|
||||
: type(type), total_(0), smallestNodeIdCounted_(SIZE_MAX) {}
|
||||
|
||||
// Categorize and count |node| as appropriate for this count's type.
|
||||
MOZ_MUST_USE bool count(mozilla::MallocSizeOf mallocSizeOf,
|
||||
const Node& node) {
|
||||
[[nodiscard]] bool count(mozilla::MallocSizeOf mallocSizeOf,
|
||||
const Node& node) {
|
||||
total_++;
|
||||
|
||||
auto id = node.identifier();
|
||||
@ -160,7 +160,7 @@ class CountBase {
|
||||
// Construct a JavaScript object reporting the counts recorded in this
|
||||
// count, and store it in |report|. Return true on success, or false on
|
||||
// failure.
|
||||
MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
|
||||
[[nodiscard]] bool report(JSContext* cx, MutableHandleValue report) {
|
||||
return type.report(cx, *this, report);
|
||||
}
|
||||
|
||||
@ -203,14 +203,14 @@ class CensusHandler {
|
||||
mozilla::MallocSizeOf mallocSizeOf)
|
||||
: census(census), rootCount(rootCount), mallocSizeOf(mallocSizeOf) {}
|
||||
|
||||
MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
|
||||
[[nodiscard]] bool report(JSContext* cx, MutableHandleValue report) {
|
||||
return rootCount->report(cx, report);
|
||||
}
|
||||
|
||||
// This class needs to retain no per-node data.
|
||||
class NodeData {};
|
||||
|
||||
MOZ_MUST_USE JS_PUBLIC_API bool operator()(
|
||||
[[nodiscard]] JS_PUBLIC_API bool operator()(
|
||||
BreadthFirst<CensusHandler>& traversal, Node origin, const Edge& edge,
|
||||
NodeData* referentData, bool first);
|
||||
};
|
||||
@ -219,10 +219,10 @@ using CensusTraversal = BreadthFirst<CensusHandler>;
|
||||
|
||||
// Examine the census options supplied by the API consumer, and (among other
|
||||
// things) use that to build a CountType tree.
|
||||
MOZ_MUST_USE JS_PUBLIC_API bool ParseCensusOptions(JSContext* cx,
|
||||
Census& census,
|
||||
HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
[[nodiscard]] JS_PUBLIC_API bool ParseCensusOptions(JSContext* cx,
|
||||
Census& census,
|
||||
HandleObject options,
|
||||
CountTypePtr& outResult);
|
||||
|
||||
// Parse the breakdown language (as described in
|
||||
// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
|
||||
|
@ -320,10 +320,10 @@ class JS_PUBLIC_API DominatorTree {
|
||||
|
||||
// Do the post order traversal of the heap graph and populate our
|
||||
// predecessor sets.
|
||||
static MOZ_MUST_USE bool doTraversal(JSContext* cx, AutoCheckCannotGC& noGC,
|
||||
const Node& root,
|
||||
JS::ubi::Vector<Node>& postOrder,
|
||||
PredecessorSets& predecessorSets) {
|
||||
[[nodiscard]] static bool doTraversal(JSContext* cx, AutoCheckCannotGC& noGC,
|
||||
const Node& root,
|
||||
JS::ubi::Vector<Node>& postOrder,
|
||||
PredecessorSets& predecessorSets) {
|
||||
uint32_t nodeCount = 0;
|
||||
auto onNode = [&](const Node& node) {
|
||||
nodeCount++;
|
||||
@ -352,7 +352,7 @@ class JS_PUBLIC_API DominatorTree {
|
||||
|
||||
// Populates the given `map` with an entry for each node to its index in
|
||||
// `postOrder`.
|
||||
static MOZ_MUST_USE bool mapNodesToTheirIndices(
|
||||
[[nodiscard]] static bool mapNodesToTheirIndices(
|
||||
JS::ubi::Vector<Node>& postOrder, NodeToIndexMap& map) {
|
||||
MOZ_ASSERT(map.empty());
|
||||
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
|
||||
@ -368,7 +368,7 @@ class JS_PUBLIC_API DominatorTree {
|
||||
|
||||
// Convert the Node -> NodeSet predecessorSets to a index -> Vector<index>
|
||||
// form.
|
||||
static MOZ_MUST_USE bool convertPredecessorSetsToVectors(
|
||||
[[nodiscard]] static bool convertPredecessorSetsToVectors(
|
||||
const Node& root, JS::ubi::Vector<Node>& postOrder,
|
||||
PredecessorSets& predecessorSets, NodeToIndexMap& nodeToPostOrderIndex,
|
||||
JS::ubi::Vector<JS::ubi::Vector<uint32_t>>& predecessorVectors) {
|
||||
@ -408,8 +408,8 @@ class JS_PUBLIC_API DominatorTree {
|
||||
|
||||
// Initialize `doms` such that the immediate dominator of the `root` is the
|
||||
// `root` itself and all others are `UNDEFINED`.
|
||||
static MOZ_MUST_USE bool initializeDominators(JS::ubi::Vector<uint32_t>& doms,
|
||||
uint32_t length) {
|
||||
[[nodiscard]] static bool initializeDominators(
|
||||
JS::ubi::Vector<uint32_t>& doms, uint32_t length) {
|
||||
MOZ_ASSERT(doms.length() == 0);
|
||||
if (!doms.growByUninitialized(length)) {
|
||||
return false;
|
||||
@ -428,7 +428,7 @@ class JS_PUBLIC_API DominatorTree {
|
||||
postOrder.length() == retainedSizes->length());
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
|
||||
[[nodiscard]] bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
|
||||
MOZ_ASSERT(retainedSizes.isNothing());
|
||||
auto length = postOrder.length();
|
||||
|
||||
@ -662,9 +662,9 @@ class JS_PUBLIC_API DominatorTree {
|
||||
* `outSize`, or 0 if `node` is not a member of the dominator tree. Returns
|
||||
* false on OOM failure, leaving `outSize` unchanged.
|
||||
*/
|
||||
MOZ_MUST_USE bool getRetainedSize(const Node& node,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
Node::Size& outSize) {
|
||||
[[nodiscard]] bool getRetainedSize(const Node& node,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
Node::Size& outSize) {
|
||||
assertSanity();
|
||||
auto ptr = nodeToPostOrderIndex.lookup(node);
|
||||
if (!ptr) {
|
||||
|
@ -85,8 +85,8 @@ struct PostOrder {
|
||||
#endif
|
||||
|
||||
private:
|
||||
MOZ_MUST_USE bool fillEdgesFromRange(EdgeVector& edges,
|
||||
js::UniquePtr<EdgeRange>& range) {
|
||||
[[nodiscard]] bool fillEdgesFromRange(EdgeVector& edges,
|
||||
js::UniquePtr<EdgeRange>& range) {
|
||||
MOZ_ASSERT(range);
|
||||
for (; !range->empty(); range->popFront()) {
|
||||
if (!edges.append(std::move(range->front()))) {
|
||||
@ -96,7 +96,7 @@ struct PostOrder {
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool pushForTraversing(const Node& node) {
|
||||
[[nodiscard]] bool pushForTraversing(const Node& node) {
|
||||
EdgeVector edges;
|
||||
auto range = node.edges(cx, /* wantNames */ false);
|
||||
return range && fillEdgesFromRange(edges, range) &&
|
||||
@ -122,7 +122,7 @@ struct PostOrder {
|
||||
|
||||
// Add `node` as a starting point for the traversal. You may add
|
||||
// as many starting points as you like. Returns false on OOM.
|
||||
MOZ_MUST_USE bool addStart(const Node& node) {
|
||||
[[nodiscard]] bool addStart(const Node& node) {
|
||||
if (!seen.put(node)) {
|
||||
return false;
|
||||
}
|
||||
@ -139,7 +139,7 @@ struct PostOrder {
|
||||
// Return false on OOM or error return from `onNode::operator()` or
|
||||
// `onEdge::operator()`.
|
||||
template <typename NodeVisitor, typename EdgeVisitor>
|
||||
MOZ_MUST_USE bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
|
||||
[[nodiscard]] bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!traversed, "Can only traverse() once!");
|
||||
traversed = true;
|
||||
|
@ -31,7 +31,7 @@ struct JS_PUBLIC_API BackEdge {
|
||||
|
||||
BackEdge() : predecessor_(), name_(nullptr) {}
|
||||
|
||||
MOZ_MUST_USE bool init(const Node& predecessor, Edge& edge) {
|
||||
[[nodiscard]] bool init(const Node& predecessor, Edge& edge) {
|
||||
MOZ_ASSERT(!predecessor_);
|
||||
MOZ_ASSERT(!name_);
|
||||
|
||||
@ -279,7 +279,7 @@ struct JS_PUBLIC_API ShortestPaths {
|
||||
* the given target, in which case `func` will not be invoked.
|
||||
*/
|
||||
template <class Func>
|
||||
MOZ_MUST_USE bool forEachPath(const Node& target, Func func) {
|
||||
[[nodiscard]] bool forEachPath(const Node& target, Func func) {
|
||||
MOZ_ASSERT(targets_.has(target));
|
||||
|
||||
auto ptr = paths_.lookup(target);
|
||||
|
@ -544,7 +544,8 @@ namespace js {
|
||||
* instances of type |T|. Return false if the calculation overflowed.
|
||||
*/
|
||||
template <typename T>
|
||||
MOZ_MUST_USE inline bool CalculateAllocSize(size_t numElems, size_t* bytesOut) {
|
||||
[[nodiscard]] inline bool CalculateAllocSize(size_t numElems,
|
||||
size_t* bytesOut) {
|
||||
*bytesOut = numElems * sizeof(T);
|
||||
return (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) == 0;
|
||||
}
|
||||
@ -555,8 +556,8 @@ MOZ_MUST_USE inline bool CalculateAllocSize(size_t numElems, size_t* bytesOut) {
|
||||
* false if the calculation overflowed.
|
||||
*/
|
||||
template <typename T, typename Extra>
|
||||
MOZ_MUST_USE inline bool CalculateAllocSizeWithExtra(size_t numExtra,
|
||||
size_t* bytesOut) {
|
||||
[[nodiscard]] inline bool CalculateAllocSizeWithExtra(size_t numExtra,
|
||||
size_t* bytesOut) {
|
||||
*bytesOut = sizeof(T) + numExtra * sizeof(Extra);
|
||||
return (numExtra & mozilla::tl::MulOverflowMask<sizeof(Extra)>::value) == 0 &&
|
||||
*bytesOut >= sizeof(T);
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
@ -20,9 +18,9 @@
|
||||
#include "js-config.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
namespace JS {
|
||||
class JS_PUBLIC_API Value;
|
||||
@ -245,9 +243,6 @@ enum JSWhyMagic {
|
||||
/** standard constructors are not created for off-thread parsing. */
|
||||
JS_OFF_THREAD_CONSTRUCTOR,
|
||||
|
||||
/** used in jit::TrySkipAwait */
|
||||
JS_CANNOT_SKIP_AWAIT,
|
||||
|
||||
/** for local use */
|
||||
JS_GENERIC_MAGIC,
|
||||
|
||||
@ -519,13 +514,14 @@ class alignas(8) Value {
|
||||
MOZ_ASSERT(magicUint32() == payload);
|
||||
}
|
||||
|
||||
void setNumber(uint32_t ui) {
|
||||
if (ui > JSVAL_INT_MAX) {
|
||||
setDouble((double)ui);
|
||||
void setNumber(float f) {
|
||||
int32_t i;
|
||||
if (mozilla::NumberIsInt32(f, &i)) {
|
||||
setInt32(i);
|
||||
return;
|
||||
}
|
||||
|
||||
setInt32((int32_t)ui);
|
||||
setDouble(double(f));
|
||||
}
|
||||
|
||||
void setNumber(double d) {
|
||||
@ -538,6 +534,34 @@ class alignas(8) Value {
|
||||
setDouble(d);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setNumber(const T t) {
|
||||
static_assert(std::is_integral<T>::value, "must be integral type");
|
||||
MOZ_ASSERT(isNumberRepresentable(t), "value creation would be lossy");
|
||||
|
||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
||||
if constexpr (sizeof(t) <= sizeof(int32_t)) {
|
||||
setInt32(int32_t(t));
|
||||
} else {
|
||||
if (JSVAL_INT_MIN <= t && t <= JSVAL_INT_MAX) {
|
||||
setInt32(int32_t(t));
|
||||
} else {
|
||||
setDouble(double(t));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if constexpr (sizeof(t) <= sizeof(uint16_t)) {
|
||||
setInt32(int32_t(t));
|
||||
} else {
|
||||
if (t <= JSVAL_INT_MAX) {
|
||||
setInt32(int32_t(t));
|
||||
} else {
|
||||
setDouble(double(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setObjectOrNull(JSObject* arg) {
|
||||
if (arg) {
|
||||
setObject(*arg);
|
||||
@ -905,7 +929,7 @@ static MOZ_ALWAYS_INLINE void ExposeValueToActiveJS(const Value& v) {
|
||||
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarrieredSlow(&tmp));
|
||||
#endif
|
||||
if (v.isGCThing()) {
|
||||
js::gc::ExposeGCThingToActiveJS(GCCellPtr(v));
|
||||
js::gc::ExposeGCThingToActiveJS(v.toGCCellPtr());
|
||||
}
|
||||
}
|
||||
|
||||
@ -999,71 +1023,16 @@ static inline Value MagicValueUint32(uint32_t payload) {
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Value NumberValue(float f) {
|
||||
Value v;
|
||||
v.setNumber(f);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Value NumberValue(double dbl) {
|
||||
Value v;
|
||||
v.setNumber(dbl);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Value NumberValue(int8_t i) { return Int32Value(i); }
|
||||
|
||||
static inline Value NumberValue(uint8_t i) { return Int32Value(i); }
|
||||
|
||||
static inline Value NumberValue(int16_t i) { return Int32Value(i); }
|
||||
|
||||
static inline Value NumberValue(uint16_t i) { return Int32Value(i); }
|
||||
|
||||
static inline Value NumberValue(int32_t i) { return Int32Value(i); }
|
||||
|
||||
static constexpr Value NumberValue(uint32_t i) {
|
||||
return i <= JSVAL_INT_MAX ? Int32Value(int32_t(i))
|
||||
: Value::fromDouble(double(i));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <bool Signed>
|
||||
class MakeNumberValue {
|
||||
public:
|
||||
template <typename T>
|
||||
static inline Value create(const T t) {
|
||||
Value v;
|
||||
if (JSVAL_INT_MIN <= t && t <= JSVAL_INT_MAX) {
|
||||
v.setInt32(int32_t(t));
|
||||
} else {
|
||||
v.setDouble(double(t));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class MakeNumberValue<false> {
|
||||
public:
|
||||
template <typename T>
|
||||
static inline Value create(const T t) {
|
||||
Value v;
|
||||
if (t <= JSVAL_INT_MAX) {
|
||||
v.setInt32(int32_t(t));
|
||||
} else {
|
||||
v.setDouble(double(t));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
static inline Value NumberValue(const T t) {
|
||||
MOZ_ASSERT(Value::isNumberRepresentable(t), "value creation would be lossy");
|
||||
return detail::MakeNumberValue<std::numeric_limits<T>::is_signed>::create(t);
|
||||
Value v;
|
||||
v.setNumber(t);
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Value ObjectOrNullValue(JSObject* obj) {
|
||||
@ -1192,6 +1161,7 @@ class WrappedPtrOperations<JS::Value, Wrapper> {
|
||||
JS::BigInt* toBigInt() const { return value().toBigInt(); }
|
||||
JSObject& toObject() const { return value().toObject(); }
|
||||
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
|
||||
JS::GCCellPtr toGCCellPtr() const { return value().toGCCellPtr(); }
|
||||
gc::Cell* toGCThing() const { return value().toGCThing(); }
|
||||
JS::TraceKind traceKind() const { return value().traceKind(); }
|
||||
void* toPrivate() const { return value().toPrivate(); }
|
||||
@ -1253,29 +1223,7 @@ class MutableWrappedPtrOperations<JS::Value, Wrapper>
|
||||
*/
|
||||
template <typename Wrapper>
|
||||
class HeapBase<JS::Value, Wrapper>
|
||||
: public MutableWrappedPtrOperations<JS::Value, Wrapper> {
|
||||
public:
|
||||
void setMagic(JSWhyMagic why) { this->set(JS::MagicValueUint32(why)); }
|
||||
|
||||
void setNumber(uint32_t ui) {
|
||||
if (ui > JSVAL_INT_MAX) {
|
||||
this->setDouble((double)ui);
|
||||
return;
|
||||
}
|
||||
|
||||
this->setInt32((int32_t)ui);
|
||||
}
|
||||
|
||||
void setNumber(double d) {
|
||||
int32_t i;
|
||||
if (mozilla::NumberIsInt32(d, &i)) {
|
||||
this->setInt32(i);
|
||||
return;
|
||||
}
|
||||
|
||||
this->setDouble(d);
|
||||
}
|
||||
};
|
||||
: public MutableWrappedPtrOperations<JS::Value, Wrapper> {};
|
||||
|
||||
MOZ_HAVE_NORETURN MOZ_COLD MOZ_NEVER_INLINE void ReportBadValueTypeAndCrash(
|
||||
const JS::Value& val);
|
||||
|
@ -157,10 +157,6 @@ class JS_FRIEND_API Wrapper : public ForwardingProxyHandler {
|
||||
static JSObject* New(JSContext* cx, JSObject* obj, const Wrapper* handler,
|
||||
const WrapperOptions& options = WrapperOptions());
|
||||
|
||||
static JSObject* NewSingleton(
|
||||
JSContext* cx, JSObject* obj, const Wrapper* handler,
|
||||
const WrapperOptions& options = WrapperOptions());
|
||||
|
||||
static JSObject* Renew(JSObject* existing, JSObject* obj,
|
||||
const Wrapper* handler);
|
||||
|
||||
|
@ -46,17 +46,6 @@ extern JS_FRIEND_API bool AddMozDateTimeFormatConstructor(
|
||||
extern JS_FRIEND_API bool AddMozDisplayNamesConstructor(JSContext* cx,
|
||||
Handle<JSObject*> intl);
|
||||
|
||||
/**
|
||||
* Create and add the Intl.DisplayNames constructor function to the provided
|
||||
* object, implementing standardized behavior (that isn't yet shippable because
|
||||
* we're not *quite* comfortable with the spec's progress yet).
|
||||
*
|
||||
* If JS was built without JS_HAS_INTL_API, this function will throw an
|
||||
* exception.
|
||||
*/
|
||||
extern JS_FRIEND_API bool AddDisplayNamesConstructor(JSContext* cx,
|
||||
Handle<JSObject*> intl);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_experimental_Intl_h
|
||||
|
79
js/public/experimental/JSStencil.h
Normal file
79
js/public/experimental/JSStencil.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef js_experimental_JSStencil_h
|
||||
#define js_experimental_JSStencil_h
|
||||
|
||||
/* The `JS::Stencil` type holds the output of the JS Parser before it is
|
||||
* allocated on the GC heap as a `JSScript`. This form may be serialized as
|
||||
* part of building a bytecode cache. This `Stencil` is not associated with any
|
||||
* particular Realm and may be generated off-main-thread, making it useful for
|
||||
* building script loaders.
|
||||
*/
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h" // mozilla::UniquePtr
|
||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "jstypes.h" // JS_FRIEND_API
|
||||
|
||||
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions
|
||||
#include "js/SourceText.h" // JS::SourceText
|
||||
#include "js/Transcoding.h"
|
||||
|
||||
struct JS_PUBLIC_API JSContext;
|
||||
|
||||
// Underlying opaque type.
|
||||
namespace js::frontend {
|
||||
struct CompilationStencil;
|
||||
};
|
||||
|
||||
namespace JS {
|
||||
|
||||
using Stencil = js::frontend::CompilationStencil;
|
||||
|
||||
// These non-member functions let us manipulate the ref counts of the opaque
|
||||
// Stencil type. The RefPtrTraits below calls these for use when using the
|
||||
// RefPtr type.
|
||||
JS_PUBLIC_API void StencilAddRef(Stencil* stencil);
|
||||
JS_PUBLIC_API void StencilRelease(Stencil* stencil);
|
||||
|
||||
// Compile the source text into a JS::Stencil using the provided options. The
|
||||
// resulting stencil may be instantiated into any Realm on the current runtime
|
||||
// and may be used multiple times.
|
||||
//
|
||||
// NOTE: On error, a null will be returned and an exception will be set on the
|
||||
// JSContext.
|
||||
extern JS_PUBLIC_API already_AddRefed<Stencil> CompileGlobalScriptToStencil(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceText<mozilla::Utf8Unit>& srcBuf);
|
||||
|
||||
// Instantiate the Stencil into current Realm and return the JSScript.
|
||||
extern JS_PUBLIC_API JSScript* InstantiateGlobalStencil(
|
||||
JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
RefPtr<Stencil> stencil);
|
||||
|
||||
// Serialize the Stencil into the transcode buffer.
|
||||
extern JS_PUBLIC_API TranscodeResult
|
||||
EncodeStencil(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
|
||||
RefPtr<Stencil> stencil, TranscodeBuffer& buffer);
|
||||
|
||||
// Deserialize data and create a new Stencil.
|
||||
extern JS_PUBLIC_API TranscodeResult
|
||||
DecodeStencil(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const TranscodeRange& range, RefPtr<Stencil>& stencilOut);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
namespace mozilla {
|
||||
template <>
|
||||
struct RefPtrTraits<JS::Stencil> {
|
||||
static void AddRef(JS::Stencil* stencil) { JS::StencilAddRef(stencil); }
|
||||
static void Release(JS::Stencil* stencil) { JS::StencilRelease(stencil); }
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // js_experimental_JSStencil_h
|
@ -38,24 +38,23 @@ class JS_PUBLIC_API AutoRequireNoGC;
|
||||
* zeros.
|
||||
*/
|
||||
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt8Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt8Array(JSContext* cx, size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint8Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArray(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt16Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint16Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt32Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint32Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewFloat32Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
extern JS_FRIEND_API JSObject* JS_NewFloat64Array(JSContext* cx,
|
||||
uint32_t nelements);
|
||||
size_t nelements);
|
||||
|
||||
/*
|
||||
* Create a new typed array and copy in values from the given object. The
|
||||
@ -92,38 +91,38 @@ extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayFromArray(
|
||||
*/
|
||||
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt8ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint8ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt16ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint16ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewInt32ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewUint32ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewBigInt64ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewBigUint64ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewFloat32ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayWithBuffer(
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, uint32_t byteOffset,
|
||||
int32_t length);
|
||||
JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
|
||||
int64_t length);
|
||||
|
||||
/**
|
||||
* Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
|
||||
@ -207,15 +206,15 @@ const size_t TypedArrayLengthSlot = 1;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
|
||||
inline void Get##Type##ArrayLengthAndData( \
|
||||
JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) { \
|
||||
MOZ_ASSERT(JS::GetClass(obj) == detail::Type##ArrayClassPtr); \
|
||||
const JS::Value& lenSlot = \
|
||||
JS::GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
|
||||
*length = mozilla::AssertedCast<uint32_t>(size_t(lenSlot.toPrivate())); \
|
||||
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
|
||||
*data = static_cast<type*>(JS::GetPrivate(obj)); \
|
||||
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
|
||||
inline void Get##Type##ArrayLengthAndData( \
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, type** data) { \
|
||||
MOZ_ASSERT(JS::GetClass(obj) == detail::Type##ArrayClassPtr); \
|
||||
const JS::Value& lenSlot = \
|
||||
JS::GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
|
||||
*length = size_t(lenSlot.toPrivate()); \
|
||||
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
|
||||
*data = static_cast<type*>(JS::GetPrivate(obj)); \
|
||||
}
|
||||
|
||||
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
|
||||
@ -233,7 +232,7 @@ JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
|
||||
// This one isn't inlined because it's rather tricky (by dint of having to deal
|
||||
// with a dozen-plus classes and varying slot layouts.
|
||||
extern JS_FRIEND_API void GetArrayBufferViewLengthAndData(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
uint8_t** data);
|
||||
|
||||
@ -245,41 +244,41 @@ extern JS_FRIEND_API void GetArrayBufferViewLengthAndData(JSObject* obj,
|
||||
* object on success, filling both outparameters.
|
||||
*/
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt8Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
int8_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
uint8_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8ClampedArray(
|
||||
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt16Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
int16_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint16Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
uint16_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsInt32Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
int32_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsUint32Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
uint32_t** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat32Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
float** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat64Array(JSObject* obj,
|
||||
uint32_t* length,
|
||||
size_t* length,
|
||||
bool* isSharedMemory,
|
||||
double** data);
|
||||
extern JS_FRIEND_API JSObject* JS_GetObjectAsArrayBufferView(
|
||||
JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
|
||||
|
||||
/*
|
||||
* Get the type of elements in a typed array, or MaxTypedArrayViewType if a
|
||||
@ -298,7 +297,7 @@ extern JS_FRIEND_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj);
|
||||
* be known that it would pass such a test: it is a typed array or a wrapper of
|
||||
* a typed array, and the unwrapping will succeed.
|
||||
*/
|
||||
extern JS_FRIEND_API uint32_t JS_GetTypedArrayLength(JSObject* obj);
|
||||
extern JS_FRIEND_API size_t JS_GetTypedArrayLength(JSObject* obj);
|
||||
|
||||
/**
|
||||
* Return the byte offset from the start of an ArrayBuffer to the start of a
|
||||
@ -308,7 +307,7 @@ extern JS_FRIEND_API uint32_t JS_GetTypedArrayLength(JSObject* obj);
|
||||
* be known that it would pass such a test: it is a typed array or a wrapper of
|
||||
* a typed array, and the unwrapping will succeed.
|
||||
*/
|
||||
extern JS_FRIEND_API uint32_t JS_GetTypedArrayByteOffset(JSObject* obj);
|
||||
extern JS_FRIEND_API size_t JS_GetTypedArrayByteOffset(JSObject* obj);
|
||||
|
||||
/**
|
||||
* Return the byte length of a typed array.
|
||||
@ -317,17 +316,17 @@ extern JS_FRIEND_API uint32_t JS_GetTypedArrayByteOffset(JSObject* obj);
|
||||
* be known that it would pass such a test: it is a typed array or a wrapper of
|
||||
* a typed array, and the unwrapping will succeed.
|
||||
*/
|
||||
extern JS_FRIEND_API uint32_t JS_GetTypedArrayByteLength(JSObject* obj);
|
||||
extern JS_FRIEND_API size_t JS_GetTypedArrayByteLength(JSObject* obj);
|
||||
|
||||
/**
|
||||
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
|
||||
*/
|
||||
extern JS_FRIEND_API uint32_t JS_GetArrayBufferViewByteLength(JSObject* obj);
|
||||
extern JS_FRIEND_API size_t JS_GetArrayBufferViewByteLength(JSObject* obj);
|
||||
|
||||
/**
|
||||
* More generic name for JS_GetTypedArrayByteOffset to cover DataViews as well
|
||||
*/
|
||||
extern JS_FRIEND_API uint32_t JS_GetArrayBufferViewByteOffset(JSObject* obj);
|
||||
extern JS_FRIEND_API size_t JS_GetArrayBufferViewByteOffset(JSObject* obj);
|
||||
|
||||
/*
|
||||
* Return a pointer to the start of the data referenced by a typed array. The
|
||||
@ -376,6 +375,28 @@ extern JS_FRIEND_API double* JS_GetFloat64ArrayData(JSObject* obj,
|
||||
extern JS_FRIEND_API void* JS_GetArrayBufferViewData(
|
||||
JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
|
||||
|
||||
/**
|
||||
* Return a "fixed" pointer (one that will not move during a GC) to the
|
||||
* ArrayBufferView's data. Note that this will not keep the object alive; the
|
||||
* holding object should be rooted or traced. If the view is storing the data
|
||||
* inline, this will copy the data to the provided buffer, returning nullptr if
|
||||
* bufSize is inadequate.
|
||||
*
|
||||
* Avoid using this unless necessary. JS_GetArrayBufferViewData is simpler and
|
||||
* more efficient because it requires the caller to ensure that a GC will not
|
||||
* occur and thus does not need to handle movable data.
|
||||
*/
|
||||
extern JS_FRIEND_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
|
||||
uint8_t* buffer,
|
||||
size_t bufSize);
|
||||
|
||||
/**
|
||||
* If the bufSize passed to JS_GetArrayBufferViewFixedData is at least this
|
||||
* many bytes, then any copied data is guaranteed to fit into the provided
|
||||
* buffer.
|
||||
*/
|
||||
extern JS_FRIEND_API size_t JS_MaxMovableTypedArraySize();
|
||||
|
||||
/**
|
||||
* Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
|
||||
* This may return a detached buffer. |obj| must be an object that would
|
||||
@ -393,6 +414,18 @@ extern JS_FRIEND_API JSObject* JS_GetArrayBufferViewBuffer(
|
||||
*/
|
||||
JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx,
|
||||
JS::Handle<JSObject*> buffer,
|
||||
uint32_t byteOffset, int32_t byteLength);
|
||||
size_t byteOffset, size_t byteLength);
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* Returns whether the passed array buffer view is 'large': its byteLength >= 2
|
||||
* GB. See also SetLargeArrayBuffersEnabled.
|
||||
*
|
||||
* |obj| must pass a JS_IsArrayBufferViewObject test.
|
||||
*/
|
||||
JS_FRIEND_API bool IsLargeArrayBufferView(JSObject* obj);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_experimental_TypedData_h
|
||||
|
@ -80,7 +80,8 @@ MSG_DEF(JSMSG_SOURCE_ARRAY_TOO_LONG, 0, JSEXN_RANGEERR, "source array is too l
|
||||
MSG_DEF(JSMSG_REDECLARED_PREV, 2, JSEXN_NOTE, "Previously declared at line {0}, column {1}")
|
||||
MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_SYNTAXERR, "redeclaration of {0} {1}")
|
||||
MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
|
||||
MSG_DEF(JSMSG_UNDECLARED_PRIVATE, 0, JSEXN_TYPEERR, "Trying to read undeclared field")
|
||||
MSG_DEF(JSMSG_GET_MISSING_PRIVATE, 0, JSEXN_TYPEERR, "can't access private field or method: object is not the right class")
|
||||
MSG_DEF(JSMSG_SET_MISSING_PRIVATE, 0, JSEXN_TYPEERR, "can't set private field: object is not the right class")
|
||||
MSG_DEF(JSMSG_GETTER_ONLY, 1, JSEXN_TYPEERR, "setting getter-only property {0}")
|
||||
MSG_DEF(JSMSG_PRIVATE_SETTER_ONLY, 0, JSEXN_TYPEERR, "getting private setter-only property")
|
||||
MSG_DEF(JSMSG_OVERWRITING_ACCESSOR, 1, JSEXN_TYPEERR, "can't overwrite accessor property {0}")
|
||||
@ -208,8 +209,11 @@ MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 3, JSEXN_SYNTAXERR, "{0} functions must h
|
||||
MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initializer too large")
|
||||
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
|
||||
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
||||
MSG_DEF(JSMSG_AS_AFTER_STRING, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after string literal")
|
||||
MSG_DEF(JSMSG_AWAIT_IN_PARAMETER, 0, JSEXN_SYNTAXERR, "await expression can't be used in parameter")
|
||||
MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "await is only valid in async functions and async generators")
|
||||
MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE, 0, JSEXN_SYNTAXERR, "await is only valid in async functions, async generators and modules")
|
||||
MSG_DEF(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "top level await is not currently supported")
|
||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
||||
MSG_DEF(JSMSG_BAD_COALESCE_MIXING, 0, JSEXN_SYNTAXERR, "cannot use `??` unparenthesized within `||` and `&&` expressions")
|
||||
@ -223,9 +227,10 @@ MSG_DEF(JSMSG_BAD_DUP_ARGS, 0, JSEXN_SYNTAXERR, "duplicate argument n
|
||||
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loop")
|
||||
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for-in/of left-hand side")
|
||||
MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding")
|
||||
MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS, 0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'")
|
||||
MSG_DEF(JSMSG_BAD_STARTING_FOROF_LHS, 1, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with '{0}'")
|
||||
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
|
||||
MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side")
|
||||
MSG_DEF(JSMSG_BAD_LOCAL_STRING_EXPORT, 0, JSEXN_SYNTAXERR, "string exports can't be used without 'from'")
|
||||
MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition")
|
||||
MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'")
|
||||
MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id")
|
||||
@ -266,7 +271,9 @@ MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 0, JSEXN_SYNTAXERR, "missing } in compoun
|
||||
MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
|
||||
MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
|
||||
MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL_LITERAL,0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals are deprecated; use the \"0o\" prefix instead")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL_ESCAPE ,0, JSEXN_SYNTAXERR, "octal escape sequences can't be used in untagged template literals or in strict mode code")
|
||||
MSG_DEF(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE, 0, JSEXN_SYNTAXERR, "the escapes \\8 and \\9 can't be used in untagged template literals or in strict mode code")
|
||||
MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
|
||||
MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'")
|
||||
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
|
||||
@ -362,6 +369,7 @@ MSG_DEF(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, 1, JSEXN_SYNTAXERR, "unexpected token
|
||||
MSG_DEF(JSMSG_UNEXPECTED_PARAMLIST_END,0, JSEXN_SYNTAXERR, "unexpected end of function parameter list")
|
||||
MSG_DEF(JSMSG_UNNAMED_CLASS_STMT, 0, JSEXN_SYNTAXERR, "class statement requires a name")
|
||||
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 0, JSEXN_SYNTAXERR, "function statement requires a name")
|
||||
MSG_DEF(JSMSG_UNPAIRED_SURROGATE_EXPORT, 0, JSEXN_SYNTAXERR, "module export name contains unpaired surrogate")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 0, JSEXN_SYNTAXERR, "unterminated comment")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
|
||||
MSG_DEF(JSMSG_EOF_BEFORE_END_OF_LITERAL,1,JSEXN_SYNTAXERR, "{0} literal not terminated before end of script")
|
||||
@ -405,6 +413,7 @@ MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}")
|
||||
MSG_DEF(JSMSG_WASM_NO_SHMEM_COMPILE, 0, JSEXN_WASMCOMPILEERROR, "shared memory is disabled")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE, 2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch")
|
||||
MSG_DEF(JSMSG_WASM_BAD_EXN_SIG, 2, JSEXN_WASMLINKERROR, "imported exception '{0}.{1}' signature mismatch")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size")
|
||||
MSG_DEF(JSMSG_WASM_IMP_SHARED_REQD, 0, JSEXN_WASMLINKERROR, "imported unshared memory but shared required")
|
||||
@ -441,19 +450,18 @@ MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD, 1, JSEXN_TYPEERR, "import object fiel
|
||||
MSG_DEF(JSMSG_WASM_BAD_REF_NONNULLABLE_VALUE, 0, JSEXN_TYPEERR, "cannot pass null to non-nullable WebAssembly reference")
|
||||
MSG_DEF(JSMSG_WASM_BAD_FUNCREF_VALUE, 0, JSEXN_TYPEERR, "can only pass WebAssembly exported functions to funcref")
|
||||
MSG_DEF(JSMSG_WASM_BAD_EQREF_VALUE, 0, JSEXN_TYPEERR, "can only pass a TypedObject to an eqref")
|
||||
MSG_DEF(JSMSG_WASM_BAD_I64_TYPE, 0, JSEXN_TYPEERR, "cannot pass v128 to or from JS")
|
||||
MSG_DEF(JSMSG_WASM_BAD_VAL_TYPE, 0, JSEXN_TYPEERR, "cannot pass v128 to or from JS")
|
||||
MSG_DEF(JSMSG_WASM_BAD_GLOBAL_TYPE, 0, JSEXN_TYPEERR, "bad type for a WebAssembly.Global")
|
||||
MSG_DEF(JSMSG_WASM_NO_TRANSFER, 0, JSEXN_TYPEERR, "cannot transfer WebAssembly/asm.js ArrayBuffer")
|
||||
MSG_DEF(JSMSG_WASM_TEXT_FAIL, 1, JSEXN_SYNTAXERR, "wasm text error: {0}")
|
||||
MSG_DEF(JSMSG_WASM_MISSING_MAXIMUM, 0, JSEXN_TYPEERR, "'shared' is true but maximum is not specified")
|
||||
MSG_DEF(JSMSG_WASM_GLOBAL_IMMUTABLE, 0, JSEXN_TYPEERR, "can't set value of immutable global")
|
||||
MSG_DEF(JSMSG_WASM_TYPEREF_FROM_JS, 0, JSEXN_TYPEERR, "conversion from JavaScript value to WebAssembly typed ref unimplemented")
|
||||
MSG_DEF(JSMSG_WASM_TYPEREF_TO_JS, 0, JSEXN_TYPEERR, "conversion from WebAssembly typed ref to JavaScript value unimplemented")
|
||||
MSG_DEF(JSMSG_WASM_WRONG_NUMBER_OF_VALUES, 2, JSEXN_TYPEERR, "wrong number of values returned by JavaScript to WebAssembly (expected {0}, got {1})")
|
||||
MSG_DEF(JSMSG_WASM_NONSHARED_WAIT , 0, JSEXN_WASMRUNTIMEERROR, "atomic wait on non-shared memory")
|
||||
MSG_DEF(JSMSG_WASM_NULL_REQUIRED, 0, JSEXN_TYPEERR, "nullref requires a null value")
|
||||
MSG_DEF(JSMSG_WASM_SUPPLY_ONLY_ONE, 2, JSEXN_TYPEERR, "exactly one of {0} and {1} must be supplied")
|
||||
MSG_DEF(JSMSG_WASM_MISSING_REQUIRED, 1, JSEXN_TYPEERR, "Missing required argument {0}")
|
||||
MSG_DEF(JSMSG_WASM_EXN_CONSTRUCTOR, 1, JSEXN_WASMRUNTIMEERROR, "cannot call {0}")
|
||||
|
||||
// Proxy
|
||||
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
|
||||
@ -600,25 +608,21 @@ MSG_DEF(JSMSG_INVALID_CAPTURE_NAME, 0, JSEXN_SYNTAXERR, "invalid capture
|
||||
MSG_DEF(JSMSG_DUPLICATE_CAPTURE_NAME, 0, JSEXN_SYNTAXERR, "duplicate capture group name in regular expression")
|
||||
MSG_DEF(JSMSG_INVALID_NAMED_REF, 0, JSEXN_SYNTAXERR, "invalid named reference in regular expression")
|
||||
MSG_DEF(JSMSG_INVALID_NAMED_CAPTURE_REF, 0, JSEXN_SYNTAXERR, "invalid named capture reference in regular expression")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_REGEXP_GETTER, 2, JSEXN_TYPEERR, "RegExp.prototype.{0} getter called on non-RegExp object: {1}")
|
||||
|
||||
// Self-hosting
|
||||
MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR, 0, JSEXN_ERR, "internal error getting the default locale")
|
||||
MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP,1, JSEXN_ERR, "No such property on self-hosted object: {0}")
|
||||
|
||||
// Typed object
|
||||
MSG_DEF(JSMSG_INVALID_PROTOTYPE, 0, JSEXN_TYPEERR, "prototype field is not an object")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 0, JSEXN_TYPEERR, "handle unattached")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE, 0, JSEXN_ERR, "setting immutable field")
|
||||
MSG_DEF(JSMSG_TYPEDOBJECT_NOT_CONSTRUCTIBLE, 0, JSEXN_TYPEERR, "not constructible")
|
||||
|
||||
// Array
|
||||
MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
|
||||
|
||||
// Typed array
|
||||
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
|
||||
MSG_DEF(JSMSG_DEFINE_BAD_INDEX, 0, JSEXN_TYPEERR, "can't define element for invalid or out-of-range index")
|
||||
MSG_DEF(JSMSG_NON_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected ArrayBuffer, but species constructor returned non-ArrayBuffer")
|
||||
MSG_DEF(JSMSG_SAME_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different ArrayBuffer, but species constructor returned same ArrayBuffer")
|
||||
MSG_DEF(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected ArrayBuffer with at least {0} bytes, but species constructor returns ArrayBuffer with {1} bytes")
|
||||
@ -701,7 +705,7 @@ MSG_DEF(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.asyn
|
||||
MSG_DEF(JSMSG_READABLESTREAM_UNDERLYINGSOURCE_TYPE_WRONG,0, JSEXN_RANGEERR,"'underlyingSource.type' must be \"bytes\" or undefined.")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_BYTES_TYPE_NOT_IMPLEMENTED, 0, JSEXN_RANGEERR,"support for 'new ReadableStream({ type: \"bytes\" })' is not yet implemented")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_BYOB_READER_FOR_NON_BYTE_STREAM,0,JSEXN_TYPEERR,"can't get a BYOB reader for a non-byte stream")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_INVALID_READER_MODE, 0, JSEXN_RANGEERR,"'mode' must be \"byob\" or undefined.")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_INVALID_READER_MODE, 0, JSEXN_TYPEERR,"'mode' must be \"byob\" or undefined.")
|
||||
MSG_DEF(JSMSG_NUMBER_MUST_BE_FINITE_NON_NEGATIVE, 1, JSEXN_RANGEERR, "'{0}' must be a finite, non-negative number.")
|
||||
MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_INVALID_BYTESWRITTEN, 0, JSEXN_RANGEERR, "'bytesWritten' exceeds remaining length.")
|
||||
MSG_DEF(JSMSG_READABLEBYTESTREAMCONTROLLER_INVALID_VIEW_SIZE, 0, JSEXN_RANGEERR, "view size does not match requested data.")
|
||||
@ -738,16 +742,17 @@ MSG_DEF(JSMSG_WRITABLESTREAM_ALREADY_LOCKED, 0, JSEXN_TYPEERR, "writ
|
||||
MSG_DEF(JSMSG_READABLESTREAM_NYI, 0, JSEXN_ERR, "full WritableStream support is not yet implemented")
|
||||
|
||||
// Other Stream-related
|
||||
MSG_DEF(JSMSG_STREAM_MISSING_HIGHWATERMARK, 0, JSEXN_TYPEERR, "'highWaterMark' must not be undefined.")
|
||||
MSG_DEF(JSMSG_STREAM_INVALID_HIGHWATERMARK, 0, JSEXN_RANGEERR, "'highWaterMark' must be a non-negative, non-NaN number.")
|
||||
MSG_DEF(JSMSG_STREAM_CONSUME_ERROR, 0, JSEXN_TYPEERR, "error consuming stream body")
|
||||
|
||||
// Response-related
|
||||
MSG_DEF(JSMSG_ERROR_CONSUMING_RESPONSE, 0, JSEXN_TYPEERR, "there was an error consuming the Response")
|
||||
MSG_DEF(JSMSG_BAD_RESPONSE_VALUE, 0, JSEXN_TYPEERR, "expected Response or Promise resolving to Response")
|
||||
MSG_DEF(JSMSG_BAD_RESPONSE_MIME_TYPE, 0, JSEXN_TYPEERR, "Response has unsupported MIME type")
|
||||
MSG_DEF(JSMSG_BAD_RESPONSE_CORS_SAME_ORIGIN, 0, JSEXN_TYPEERR, "Response.type must be 'basic', 'cors' or 'default'")
|
||||
MSG_DEF(JSMSG_BAD_RESPONSE_STATUS, 0, JSEXN_TYPEERR, "Response does not have ok status")
|
||||
MSG_DEF(JSMSG_RESPONSE_ALREADY_CONSUMED, 0, JSEXN_TYPEERR, "Response already consumed")
|
||||
// (wasm) Response-related
|
||||
MSG_DEF(JSMSG_WASM_ERROR_CONSUMING_RESPONSE, 0, JSEXN_TYPEERR, "WebAssembly: There was an error consuming the Response")
|
||||
MSG_DEF(JSMSG_WASM_BAD_RESPONSE_VALUE, 0, JSEXN_TYPEERR, "WebAssembly: Expected Response or Promise resolving to Response")
|
||||
MSG_DEF(JSMSG_WASM_BAD_RESPONSE_MIME_TYPE, 2, JSEXN_TYPEERR, "WebAssembly: Response has unsupported MIME type '{0}' expected '{1}'")
|
||||
MSG_DEF(JSMSG_WASM_BAD_RESPONSE_CORS_SAME_ORIGIN, 0, JSEXN_TYPEERR, "WebAssembly: Response.type must be 'basic', 'cors' or 'default'")
|
||||
MSG_DEF(JSMSG_WASM_BAD_RESPONSE_STATUS, 0, JSEXN_TYPEERR, "WebAssembly: Response does not have ok status")
|
||||
MSG_DEF(JSMSG_WASM_RESPONSE_ALREADY_CONSUMED, 0, JSEXN_TYPEERR, "WebAssembly: Response already consumed")
|
||||
|
||||
// BigInt
|
||||
MSG_DEF(JSMSG_BIGINT_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert BigInt to number")
|
||||
|
@ -31,17 +31,17 @@ struct Zone {
|
||||
Compact
|
||||
};
|
||||
|
||||
enum Kind : uint8_t { NormalZone, AtomsZone, SelfHostingZone, SystemZone };
|
||||
|
||||
protected:
|
||||
JSRuntime* const runtime_;
|
||||
JSTracer* const barrierTracer_; // A pointer to the JSRuntime's |gcMarker|.
|
||||
uint32_t needsIncrementalBarrier_;
|
||||
GCState gcState_;
|
||||
uint32_t needsIncrementalBarrier_ = 0;
|
||||
GCState gcState_ = NoGC;
|
||||
const Kind kind_;
|
||||
|
||||
Zone(JSRuntime* runtime, JSTracer* barrierTracerArg)
|
||||
: runtime_(runtime),
|
||||
barrierTracer_(barrierTracerArg),
|
||||
needsIncrementalBarrier_(0),
|
||||
gcState_(NoGC) {}
|
||||
Zone(JSRuntime* runtime, JSTracer* barrierTracerArg, Kind kind)
|
||||
: runtime_(runtime), barrierTracer_(barrierTracerArg), kind_(kind) {}
|
||||
|
||||
public:
|
||||
bool needsIncrementalBarrier() const { return needsIncrementalBarrier_; }
|
||||
@ -72,10 +72,17 @@ struct Zone {
|
||||
bool isGCMarking() const {
|
||||
return isGCMarkingBlackOnly() || isGCMarkingBlackAndGray();
|
||||
}
|
||||
bool isGCMarkingOrSweeping() const {
|
||||
return gcState_ >= MarkBlackOnly && gcState_ <= Sweep;
|
||||
}
|
||||
bool isGCSweepingOrCompacting() const {
|
||||
return gcState_ == Sweep || gcState_ == Compact;
|
||||
}
|
||||
|
||||
bool isAtomsZone() const { return kind_ == AtomsZone; }
|
||||
bool isSelfHostingZone() const { return kind_ == SelfHostingZone; }
|
||||
bool isSystemZone() const { return kind_ == SystemZone; }
|
||||
|
||||
static shadow::Zone* from(JS::Zone* zone) {
|
||||
return reinterpret_cast<shadow::Zone*>(zone);
|
||||
}
|
||||
|
@ -215,6 +215,7 @@ const WHITELIST_TYPES: &'static [&'static str] = &[
|
||||
"JS::Compartment",
|
||||
"JS::Latin1Char",
|
||||
"JS::detail::RootedPtr",
|
||||
"JS::detail::RootListEntry",
|
||||
"JS::MutableHandle",
|
||||
"JS::MutableHandleObject",
|
||||
"JS::MutableHandleValue",
|
||||
@ -387,7 +388,6 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
||||
"JS_NewObject",
|
||||
"JS_NewObjectWithGivenProto",
|
||||
"JS_NewObjectWithoutMetadata",
|
||||
"JS_NewObjectWithUniqueType",
|
||||
"JS_NewPlainObject",
|
||||
"JS::NewPromiseObject",
|
||||
"JS_NewStringCopyN",
|
||||
|
@ -301,12 +301,6 @@ extern "C" {
|
||||
aHandler: *const ::libc::c_void,
|
||||
aClass: *const JSClass,
|
||||
) -> *mut JSObject;
|
||||
pub fn WrapperNewSingleton(
|
||||
aCx: *mut JSContext,
|
||||
aObj: JS::HandleObject,
|
||||
aHandler: *const ::libc::c_void,
|
||||
aClass: *const JSClass,
|
||||
) -> *mut JSObject;
|
||||
pub fn NewWindowProxy(
|
||||
aCx: *mut JSContext,
|
||||
aObj: JS::HandleObject,
|
||||
@ -394,55 +388,55 @@ extern "C" {
|
||||
|
||||
pub fn GetInt8ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut i8,
|
||||
);
|
||||
pub fn GetUint8ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut u8,
|
||||
);
|
||||
pub fn GetUint8ClampedArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut u8,
|
||||
);
|
||||
pub fn GetInt16ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut i16,
|
||||
);
|
||||
pub fn GetUint16ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut u16,
|
||||
);
|
||||
pub fn GetInt32ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut i32,
|
||||
);
|
||||
pub fn GetUint32ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut u32,
|
||||
);
|
||||
pub fn GetFloat32ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut f32,
|
||||
);
|
||||
pub fn GetFloat64ArrayLengthAndData(
|
||||
obj: *mut JSObject,
|
||||
length: *mut u32,
|
||||
length: *mut usize,
|
||||
isSharedMemory: *mut bool,
|
||||
data: *mut *mut f64,
|
||||
);
|
||||
|
@ -465,16 +465,6 @@ JSObject* WrapperNew(JSContext* aCx, JS::HandleObject aObj,
|
||||
return js::Wrapper::New(aCx, aObj, (const js::Wrapper*)aHandler, options);
|
||||
}
|
||||
|
||||
JSObject* WrapperNewSingleton(JSContext* aCx, JS::HandleObject aObj,
|
||||
const void* aHandler, const JSClass* aClass) {
|
||||
js::WrapperOptions options;
|
||||
if (aClass) {
|
||||
options.setClass(aClass);
|
||||
}
|
||||
return js::Wrapper::NewSingleton(aCx, aObj, (const js::Wrapper*)aHandler,
|
||||
options);
|
||||
}
|
||||
|
||||
const JSClass WindowProxyClass = PROXY_CLASS_DEF(
|
||||
"Proxy", JSCLASS_HAS_RESERVED_SLOTS(1)); /* additional class flags */
|
||||
|
||||
@ -490,7 +480,7 @@ void SetProxyReservedSlot(JSObject* obj, uint32_t slot, const JS::Value* val) {
|
||||
|
||||
JSObject* NewWindowProxy(JSContext* aCx, JS::HandleObject aObj,
|
||||
const void* aHandler) {
|
||||
return WrapperNewSingleton(aCx, aObj, aHandler, &WindowProxyClass);
|
||||
return WrapperNew(aCx, aObj, aHandler, &WindowProxyClass);
|
||||
}
|
||||
|
||||
JS::Value GetProxyPrivate(JSObject* obj) { return js::GetProxyPrivate(obj); }
|
||||
@ -677,7 +667,7 @@ bool IsDebugBuild() {
|
||||
}
|
||||
|
||||
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
|
||||
void Get##Type##ArrayLengthAndData(JSObject* obj, uint32_t* length, \
|
||||
void Get##Type##ArrayLengthAndData(JSObject* obj, size_t* length, \
|
||||
bool* isSharedMemory, type** data) { \
|
||||
js::Get##Type##ArrayLengthAndData(obj, length, isSharedMemory, data); \
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ impl<T> JS::Rooted<T> {
|
||||
|
||||
unsafe fn get_root_stack(
|
||||
cx: *mut JSContext,
|
||||
) -> *mut *mut JS::Rooted<*mut ::std::os::raw::c_void>
|
||||
) -> *mut *mut JS::Rooted<*mut JS::detail::RootListEntry>
|
||||
where
|
||||
T: RootKind,
|
||||
{
|
||||
|
@ -23,14 +23,14 @@ use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
pub enum CreateWith<'a, T: 'a> {
|
||||
Length(u32),
|
||||
Length(usize),
|
||||
Slice(&'a [T]),
|
||||
}
|
||||
|
||||
/// A rooted typed array.
|
||||
pub struct TypedArray<'a, T: 'a + TypedArrayElement> {
|
||||
object: RootedGuard<'a, *mut JSObject>,
|
||||
computed: Option<(*mut T::Element, u32)>,
|
||||
computed: Option<(*mut T::Element, usize)>,
|
||||
}
|
||||
|
||||
impl<'a, T: TypedArrayElement> TypedArray<'a, T> {
|
||||
@ -60,7 +60,7 @@ impl<'a, T: TypedArrayElement> TypedArray<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn data(&mut self) -> (*mut T::Element, u32) {
|
||||
fn data(&mut self) -> (*mut T::Element, usize) {
|
||||
if let Some(data) = self.computed {
|
||||
return data;
|
||||
}
|
||||
@ -102,7 +102,7 @@ impl<'a, T: TypedArrayElementCreator + TypedArrayElement> TypedArray<'a, T> {
|
||||
) -> Result<(), ()> {
|
||||
let length = match with {
|
||||
CreateWith::Length(len) => len,
|
||||
CreateWith::Slice(slice) => slice.len() as u32,
|
||||
CreateWith::Slice(slice) => slice.len(),
|
||||
};
|
||||
|
||||
result.set(T::create_new(cx, length));
|
||||
@ -137,13 +137,13 @@ pub trait TypedArrayElement {
|
||||
/// Unwrap a typed array JS reflector for this element type.
|
||||
unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject;
|
||||
/// Retrieve the length and data of a typed array's buffer for this element type.
|
||||
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32);
|
||||
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, usize);
|
||||
}
|
||||
|
||||
/// Internal trait for creating new typed arrays.
|
||||
pub trait TypedArrayElementCreator: TypedArrayElement {
|
||||
/// Create a new typed array.
|
||||
unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject;
|
||||
unsafe fn create_new(cx: *mut JSContext, length: usize) -> *mut JSObject;
|
||||
/// Get the data.
|
||||
unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element;
|
||||
}
|
||||
@ -162,7 +162,7 @@ macro_rules! typed_array_element {
|
||||
$unwrap(obj)
|
||||
}
|
||||
|
||||
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32) {
|
||||
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, usize) {
|
||||
let mut len = 0;
|
||||
let mut shared = false;
|
||||
let mut data = ptr::null_mut();
|
||||
@ -182,7 +182,7 @@ macro_rules! typed_array_element {
|
||||
typed_array_element!($t, $element, $unwrap, $length_and_data);
|
||||
|
||||
impl TypedArrayElementCreator for $t {
|
||||
unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject {
|
||||
unsafe fn create_new(cx: *mut JSContext, length: usize) -> *mut JSObject {
|
||||
$create_new(cx, length)
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ fn rooting() {
|
||||
&c_option));
|
||||
let _ar = js::ar::AutoRealm::with_obj(cx, global.get());
|
||||
rooted!(in(cx) let prototype_proto = JS::GetRealmObjectPrototype(cx));
|
||||
rooted!(in(cx) let proto = JS_NewObjectWithUniqueType(cx,
|
||||
rooted!(in(cx) let proto = JS_NewObjectWithGivenProto(cx,
|
||||
&CLASS as *const _,
|
||||
prototype_proto.handle()));
|
||||
define_methods(cx, proto.handle(), &METHODS[..]).unwrap();
|
||||
|
@ -72,7 +72,8 @@ ifndef HAVE_DTRACE
|
||||
endif
|
||||
endif
|
||||
|
||||
DIST_GARBAGE = config.cache config.log config.status* \
|
||||
GARBAGE_DIRS += config.statusd
|
||||
DIST_GARBAGE = config.cache config.log config.status \
|
||||
config/autoconf.mk config/emptyvars.mk \
|
||||
js-config.h js-confdefs.h \
|
||||
backend.mk config/backend.mk devtools/backend.mk editline/backend.mk \
|
||||
|
5
js/src/aclocal.m4
vendored
5
js/src/aclocal.m4
vendored
@ -8,8 +8,6 @@ builtin(include, ../../build/autoconf/hooks.m4)dnl
|
||||
builtin(include, ../../build/autoconf/config.status.m4)dnl
|
||||
builtin(include, ../../build/autoconf/toolchain.m4)dnl
|
||||
builtin(include, ../../build/autoconf/pkg.m4)dnl
|
||||
builtin(include, ../../build/autoconf/nspr.m4)dnl
|
||||
builtin(include, ../../build/autoconf/nspr-build.m4)dnl
|
||||
builtin(include, ../../build/autoconf/codeset.m4)dnl
|
||||
builtin(include, ../../build/autoconf/altoptions.m4)dnl
|
||||
builtin(include, ../../build/autoconf/mozprog.m4)dnl
|
||||
@ -18,12 +16,9 @@ builtin(include, ../../build/autoconf/compiler-opts.m4)dnl
|
||||
builtin(include, ../../build/autoconf/expandlibs.m4)dnl
|
||||
builtin(include, ../../build/autoconf/arch.m4)dnl
|
||||
builtin(include, ../../build/autoconf/android.m4)dnl
|
||||
builtin(include, ../../build/autoconf/zlib.m4)dnl
|
||||
builtin(include, ../../build/autoconf/icu.m4)dnl
|
||||
builtin(include, ../../build/autoconf/clang-plugin.m4)dnl
|
||||
builtin(include, ../../build/autoconf/alloc.m4)dnl
|
||||
builtin(include, ../../build/autoconf/sanitize.m4)dnl
|
||||
builtin(include, ../../build/autoconf/ios.m4)dnl
|
||||
|
||||
define([__MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE]))
|
||||
define([AC_INIT_PREPARE],
|
||||
|
@ -3,14 +3,14 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
CONFIGURE_SUBST_FILES += [
|
||||
'js-config',
|
||||
'js.pc',
|
||||
"js-config",
|
||||
"js.pc",
|
||||
]
|
||||
|
||||
LIBRARY_DEFINES['EXPORT_JS_API'] = True
|
||||
LIBRARY_DEFINES["EXPORT_JS_API"] = True
|
||||
|
||||
if not CONFIG['JS_STANDALONE']:
|
||||
LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
|
||||
if not CONFIG["JS_STANDALONE"]:
|
||||
LIBRARY_DEFINES["MOZ_HAS_MOZGLUE"] = True
|
||||
|
||||
# JavaScript must be built shared, even for static builds, as it is used by
|
||||
# other modules which are always built shared. Failure to do so results in
|
||||
@ -20,60 +20,63 @@ if not CONFIG['JS_STANDALONE']:
|
||||
# In fact, we now build both a static and a shared library, as the
|
||||
# JS shell would like to link to the static library.
|
||||
|
||||
if CONFIG['JS_SHARED_LIBRARY']:
|
||||
GeckoSharedLibrary('js', linkage=None)
|
||||
SHARED_LIBRARY_NAME = CONFIG['JS_LIBRARY_NAME']
|
||||
if CONFIG["JS_SHARED_LIBRARY"]:
|
||||
GeckoSharedLibrary("js", linkage=None)
|
||||
SHARED_LIBRARY_NAME = CONFIG["JS_LIBRARY_NAME"]
|
||||
|
||||
# Ensure symbol versions of shared library on Linux do not conflict
|
||||
# with those in libxul.
|
||||
if CONFIG['OS_TARGET'] == 'Linux':
|
||||
GeneratedFile('symverscript', script='/build/gen_symverscript.py',
|
||||
inputs=['symverscript.in'],
|
||||
flags=[CONFIG['JS_LIBRARY_NAME'].replace('-', '_')])
|
||||
SYMBOLS_FILE = '!symverscript'
|
||||
if CONFIG["OS_TARGET"] == "Linux":
|
||||
GeneratedFile(
|
||||
"symverscript",
|
||||
script="/build/gen_symverscript.py",
|
||||
inputs=["symverscript.in"],
|
||||
flags=[CONFIG["JS_LIBRARY_NAME"].replace("-", "_")],
|
||||
)
|
||||
SYMBOLS_FILE = "!symverscript"
|
||||
else:
|
||||
Library('js')
|
||||
Library("js")
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
STATIC_LIBRARY_NAME = 'js_static'
|
||||
STATIC_LIBRARY_NAME = "js_static"
|
||||
|
||||
if CONFIG['JS_HAS_INTL_API']:
|
||||
if CONFIG["JS_HAS_INTL_API"]:
|
||||
USE_LIBS += [
|
||||
'icu',
|
||||
"icu",
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'nspr',
|
||||
'zlib',
|
||||
"nspr",
|
||||
"zlib",
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] not in ('WINNT', 'HP-UX'):
|
||||
if CONFIG["OS_ARCH"] not in ("WINNT", "HP-UX"):
|
||||
OS_LIBS += [
|
||||
'm',
|
||||
"m",
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'FreeBSD':
|
||||
if CONFIG["OS_ARCH"] == "FreeBSD":
|
||||
OS_LIBS += [
|
||||
'-pthread',
|
||||
"-pthread",
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Linux':
|
||||
if CONFIG["OS_ARCH"] == "Linux":
|
||||
OS_LIBS += [
|
||||
'dl',
|
||||
"dl",
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'SunOS':
|
||||
if CONFIG["OS_ARCH"] == "SunOS":
|
||||
OS_LIBS += [
|
||||
'posix4',
|
||||
'dl',
|
||||
'nsl',
|
||||
'socket',
|
||||
"posix4",
|
||||
"dl",
|
||||
"nsl",
|
||||
"socket",
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_NEEDS_LIBATOMIC']:
|
||||
OS_LIBS += ['atomic']
|
||||
if CONFIG["MOZ_NEEDS_LIBATOMIC"]:
|
||||
OS_LIBS += ["atomic"]
|
||||
|
||||
OS_LIBS += CONFIG['REALTIME_LIBS']
|
||||
OS_LIBS += CONFIG["REALTIME_LIBS"]
|
||||
|
||||
NO_EXPAND_LIBS = True
|
||||
|
||||
@ -82,10 +85,12 @@ DIST_INSTALL = True
|
||||
# Run SpiderMonkey style checker after linking the static library. This avoids
|
||||
# running the script for no-op builds.
|
||||
GeneratedFile(
|
||||
'spidermonkey_checks', script='/config/run_spidermonkey_checks.py',
|
||||
"spidermonkey_checks",
|
||||
script="/config/run_spidermonkey_checks.py",
|
||||
inputs=[
|
||||
'!%sjs_static.%s' % (CONFIG['LIB_PREFIX'], CONFIG['LIB_SUFFIX']),
|
||||
'/config/check_spidermonkey_style.py',
|
||||
'/config/check_macroassembler_style.py',
|
||||
'/config/check_js_opcode.py'
|
||||
])
|
||||
"!%sjs_static.%s" % (CONFIG["LIB_PREFIX"], CONFIG["LIB_SUFFIX"]),
|
||||
"/config/check_spidermonkey_style.py",
|
||||
#"/config/check_macroassembler_style.py",
|
||||
"/config/check_js_opcode.py",
|
||||
],
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ namespace js {
|
||||
|
||||
inline bool GetElement(JSContext* cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleValue vp) {
|
||||
if (obj->isNative() &&
|
||||
if (obj->is<NativeObject>() &&
|
||||
index < obj->as<NativeObject>().getDenseInitializedLength()) {
|
||||
vp.set(obj->as<NativeObject>().getDenseElement(index));
|
||||
if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "builtin/Array-inl.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
@ -12,6 +11,7 @@
|
||||
#include "mozilla/TextUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
@ -42,6 +42,7 @@
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/ToSource.h" // js::ValueToSource
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
#include "vm/WrapperObject.h"
|
||||
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
@ -52,12 +53,10 @@
|
||||
#include "vm/IsGivenTypeObject-inl.h"
|
||||
#include "vm/JSAtom-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/ObjectGroup-inl.h" // JSObject::setSingleton
|
||||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::Abs;
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::CeilingLog2;
|
||||
using mozilla::CheckedInt;
|
||||
using mozilla::DebugOnly;
|
||||
@ -304,7 +303,7 @@ template <typename T>
|
||||
static bool HasAndGetElement(JSContext* cx, HandleObject obj,
|
||||
HandleObject receiver, T index, bool* hole,
|
||||
MutableHandleValue vp) {
|
||||
if (obj->isNative()) {
|
||||
if (obj->is<NativeObject>()) {
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
if (index < nobj->getDenseInitializedLength()) {
|
||||
vp.set(nobj->getDenseElement(size_t(index)));
|
||||
@ -452,7 +451,7 @@ bool js::GetElements(JSContext* cx, HandleObject aobj, uint32_t length,
|
||||
|
||||
if (aobj->is<TypedArrayObject>()) {
|
||||
Handle<TypedArrayObject*> typedArray = aobj.as<TypedArrayObject>();
|
||||
if (typedArray->length().deprecatedGetUint32() == length) {
|
||||
if (typedArray->length().get() == length) {
|
||||
return TypedArrayObject::getElements(cx, typedArray, vp);
|
||||
}
|
||||
}
|
||||
@ -474,7 +473,7 @@ bool js::GetElements(JSContext* cx, HandleObject aobj, uint32_t length,
|
||||
|
||||
static inline bool GetArrayElement(JSContext* cx, HandleObject obj,
|
||||
uint64_t index, MutableHandleValue vp) {
|
||||
if (obj->isNative()) {
|
||||
if (obj->is<NativeObject>()) {
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
if (index < nobj->getDenseInitializedLength()) {
|
||||
vp.set(nobj->getDenseElement(size_t(index)));
|
||||
@ -537,13 +536,10 @@ static bool DeleteArrayElement(JSContext* cx, HandleObject obj, uint64_t index,
|
||||
if (index <= UINT32_MAX) {
|
||||
uint32_t idx = uint32_t(index);
|
||||
if (idx < aobj->getDenseInitializedLength()) {
|
||||
if (!aobj->maybeCopyElementsForWrite(cx)) {
|
||||
return false;
|
||||
}
|
||||
if (idx + 1 == aobj->getDenseInitializedLength()) {
|
||||
aobj->setDenseInitializedLengthMaybeNonExtensible(cx, idx);
|
||||
} else {
|
||||
aobj->setDenseElementHole(cx, idx);
|
||||
aobj->setDenseElementHole(idx);
|
||||
}
|
||||
if (!SuppressDeletedElement(cx, obj, idx)) {
|
||||
return false;
|
||||
@ -672,10 +668,6 @@ bool js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
ObjectOpResult& result) {
|
||||
MOZ_ASSERT(id == NameToId(cx->names().length));
|
||||
|
||||
if (!arr->maybeCopyElementsForWrite(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 1.
|
||||
uint32_t newLen;
|
||||
if (attrs & JSPROP_IGNORE_VALUE) {
|
||||
@ -770,10 +762,6 @@ bool js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
// (non-configurable) elements.
|
||||
if (!arr->isIndexed() && !arr->denseElementsMaybeInIteration() &&
|
||||
!arr->denseElementsAreSealed()) {
|
||||
if (!arr->maybeCopyElementsForWrite(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t oldCapacity = arr->getDenseCapacity();
|
||||
uint32_t oldInitializedLength = arr->getDenseInitializedLength();
|
||||
MOZ_ASSERT(oldCapacity >= oldInitializedLength);
|
||||
@ -906,7 +894,7 @@ bool js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
|
||||
// Update array length. Technically we should have been doing this
|
||||
// throughout the loop, in step 19.d.iii.
|
||||
arr->setLength(cx, newLen);
|
||||
arr->setLength(newLen);
|
||||
|
||||
// Step 20.
|
||||
if (attrs & JSPROP_READONLY) {
|
||||
@ -959,13 +947,13 @@ static bool array_addProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
if (index >= length) {
|
||||
MOZ_ASSERT(arr->lengthIsWritable(),
|
||||
"how'd this element get added if length is non-writable?");
|
||||
arr->setLength(cx, index + 1);
|
||||
arr->setLength(index + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj) {
|
||||
if (!obj->isNative()) {
|
||||
if (!obj->is<NativeObject>()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -987,7 +975,7 @@ static inline bool ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj) {
|
||||
* indexed properties or elements along its prototype chain.
|
||||
*/
|
||||
bool js::ObjectMayHaveExtraIndexedProperties(JSObject* obj) {
|
||||
MOZ_ASSERT_IF(obj->hasDynamicPrototype(), !obj->isNative());
|
||||
MOZ_ASSERT_IF(obj->hasDynamicPrototype(), !obj->is<NativeObject>());
|
||||
|
||||
if (ObjectMayHaveExtraIndexedOwnProperties(obj)) {
|
||||
return true;
|
||||
@ -1402,7 +1390,7 @@ bool js::array_join(JSContext* cx, unsigned argc, Value* vp) {
|
||||
// An optimized version of a special case of steps 5-8: when length==1 and
|
||||
// the 0th element is a string, ToString() of that element is a no-op and
|
||||
// so it can be immediately returned as the result.
|
||||
if (length == 1 && obj->isNative()) {
|
||||
if (length == 1 && obj->is<NativeObject>()) {
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
if (nobj->getDenseInitializedLength() == 1) {
|
||||
Value elem0 = nobj->getDenseElement(0);
|
||||
@ -1520,10 +1508,8 @@ static bool array_toLocaleString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* vector must point to rooted memory. */
|
||||
static bool SetArrayElements(
|
||||
JSContext* cx, HandleObject obj, uint64_t start, uint32_t count,
|
||||
const Value* vector,
|
||||
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update) {
|
||||
static bool SetArrayElements(JSContext* cx, HandleObject obj, uint64_t start,
|
||||
uint32_t count, const Value* vector) {
|
||||
MOZ_ASSERT(count <= MAX_ARRAY_INDEX);
|
||||
MOZ_ASSERT(start + count < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT));
|
||||
|
||||
@ -1533,8 +1519,8 @@ static bool SetArrayElements(
|
||||
|
||||
if (!ObjectMayHaveExtraIndexedProperties(obj) && start <= UINT32_MAX) {
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
DenseElementResult result = nobj->setOrExtendDenseElements(
|
||||
cx, uint32_t(start), vector, count, updateTypes);
|
||||
DenseElementResult result =
|
||||
nobj->setOrExtendDenseElements(cx, uint32_t(start), vector, count);
|
||||
if (result != DenseElementResult::Incomplete) {
|
||||
return result == DenseElementResult::Success;
|
||||
}
|
||||
@ -1590,11 +1576,7 @@ static DenseElementResult ArrayReverseDenseKernel(JSContext* cx,
|
||||
}
|
||||
|
||||
/* Fill out the array's initialized length to its proper length. */
|
||||
obj->ensureDenseInitializedLength(cx, length, 0);
|
||||
} else {
|
||||
if (!obj->maybeCopyElementsForWrite(cx)) {
|
||||
return DenseElementResult::Failure;
|
||||
}
|
||||
obj->ensureDenseInitializedLength(length, 0);
|
||||
}
|
||||
|
||||
if (!obj->denseElementsMaybeInIteration() &&
|
||||
@ -1610,7 +1592,7 @@ static DenseElementResult ArrayReverseDenseKernel(JSContext* cx,
|
||||
return true;
|
||||
}
|
||||
|
||||
obj->setDenseElementHole(cx, index);
|
||||
obj->setDenseElementHole(index);
|
||||
return SuppressDeletedProperty(cx, obj, INT_TO_JSID(index));
|
||||
};
|
||||
|
||||
@ -1777,11 +1759,11 @@ static inline bool CompareLexicographicInt32(const Value& a, const Value& b,
|
||||
if (digitsa == digitsb) {
|
||||
*lessOrEqualp = (auint <= buint);
|
||||
} else if (digitsa > digitsb) {
|
||||
MOZ_ASSERT((digitsa - digitsb) < ArrayLength(powersOf10));
|
||||
MOZ_ASSERT((digitsa - digitsb) < std::size(powersOf10));
|
||||
*lessOrEqualp =
|
||||
(uint64_t(auint) < uint64_t(buint) * powersOf10[digitsa - digitsb]);
|
||||
} else { /* if (digitsb > digitsa) */
|
||||
MOZ_ASSERT((digitsb - digitsa) < ArrayLength(powersOf10));
|
||||
MOZ_ASSERT((digitsb - digitsa) < std::size(powersOf10));
|
||||
*lessOrEqualp =
|
||||
(uint64_t(auint) * powersOf10[digitsb - digitsa] <= uint64_t(buint));
|
||||
}
|
||||
@ -2117,11 +2099,11 @@ static bool FillWithUndefined(JSContext* cx, HandleObject obj, uint32_t start,
|
||||
|
||||
if (obj->is<ArrayObject>() &&
|
||||
start + count >= obj->as<ArrayObject>().length()) {
|
||||
obj->as<ArrayObject>().setLengthInt32(start + count);
|
||||
obj->as<ArrayObject>().setLength(start + count);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
nobj->setDenseElementWithType(cx, start + i, UndefinedHandleValue);
|
||||
nobj->setDenseElement(start + i, UndefinedHandleValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2213,11 +2195,9 @@ bool js::intrinsic_ArrayNativeSort(JSContext* cx, unsigned argc, Value* vp) {
|
||||
undefs = 0;
|
||||
bool allStrings = true;
|
||||
bool allInts = true;
|
||||
bool extraIndexed;
|
||||
RootedValue v(cx);
|
||||
if (IsPackedArray(obj)) {
|
||||
HandleArrayObject array = obj.as<ArrayObject>();
|
||||
extraIndexed = false;
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (!CheckForInterrupt(cx)) {
|
||||
@ -2235,8 +2215,6 @@ bool js::intrinsic_ArrayNativeSort(JSContext* cx, unsigned argc, Value* vp) {
|
||||
allInts = allInts && v.isInt32();
|
||||
}
|
||||
} else {
|
||||
extraIndexed = ObjectMayHaveExtraIndexedProperties(obj);
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (!CheckForInterrupt(cx)) {
|
||||
return false;
|
||||
@ -2306,13 +2284,7 @@ bool js::intrinsic_ArrayNativeSort(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
}
|
||||
|
||||
// We can omit the type update when neither collecting the elements
|
||||
// nor calling the default comparator can execute a (getter) function
|
||||
// that might run user code.
|
||||
ShouldUpdateTypes updateTypes = !extraIndexed && (allStrings || allInts)
|
||||
? ShouldUpdateTypes::DontUpdate
|
||||
: ShouldUpdateTypes::Update;
|
||||
if (!SetArrayElements(cx, obj, 0, uint32_t(n), vec.begin(), updateTypes)) {
|
||||
if (!SetArrayElements(cx, obj, 0, uint32_t(n), vec.begin())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2349,8 +2321,8 @@ bool js::NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v) {
|
||||
}
|
||||
|
||||
arr->setDenseInitializedLength(length + 1);
|
||||
arr->setLengthInt32(length + 1);
|
||||
arr->initDenseElementWithType(cx, length, v);
|
||||
arr->setLength(length + 1);
|
||||
arr->initDenseElement(length, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2462,8 +2434,7 @@ void js::ArrayShiftMoveElements(ArrayObject* arr) {
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
MOZ_ASSERT(arr->isExtensible());
|
||||
MOZ_ASSERT(arr->lengthIsWritable());
|
||||
MOZ_ASSERT_IF(jit::JitOptions.warpBuilder, IsPackedArray(arr));
|
||||
MOZ_ASSERT(!arr->denseElementsAreCopyOnWrite());
|
||||
MOZ_ASSERT(IsPackedArray(arr));
|
||||
MOZ_ASSERT(!arr->denseElementsHaveMaybeInIterationFlag());
|
||||
|
||||
size_t initlen = arr->getDenseInitializedLength();
|
||||
@ -2485,19 +2456,6 @@ static inline void SetInitializedLength(JSContext* cx, NativeObject* obj,
|
||||
}
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool MoveDenseElements(JSContext* cx, NativeObject* obj,
|
||||
uint32_t dstStart, uint32_t srcStart,
|
||||
uint32_t length) {
|
||||
MOZ_ASSERT(obj->isExtensible());
|
||||
|
||||
if (!obj->maybeCopyElementsForWrite(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
obj->moveDenseElements(dstStart, srcStart, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
static DenseElementResult ArrayShiftDenseKernel(JSContext* cx, HandleObject obj,
|
||||
MutableHandleValue rval) {
|
||||
if (!IsPackedArray(obj) && ObjectMayHaveExtraIndexedProperties(obj)) {
|
||||
@ -2527,9 +2485,7 @@ static DenseElementResult ArrayShiftDenseKernel(JSContext* cx, HandleObject obj,
|
||||
return DenseElementResult::Success;
|
||||
}
|
||||
|
||||
if (!MoveDenseElements(cx, nobj, 0, 1, initlen - 1)) {
|
||||
return DenseElementResult::Failure;
|
||||
}
|
||||
nobj->moveDenseElements(0, 1, initlen - 1);
|
||||
|
||||
SetInitializedLength(cx, nobj, initlen - 1);
|
||||
return DenseElementResult::Success;
|
||||
@ -2677,7 +2633,7 @@ static bool array_unshift(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < args.length(); i++) {
|
||||
nobj->setDenseElementWithType(cx, i, args[i]);
|
||||
nobj->setDenseElement(i, args[i]);
|
||||
}
|
||||
optimized = true;
|
||||
} while (false);
|
||||
@ -2813,16 +2769,16 @@ static ArrayObject* CopyDenseArrayElements(JSContext* cx,
|
||||
newlength = std::min<uint32_t>(initlen - begin, count);
|
||||
}
|
||||
|
||||
ArrayObject* narr = NewFullyAllocatedArrayTryReuseGroup(cx, obj, newlength);
|
||||
ArrayObject* narr = NewDenseFullyAllocatedArray(cx, newlength);
|
||||
if (!narr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(count >= narr->length());
|
||||
narr->setLength(cx, count);
|
||||
narr->setLength(count);
|
||||
|
||||
if (newlength > 0) {
|
||||
narr->initDenseElements(cx, obj, begin, newlength);
|
||||
narr->initDenseElements(obj, begin, newlength);
|
||||
}
|
||||
|
||||
return narr;
|
||||
@ -2860,7 +2816,7 @@ static bool CopyArrayElements(JSContext* cx, HandleObject obj, uint64_t begin,
|
||||
|
||||
break;
|
||||
}
|
||||
result->setDenseElementWithType(cx, index, value);
|
||||
result->setDenseElement(index, value);
|
||||
}
|
||||
}
|
||||
startIndex = index + 1;
|
||||
@ -2969,7 +2925,7 @@ static bool array_splice_impl(JSContext* cx, unsigned argc, Value* vp,
|
||||
}
|
||||
} else {
|
||||
/* Step 9. */
|
||||
arr = NewFullyAllocatedArrayTryReuseGroup(cx, obj, count);
|
||||
arr = NewDenseFullyAllocatedArray(cx, count);
|
||||
if (!arr) {
|
||||
return false;
|
||||
}
|
||||
@ -3031,16 +2987,13 @@ static bool array_splice_impl(JSContext* cx, unsigned argc, Value* vp,
|
||||
MOZ_ASSERT(sourceIndex <= len && targetIndex <= len && len <= UINT32_MAX,
|
||||
"sourceIndex and targetIndex are uint32 array indices");
|
||||
MOZ_ASSERT(finalLength < len, "finalLength is strictly less than len");
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(obj->is<NativeObject>());
|
||||
|
||||
/* Steps 15.a-b. */
|
||||
HandleArrayObject arr = obj.as<ArrayObject>();
|
||||
if (targetIndex != 0 || !arr->tryShiftDenseElements(sourceIndex)) {
|
||||
if (!MoveDenseElements(cx, arr, uint32_t(targetIndex),
|
||||
uint32_t(sourceIndex),
|
||||
uint32_t(len - sourceIndex))) {
|
||||
return false;
|
||||
}
|
||||
arr->moveDenseElements(uint32_t(targetIndex), uint32_t(sourceIndex),
|
||||
uint32_t(len - sourceIndex));
|
||||
}
|
||||
|
||||
/* Steps 15.c-d. */
|
||||
@ -3244,7 +3197,7 @@ static bool GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj,
|
||||
// properties.
|
||||
JSObject* pobj = obj;
|
||||
do {
|
||||
if (!pobj->isNative() || pobj->getClass()->getResolve() ||
|
||||
if (!pobj->is<NativeObject>() || pobj->getClass()->getResolve() ||
|
||||
pobj->getOpsLookupProperty()) {
|
||||
return true;
|
||||
}
|
||||
@ -3267,8 +3220,7 @@ static bool GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj,
|
||||
|
||||
// Append typed array elements.
|
||||
if (nativeObj->is<TypedArrayObject>()) {
|
||||
uint32_t len =
|
||||
nativeObj->as<TypedArrayObject>().length().deprecatedGetUint32();
|
||||
size_t len = nativeObj->as<TypedArrayObject>().length().get();
|
||||
for (uint32_t i = begin; i < len && i < end; i++) {
|
||||
if (!indexes.append(i)) {
|
||||
return false;
|
||||
@ -3440,8 +3392,7 @@ static bool ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin,
|
||||
}
|
||||
}
|
||||
|
||||
RootedArrayObject narr(cx,
|
||||
NewPartlyAllocatedArrayTryReuseGroup(cx, obj, count));
|
||||
RootedArrayObject narr(cx, NewDensePartlyAllocatedArray(cx, count));
|
||||
if (!narr) {
|
||||
return false;
|
||||
}
|
||||
@ -3459,7 +3410,8 @@ static bool ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin,
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->isNative() && obj->as<NativeObject>().isIndexed() && count > 1000) {
|
||||
if (obj->is<NativeObject>() && obj->as<NativeObject>().isIndexed() &&
|
||||
count > 1000) {
|
||||
if (!SliceSparse(cx, obj, begin, end, narr)) {
|
||||
return false;
|
||||
}
|
||||
@ -3589,19 +3541,19 @@ static bool ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr,
|
||||
if (!result->ensureElements(cx, newlength)) {
|
||||
return false;
|
||||
}
|
||||
result->initDenseElements(cx, arr, begin, newlength);
|
||||
result->initDenseElements(arr, begin, newlength);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(count >= result->length());
|
||||
result->setLength(cx, count);
|
||||
result->setLength(count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* js::ArraySliceDense(JSContext* cx, HandleObject obj, int32_t begin,
|
||||
int32_t end, HandleObject result) {
|
||||
MOZ_ASSERT_IF(jit::JitOptions.warpBuilder, IsPackedArray(obj));
|
||||
MOZ_ASSERT(IsPackedArray(obj));
|
||||
|
||||
if (result && IsArraySpecies(cx, obj)) {
|
||||
if (!ArraySliceDenseKernel(cx, &obj->as<ArrayObject>(), begin, end,
|
||||
@ -3638,8 +3590,8 @@ static bool array_isArray(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
static bool ArrayFromCallArgs(JSContext* cx, CallArgs& args,
|
||||
HandleObject proto = nullptr) {
|
||||
ArrayObject* obj = NewCopiedArrayForCallingAllocationSite(
|
||||
cx, args.array(), args.length(), proto);
|
||||
ArrayObject* obj =
|
||||
NewDenseCopiedArray(cx, args.length(), args.array(), proto);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
@ -3800,8 +3752,7 @@ static inline bool ArrayConstructorImpl(JSContext* cx, CallArgs& args,
|
||||
}
|
||||
}
|
||||
|
||||
ArrayObject* obj =
|
||||
NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
|
||||
ArrayObject* obj = NewDensePartlyAllocatedArray(cx, length, proto);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
@ -3842,9 +3793,8 @@ ArrayObject* js::ArrayConstructorOneArg(JSContext* cx,
|
||||
}
|
||||
|
||||
uint32_t length = uint32_t(lengthInt);
|
||||
RootedObjectGroup group(cx, templateObject->group());
|
||||
ArrayObject* res = NewPartlyAllocatedArrayTryUseGroup(cx, group, length);
|
||||
MOZ_ASSERT_IF(res, res->realm() == group->realm());
|
||||
ArrayObject* res = NewDensePartlyAllocatedArray(cx, length);
|
||||
MOZ_ASSERT_IF(res, res->realm() == templateObject->realm());
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -3874,8 +3824,7 @@ static JSObject* CreateArrayPrototype(JSContext* cx, JSProtoKey key) {
|
||||
RootedArrayObject arrayProto(
|
||||
cx, ArrayObject::createArray(cx, gc::AllocKind::OBJECT4, gc::TenuredHeap,
|
||||
shape, group, 0, metadata));
|
||||
if (!arrayProto || !JSObject::setSingleton(cx, arrayProto) ||
|
||||
!JSObject::setDelegate(cx, arrayProto) ||
|
||||
if (!arrayProto || !JSObject::setDelegate(cx, arrayProto) ||
|
||||
!AddLengthProperty(cx, arrayProto)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -3887,7 +3836,7 @@ static bool array_proto_finish(JSContext* cx, JS::HandleObject ctor,
|
||||
JS::HandleObject proto) {
|
||||
// Add Array.prototype[@@unscopables]. ECMA-262 draft (2016 Mar 19) 22.1.3.32.
|
||||
RootedObject unscopables(
|
||||
cx, NewSingletonObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
cx, NewTenuredObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
if (!unscopables) {
|
||||
return false;
|
||||
}
|
||||
@ -3993,7 +3942,7 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArray(JSContext* cx, uint32_t length,
|
||||
/* Fixup the elements pointer and length, which may be incorrect. */
|
||||
ArrayObject* arr = &obj->as<ArrayObject>();
|
||||
arr->setFixedElements();
|
||||
arr->setLength(cx, length);
|
||||
arr->setLength(length);
|
||||
if (maxLength > 0 &&
|
||||
!EnsureNewArrayElements(cx, arr, std::min(maxLength, length))) {
|
||||
return nullptr;
|
||||
@ -4037,10 +3986,6 @@ static MOZ_ALWAYS_INLINE ArrayObject* NewArray(JSContext* cx, uint32_t length,
|
||||
EmptyShape::insertInitialShape(cx, shape, proto);
|
||||
}
|
||||
|
||||
if (newKind == SingletonObject && !JSObject::setSingleton(cx, arr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (isCachable) {
|
||||
NewObjectCache& cache = cx->caches().newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
@ -4073,6 +4018,13 @@ ArrayObject* JS_FASTCALL js::NewDenseFullyAllocatedArray(
|
||||
return NewArray<UINT32_MAX>(cx, length, proto, newKind);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewDensePartlyAllocatedArray(
|
||||
JSContext* cx, uint32_t length, HandleObject proto /* = nullptr */,
|
||||
NewObjectKind newKind /* = GenericObject */) {
|
||||
return NewArray<ArrayObject::EagerAllocationMaxLength>(cx, length, proto,
|
||||
newKind);
|
||||
}
|
||||
|
||||
ArrayObject* JS_FASTCALL js::NewDenseUnallocatedArray(
|
||||
JSContext* cx, uint32_t length, HandleObject proto /* = nullptr */,
|
||||
NewObjectKind newKind /* = GenericObject */) {
|
||||
@ -4126,166 +4078,9 @@ ArrayObject* js::NewDenseFullyAllocatedArrayWithTemplate(
|
||||
return arr;
|
||||
}
|
||||
|
||||
ArrayObject* js::NewDenseCopyOnWriteArray(JSContext* cx,
|
||||
HandleArrayObject templateObject) {
|
||||
MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
|
||||
|
||||
gc::InitialHeap heap = GetInitialHeap(GenericObject, templateObject->group());
|
||||
|
||||
ArrayObject* arr =
|
||||
ArrayObject::createCopyOnWriteArray(cx, heap, templateObject);
|
||||
if (!arr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
probes::CreateObject(cx, arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Return a new array with the specified length and allocated capacity (up to
|
||||
// maxLength), using the specified group if possible. If the specified group
|
||||
// cannot be used, ensure that the created array at least has the given
|
||||
// [[Prototype]].
|
||||
template <uint32_t maxLength>
|
||||
static inline ArrayObject* NewArrayTryUseGroup(
|
||||
JSContext* cx, HandleObjectGroup group, size_t length,
|
||||
NewObjectKind newKind = GenericObject) {
|
||||
MOZ_ASSERT(newKind != SingletonObject);
|
||||
|
||||
RootedObject proto(cx, group->proto().toObject());
|
||||
ArrayObject* res = NewArray<maxLength>(cx, length, proto, newKind);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
res->setGroup(group);
|
||||
|
||||
// If the length calculation overflowed, make sure that is marked for the
|
||||
// new group.
|
||||
if (res->length() > INT32_MAX) {
|
||||
res->setLength(cx, res->length());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ArrayObject* js::NewFullyAllocatedArrayTryUseGroup(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
size_t length,
|
||||
NewObjectKind newKind) {
|
||||
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewPartlyAllocatedArrayTryUseGroup(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
size_t length) {
|
||||
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group,
|
||||
length);
|
||||
}
|
||||
|
||||
static bool CanReuseGroupForNewArray(JSObject* obj, JSContext* cx) {
|
||||
if (!obj->is<ArrayObject>()) {
|
||||
return false;
|
||||
}
|
||||
if (obj->as<ArrayObject>().realm() != cx->realm()) {
|
||||
return false;
|
||||
}
|
||||
if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return a new array with the default prototype and specified allocated
|
||||
// capacity and length. If possible, try to reuse the group of the input
|
||||
// object. The resulting array will either reuse the input object's group or
|
||||
// will have unknown property types.
|
||||
template <uint32_t maxLength>
|
||||
static inline ArrayObject* NewArrayTryReuseGroup(
|
||||
JSContext* cx, HandleObject obj, size_t length,
|
||||
NewObjectKind newKind = GenericObject) {
|
||||
if (!CanReuseGroupForNewArray(obj, cx)) {
|
||||
return NewArray<maxLength>(cx, length, nullptr, newKind);
|
||||
}
|
||||
|
||||
RootedObjectGroup group(cx, JSObject::getGroup(cx, obj));
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return NewArrayTryUseGroup<maxLength>(cx, group, length, newKind);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx,
|
||||
HandleObject obj,
|
||||
size_t length,
|
||||
NewObjectKind newKind) {
|
||||
return NewArrayTryReuseGroup<UINT32_MAX>(cx, obj, length, newKind);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx,
|
||||
HandleObject obj,
|
||||
size_t length) {
|
||||
return NewArrayTryReuseGroup<ArrayObject::EagerAllocationMaxLength>(cx, obj,
|
||||
length);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewFullyAllocatedArrayForCallingAllocationSite(
|
||||
JSContext* cx, size_t length, NewObjectKind newKind) {
|
||||
RootedObjectGroup group(
|
||||
cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array));
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewPartlyAllocatedArrayForCallingAllocationSite(
|
||||
JSContext* cx, size_t length, HandleObject proto) {
|
||||
RootedObjectGroup group(
|
||||
cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto));
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group,
|
||||
length);
|
||||
}
|
||||
|
||||
ArrayObject* js::NewCopiedArrayTryUseGroup(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
const Value* vp, size_t length,
|
||||
NewObjectKind newKind,
|
||||
ShouldUpdateTypes updateTypes) {
|
||||
ArrayObject* obj =
|
||||
NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DenseElementResult result =
|
||||
obj->setOrExtendDenseElements(cx, 0, vp, length, updateTypes);
|
||||
if (result == DenseElementResult::Failure) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result == DenseElementResult::Success);
|
||||
return obj;
|
||||
}
|
||||
|
||||
ArrayObject* js::NewCopiedArrayForCallingAllocationSite(
|
||||
JSContext* cx, const Value* vp, size_t length,
|
||||
HandleObject proto /* = nullptr */) {
|
||||
RootedObjectGroup group(
|
||||
cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto));
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewCopiedArrayTryUseGroup(cx, group, vp, length);
|
||||
}
|
||||
|
||||
// TODO(no-TI): clean up.
|
||||
ArrayObject* js::NewArrayWithGroup(JSContext* cx, uint32_t length,
|
||||
HandleObjectGroup group,
|
||||
bool convertDoubleElements) {
|
||||
HandleObjectGroup group) {
|
||||
// Ion can call this with a group from a different realm when calling
|
||||
// another realm's Array constructor.
|
||||
Maybe<AutoRealm> ar;
|
||||
@ -4294,16 +4089,7 @@ ArrayObject* js::NewArrayWithGroup(JSContext* cx, uint32_t length,
|
||||
ar.emplace(cx, group);
|
||||
}
|
||||
|
||||
ArrayObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (convertDoubleElements) {
|
||||
res->setShouldConvertDoubleElements();
|
||||
}
|
||||
|
||||
return res;
|
||||
return NewDenseFullyAllocatedArray(cx, length);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -67,6 +67,12 @@ extern ArrayObject* JS_FASTCALL NewDenseFullyAllocatedArray(
|
||||
JSContext* cx, uint32_t length, HandleObject proto = nullptr,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
// Create a dense array with length == 'length', initialized length set to 0,
|
||||
// and capacity == 'length' clamped to EagerAllocationMaxLength.
|
||||
extern ArrayObject* NewDensePartlyAllocatedArray(
|
||||
JSContext* cx, uint32_t length, HandleObject proto = nullptr,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
// Create a dense array from the given array values, which must be rooted.
|
||||
extern ArrayObject* NewDenseCopiedArray(JSContext* cx, uint32_t length,
|
||||
const Value* values,
|
||||
@ -77,44 +83,8 @@ extern ArrayObject* NewDenseCopiedArray(JSContext* cx, uint32_t length,
|
||||
extern ArrayObject* NewDenseFullyAllocatedArrayWithTemplate(
|
||||
JSContext* cx, uint32_t length, ArrayObject* templateObject);
|
||||
|
||||
// Create a dense array with the same copy-on-write elements as another object.
|
||||
extern ArrayObject* NewDenseCopyOnWriteArray(JSContext* cx,
|
||||
HandleArrayObject templateObject);
|
||||
|
||||
extern ArrayObject* NewFullyAllocatedArrayTryUseGroup(
|
||||
JSContext* cx, HandleObjectGroup group, size_t length,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
extern ArrayObject* NewPartlyAllocatedArrayTryUseGroup(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
size_t length);
|
||||
|
||||
extern ArrayObject* NewFullyAllocatedArrayTryReuseGroup(
|
||||
JSContext* cx, HandleObject obj, size_t length,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
extern ArrayObject* NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx,
|
||||
HandleObject obj,
|
||||
size_t length);
|
||||
|
||||
extern ArrayObject* NewFullyAllocatedArrayForCallingAllocationSite(
|
||||
JSContext* cx, size_t length, NewObjectKind newKind = GenericObject);
|
||||
|
||||
extern ArrayObject* NewPartlyAllocatedArrayForCallingAllocationSite(
|
||||
JSContext* cx, size_t length, HandleObject proto);
|
||||
|
||||
extern ArrayObject* NewCopiedArrayTryUseGroup(
|
||||
JSContext* cx, HandleObjectGroup group, const Value* vp, size_t length,
|
||||
NewObjectKind newKind = GenericObject,
|
||||
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
|
||||
|
||||
extern ArrayObject* NewCopiedArrayForCallingAllocationSite(
|
||||
JSContext* cx, const Value* vp, size_t length,
|
||||
HandleObject proto = nullptr);
|
||||
|
||||
extern ArrayObject* NewArrayWithGroup(JSContext* cx, uint32_t length,
|
||||
HandleObjectGroup group,
|
||||
bool convertDoubleElements);
|
||||
HandleObjectGroup group);
|
||||
|
||||
extern bool ToLength(JSContext* cx, HandleValue v, uint64_t* out);
|
||||
|
||||
|
@ -1169,3 +1169,5 @@ function ArrayAt(index) {
|
||||
// Step 7.
|
||||
return O[k];
|
||||
}
|
||||
// This function is only barely too long for normal inlining.
|
||||
_SetIsInlinableLargeFunction(ArrayAt);
|
||||
|
@ -1072,7 +1072,7 @@ static JSObject* CreateAtomicsObject(JSContext* cx, JSProtoKey key) {
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewSingletonObjectWithGivenProto(cx, &AtomicsObject::class_, proto);
|
||||
return NewTenuredObjectWithGivenProto(cx, &AtomicsObject::class_, proto);
|
||||
}
|
||||
|
||||
static const ClassSpec AtomicsClassSpec = {CreateAtomicsObject, nullptr,
|
||||
|
@ -27,14 +27,14 @@ class FutexThread {
|
||||
friend class AutoLockFutexAPI;
|
||||
|
||||
public:
|
||||
static MOZ_MUST_USE bool initialize();
|
||||
[[nodiscard]] static bool initialize();
|
||||
static void destroy();
|
||||
|
||||
static void lock();
|
||||
static void unlock();
|
||||
|
||||
FutexThread();
|
||||
MOZ_MUST_USE bool initInstance();
|
||||
[[nodiscard]] bool initInstance();
|
||||
void destroyInstance();
|
||||
|
||||
// Parameters to notify().
|
||||
@ -60,9 +60,9 @@ class FutexThread {
|
||||
// wait.
|
||||
//
|
||||
// wait() will not wake up spuriously.
|
||||
MOZ_MUST_USE WaitResult
|
||||
wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
|
||||
const mozilla::Maybe<mozilla::TimeDuration>& timeout);
|
||||
[[nodiscard]] WaitResult wait(
|
||||
JSContext* cx, js::UniqueLock<js::Mutex>& locked,
|
||||
const mozilla::Maybe<mozilla::TimeDuration>& timeout);
|
||||
|
||||
// Notify the thread this is associated with.
|
||||
//
|
||||
@ -120,12 +120,12 @@ class FutexThread {
|
||||
};
|
||||
|
||||
// Go to sleep if the int32_t value at the given address equals `value`.
|
||||
MOZ_MUST_USE FutexThread::WaitResult atomics_wait_impl(
|
||||
[[nodiscard]] FutexThread::WaitResult atomics_wait_impl(
|
||||
JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int32_t value,
|
||||
const mozilla::Maybe<mozilla::TimeDuration>& timeout);
|
||||
|
||||
// Go to sleep if the int64_t value at the given address equals `value`.
|
||||
MOZ_MUST_USE FutexThread::WaitResult atomics_wait_impl(
|
||||
[[nodiscard]] FutexThread::WaitResult atomics_wait_impl(
|
||||
JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int64_t value,
|
||||
const mozilla::Maybe<mozilla::TimeDuration>& timeout);
|
||||
|
||||
@ -133,8 +133,8 @@ MOZ_MUST_USE FutexThread::WaitResult atomics_wait_impl(
|
||||
// all. The return value is nonnegative and is the number of waiters woken. If
|
||||
// the number of waiters woken exceeds INT64_MAX then this never returns. If
|
||||
// `count` is nonnegative then the return value is never greater than `count`.
|
||||
MOZ_MUST_USE int64_t atomics_notify_impl(SharedArrayRawBuffer* sarb,
|
||||
size_t byteOffset, int64_t count);
|
||||
[[nodiscard]] int64_t atomics_notify_impl(SharedArrayRawBuffer* sarb,
|
||||
size_t byteOffset, int64_t count);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "gc/Tracer.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/TracingAPI.h"
|
||||
@ -229,4 +230,5 @@ const JSFunctionSpec BigIntObject::methods[] = {
|
||||
JS_FS_END};
|
||||
|
||||
const JSFunctionSpec BigIntObject::staticMethods[] = {
|
||||
JS_FN("asUintN", asUintN, 2, 0), JS_FN("asIntN", asIntN, 2, 0), JS_FS_END};
|
||||
JS_INLINABLE_FN("asUintN", asUintN, 2, 0, BigIntAsUintN),
|
||||
JS_INLINABLE_FN("asIntN", asIntN, 2, 0, BigIntAsIntN), JS_FS_END};
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "vm/BooleanObject-inl.h"
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
// Give a builtin constructor that we can use as the default. When we give
|
||||
// it to our newly made class, we will be sure to set it up with the correct name
|
||||
// and .prototype, so that everything works properly.
|
||||
|
||||
var DefaultDerivedClassConstructor =
|
||||
class extends null { constructor(...args) { super(...allowContentIter(args)); } };
|
||||
|
||||
var DefaultBaseClassConstructor =
|
||||
class { constructor() { } };
|
@ -24,6 +24,7 @@
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/Wrapper.h"
|
||||
#include "util/DifferentialTesting.h"
|
||||
#include "util/Windows.h"
|
||||
#include "vm/ArrayBufferObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
@ -72,14 +73,13 @@ bool DataViewObject::getAndCheckConstructorArgs(JSContext* cx,
|
||||
BufferSize* byteOffsetPtr,
|
||||
BufferSize* byteLengthPtr) {
|
||||
// Step 3.
|
||||
if (!IsArrayBufferMaybeShared(bufobj)) {
|
||||
if (!bufobj->is<ArrayBufferObjectMaybeShared>()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_EXPECTED_TYPE, "DataView",
|
||||
"ArrayBuffer", bufobj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
Rooted<ArrayBufferObjectMaybeShared*> buffer(
|
||||
cx, &AsArrayBufferMaybeShared(bufobj));
|
||||
auto buffer = bufobj.as<ArrayBufferObjectMaybeShared>();
|
||||
|
||||
// Step 4.
|
||||
uint64_t offset;
|
||||
@ -148,8 +148,7 @@ bool DataViewObject::constructSameCompartment(JSContext* cx,
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<ArrayBufferObjectMaybeShared*> buffer(
|
||||
cx, &AsArrayBufferMaybeShared(bufobj));
|
||||
auto buffer = bufobj.as<ArrayBufferObjectMaybeShared>();
|
||||
JSObject* obj =
|
||||
DataViewObject::create(cx, byteOffset, byteLength, buffer, proto);
|
||||
if (!obj) {
|
||||
@ -453,12 +452,10 @@ bool DataViewObject::write(JSContext* cx, Handle<DataViewObject*> obj,
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
// See the comment in ElementSpecific::doubleToNative.
|
||||
if (TypeIsFloatingPoint<NativeType>()) {
|
||||
if (js::SupportDifferentialTesting() && TypeIsFloatingPoint<NativeType>()) {
|
||||
value = JS::CanonicalizeNaN(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Step 6.
|
||||
bool isLittleEndian = args.length() >= 3 && ToBoolean(args[2]);
|
||||
@ -1026,8 +1023,7 @@ const JSPropertySpec DataViewObject::properties[] = {
|
||||
JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), JS_PS_END};
|
||||
|
||||
JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
|
||||
uint32_t byteOffset,
|
||||
int32_t byteLength) {
|
||||
size_t byteOffset, size_t byteLength) {
|
||||
JSProtoKey key = JSProto_DataView;
|
||||
RootedObject constructor(cx, GlobalObject::getOrCreateConstructor(cx, key));
|
||||
if (!constructor) {
|
||||
@ -1038,7 +1034,7 @@ JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
|
||||
|
||||
cargs[0].setObject(*buffer);
|
||||
cargs[1].setNumber(byteOffset);
|
||||
cargs[2].setInt32(byteLength);
|
||||
cargs[2].setNumber(byteLength);
|
||||
|
||||
RootedValue fun(cx, ObjectValue(*constructor));
|
||||
RootedObject obj(cx);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef vm_DataViewObject_h
|
||||
#define vm_DataViewObject_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
|
@ -78,8 +78,8 @@ function GetCachedFormat(format, required, defaults) {
|
||||
* Spec: ECMAScript Internationalization API Specification, 13.3.1.
|
||||
*/
|
||||
function Date_toLocaleString() {
|
||||
// Steps 1-2. Note that valueOf enforces "this time value" restrictions.
|
||||
var x = callFunction(std_Date_valueOf, this);
|
||||
// Steps 1-2.
|
||||
var x = callFunction(ThisTimeValue, this, DATE_METHOD_LOCALE_STRING);
|
||||
if (Number_isNaN(x))
|
||||
return "Invalid Date";
|
||||
|
||||
@ -111,8 +111,8 @@ function Date_toLocaleString() {
|
||||
* Spec: ECMAScript Internationalization API Specification, 13.3.2.
|
||||
*/
|
||||
function Date_toLocaleDateString() {
|
||||
// Steps 1-2. Note that valueOf enforces "this time value" restrictions.
|
||||
var x = callFunction(std_Date_valueOf, this);
|
||||
// Steps 1-2.
|
||||
var x = callFunction(ThisTimeValue, this, DATE_METHOD_LOCALE_DATE_STRING);
|
||||
if (Number_isNaN(x))
|
||||
return "Invalid Date";
|
||||
|
||||
@ -144,8 +144,8 @@ function Date_toLocaleDateString() {
|
||||
* Spec: ECMAScript Internationalization API Specification, 13.3.3.
|
||||
*/
|
||||
function Date_toLocaleTimeString() {
|
||||
// Steps 1-2. Note that valueOf enforces "this time value" restrictions.
|
||||
var x = callFunction(std_Date_valueOf, this);
|
||||
// Steps 1-2.
|
||||
var x = callFunction(ThisTimeValue, this, DATE_METHOD_LOCALE_TIME_STRING);
|
||||
if (Number_isNaN(x))
|
||||
return "Invalid Date";
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "frontend/BytecodeCompilation.h"
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "gc/HashUtil.h"
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
#include "js/friend/JSMEnvironment.h" // JS::NewJSMEnvironment, JS::ExecuteInJSMEnvironment, JS::GetJSMEnvironmentOfScriptedCaller, JS::IsJSMEnvironment
|
||||
@ -349,97 +348,6 @@ static bool EvalKernel(JSContext* cx, HandleValue v, EvalType evalType,
|
||||
NullFramePtr() /* evalInFrame */, vp);
|
||||
}
|
||||
|
||||
bool js::DirectEvalStringFromIon(JSContext* cx, HandleObject env,
|
||||
HandleScript callerScript,
|
||||
HandleValue newTargetValue, HandleString str,
|
||||
jsbytecode* pc, MutableHandleValue vp) {
|
||||
AssertInnerizedEnvironmentChain(cx, *env);
|
||||
|
||||
if (!GlobalObject::isRuntimeCodeGenEnabled(cx, str, cx->global())) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_CSP_BLOCKED_EVAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ES5 15.1.2.1 steps 2-8.
|
||||
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
|
||||
if (ejr != EvalJSONResult::NotJSON) {
|
||||
return ejr == EvalJSONResult::Success;
|
||||
}
|
||||
|
||||
EvalScriptGuard esg(cx);
|
||||
|
||||
esg.lookupInEvalCache(linearStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
const char* filename;
|
||||
unsigned lineno;
|
||||
bool mutedErrors;
|
||||
uint32_t pcOffset;
|
||||
DescribeScriptedCallerForDirectEval(cx, callerScript, pc, &filename,
|
||||
&lineno, &pcOffset, &mutedErrors);
|
||||
|
||||
const char* introducerFilename = filename;
|
||||
if (callerScript->scriptSource()->introducerFilename()) {
|
||||
introducerFilename = callerScript->scriptSource()->introducerFilename();
|
||||
}
|
||||
|
||||
RootedScope enclosing(cx, callerScript->innermostScope(pc));
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setIsRunOnce(true);
|
||||
options.setNoScriptRval(false);
|
||||
options.setMutedErrors(mutedErrors);
|
||||
|
||||
if (IsStrictEvalPC(pc)) {
|
||||
options.setForceStrictMode();
|
||||
}
|
||||
|
||||
if (introducerFilename) {
|
||||
options.setFileAndLine(filename, 1);
|
||||
options.setIntroductionInfo(introducerFilename, "eval", lineno,
|
||||
callerScript, pcOffset);
|
||||
} else {
|
||||
options.setFileAndLine("eval", 1);
|
||||
options.setIntroductionType("eval");
|
||||
}
|
||||
options.setNonSyntacticScope(
|
||||
enclosing->hasOnChain(ScopeKind::NonSyntactic));
|
||||
|
||||
AutoStableStringChars linearChars(cx);
|
||||
if (!linearChars.initTwoByte(cx, linearStr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceText<char16_t> srcBuf;
|
||||
|
||||
const char16_t* chars = linearChars.twoByteRange().begin().get();
|
||||
SourceOwnership ownership = linearChars.maybeGiveOwnershipToCaller()
|
||||
? SourceOwnership::TakeOwnership
|
||||
: SourceOwnership::Borrowed;
|
||||
if (!srcBuf.init(cx, chars, linearStr->length(), ownership)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSScript* script =
|
||||
frontend::CompileEvalScript(cx, options, srcBuf, enclosing, env);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
esg.setNewScript(script);
|
||||
}
|
||||
|
||||
return ExecuteKernel(cx, esg.script(), env, newTargetValue,
|
||||
NullFramePtr() /* evalInFrame */, vp);
|
||||
}
|
||||
|
||||
bool js::IndirectEval(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -480,7 +388,7 @@ static bool ExecuteInExtensibleLexicalEnvironment(JSContext* cx,
|
||||
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (script->realm() != cx->realm()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
script = CloneGlobalScript(cx, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
@ -16,19 +16,13 @@ namespace js {
|
||||
// JSOp::Eval which in turn calls DirectEval. Thus, even though IndirectEval is
|
||||
// the callee function object for *all* calls to eval, it is by construction
|
||||
// only ever called in the case indirect eval.
|
||||
extern MOZ_MUST_USE bool IndirectEval(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] extern bool IndirectEval(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Performs a direct eval of |v| (a string containing code, or another value
|
||||
// that will be vacuously returned), which must correspond to the currently-
|
||||
// executing stack frame, which must be a script frame.
|
||||
extern MOZ_MUST_USE bool DirectEval(JSContext* cx, HandleValue v,
|
||||
MutableHandleValue vp);
|
||||
|
||||
// Performs a direct eval called from Ion code.
|
||||
extern MOZ_MUST_USE bool DirectEvalStringFromIon(
|
||||
JSContext* cx, HandleObject scopeObj, HandleScript callerScript,
|
||||
HandleValue newTargetValue, HandleString str, jsbytecode* pc,
|
||||
MutableHandleValue vp);
|
||||
[[nodiscard]] extern bool DirectEval(JSContext* cx, HandleValue v,
|
||||
MutableHandleValue vp);
|
||||
|
||||
// True iff fun is a built-in eval function.
|
||||
extern bool IsAnyBuiltinEval(JSFunction* fun);
|
||||
|
@ -11,7 +11,8 @@
|
||||
#include "gc/Zone.h"
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
@ -3,14 +3,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Stream handler for operations that act on a target object, and possibly upon
|
||||
* Handler for operations that act on a target object, and possibly upon
|
||||
* an extra value.
|
||||
*/
|
||||
|
||||
#ifndef builtin_streams_HandlerFunction_inl_h
|
||||
#define builtin_streams_HandlerFunction_inl_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
#ifndef builtin_HandlerFunction_inl_h
|
||||
#define builtin_HandlerFunction_inl_h
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
@ -31,16 +29,15 @@ namespace js {
|
||||
// Handler functions are extended functions, that close over a target object and
|
||||
// (optionally) over an extra object, storing those objects in the function's
|
||||
// extended slots.
|
||||
constexpr size_t StreamHandlerFunctionSlot_Target = 0;
|
||||
constexpr size_t StreamHandlerFunctionSlot_Extra = 1;
|
||||
constexpr size_t HandlerFunctionSlot_Target = 0;
|
||||
constexpr size_t HandlerFunctionSlot_Extra = 1;
|
||||
|
||||
static_assert(StreamHandlerFunctionSlot_Extra <
|
||||
FunctionExtended::NUM_EXTENDED_SLOTS,
|
||||
static_assert(HandlerFunctionSlot_Extra < FunctionExtended::NUM_EXTENDED_SLOTS,
|
||||
"handler function slots shouldn't exceed available extended "
|
||||
"slots");
|
||||
|
||||
inline MOZ_MUST_USE JSFunction* NewHandler(JSContext* cx, Native handler,
|
||||
JS::Handle<JSObject*> target) {
|
||||
[[nodiscard]] inline JSFunction* NewHandler(JSContext* cx, Native handler,
|
||||
JS::Handle<JSObject*> target) {
|
||||
cx->check(target);
|
||||
|
||||
JS::Handle<PropertyName*> funName = cx->names().empty;
|
||||
@ -50,30 +47,30 @@ inline MOZ_MUST_USE JSFunction* NewHandler(JSContext* cx, Native handler,
|
||||
if (!handlerFun) {
|
||||
return nullptr;
|
||||
}
|
||||
handlerFun->setExtendedSlot(StreamHandlerFunctionSlot_Target,
|
||||
handlerFun->setExtendedSlot(HandlerFunctionSlot_Target,
|
||||
JS::ObjectValue(*target));
|
||||
return handlerFun;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE JSFunction* NewHandlerWithExtra(
|
||||
[[nodiscard]] inline JSFunction* NewHandlerWithExtra(
|
||||
JSContext* cx, Native handler, JS::Handle<JSObject*> target,
|
||||
JS::Handle<JSObject*> extra) {
|
||||
cx->check(extra);
|
||||
JSFunction* handlerFun = NewHandler(cx, handler, target);
|
||||
if (handlerFun) {
|
||||
handlerFun->setExtendedSlot(StreamHandlerFunctionSlot_Extra,
|
||||
handlerFun->setExtendedSlot(HandlerFunctionSlot_Extra,
|
||||
JS::ObjectValue(*extra));
|
||||
}
|
||||
return handlerFun;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE JSFunction* NewHandlerWithExtraValue(
|
||||
[[nodiscard]] inline JSFunction* NewHandlerWithExtraValue(
|
||||
JSContext* cx, Native handler, JS::Handle<JSObject*> target,
|
||||
JS::Handle<JS::Value> extra) {
|
||||
cx->check(extra);
|
||||
JSFunction* handlerFun = NewHandler(cx, handler, target);
|
||||
if (handlerFun) {
|
||||
handlerFun->setExtendedSlot(StreamHandlerFunctionSlot_Extra, extra);
|
||||
handlerFun->setExtendedSlot(HandlerFunctionSlot_Extra, extra);
|
||||
}
|
||||
return handlerFun;
|
||||
}
|
||||
@ -83,20 +80,18 @@ inline MOZ_MUST_USE JSFunction* NewHandlerWithExtraValue(
|
||||
* is always a |T*| object (and never a wrapper around one), return that |T*|.
|
||||
*/
|
||||
template <class T>
|
||||
inline MOZ_MUST_USE T* TargetFromHandler(const JS::CallArgs& args) {
|
||||
[[nodiscard]] inline T* TargetFromHandler(const JS::CallArgs& args) {
|
||||
JSFunction& func = args.callee().as<JSFunction>();
|
||||
return &func.getExtendedSlot(StreamHandlerFunctionSlot_Target)
|
||||
.toObject()
|
||||
.as<T>();
|
||||
return &func.getExtendedSlot(HandlerFunctionSlot_Target).toObject().as<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Within the call of a handler function that "closes over" a target value and
|
||||
* an extra value, return that extra value.
|
||||
*/
|
||||
inline MOZ_MUST_USE JS::Value ExtraValueFromHandler(const JS::CallArgs& args) {
|
||||
[[nodiscard]] inline JS::Value ExtraValueFromHandler(const JS::CallArgs& args) {
|
||||
JSFunction& func = args.callee().as<JSFunction>();
|
||||
return func.getExtendedSlot(StreamHandlerFunctionSlot_Extra);
|
||||
return func.getExtendedSlot(HandlerFunctionSlot_Extra);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,10 +100,10 @@ inline MOZ_MUST_USE JS::Value ExtraValueFromHandler(const JS::CallArgs& args) {
|
||||
* wrapper around one), return that |T*|.
|
||||
*/
|
||||
template <class T>
|
||||
inline MOZ_MUST_USE T* ExtraFromHandler(const JS::CallArgs& args) {
|
||||
[[nodiscard]] inline T* ExtraFromHandler(const JS::CallArgs& args) {
|
||||
return &ExtraValueFromHandler(args).toObject().as<T>();
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // builtin_streams_HandlerFunction_inl_h
|
||||
#endif // builtin_HandlerFunction_inl_h
|
@ -27,7 +27,8 @@
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/JSONParser.h"
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "builtin/Array-inl.h"
|
||||
#include "builtin/Boolean-inl.h"
|
||||
@ -1119,7 +1120,7 @@ static JSObject* CreateJSONObject(JSContext* cx, JSProtoKey key) {
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewSingletonObjectWithGivenProto(cx, &JSONClass, proto);
|
||||
return NewTenuredObjectWithGivenProto(cx, &JSONClass, proto);
|
||||
}
|
||||
|
||||
static const ClassSpec JSONClassSpec = {
|
||||
|
@ -330,8 +330,6 @@ bool MapIteratorObject::next(MapIteratorObject* mapIterator,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Note: we don't need to call setDenseElementWithType because
|
||||
// MapIteratorObject::createResultPair gave the elements unknown-types.
|
||||
switch (mapIterator->kind()) {
|
||||
case MapObject::Keys:
|
||||
resultPairObj->setDenseElement(0, range->front().key.get());
|
||||
@ -359,14 +357,6 @@ JSObject* MapIteratorObject::createResultPair(JSContext* cx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<TaggedProto> proto(cx, resultPairObj->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupRealm::makeGroup(
|
||||
cx, resultPairObj->realm(), resultPairObj->getClass(), proto);
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
resultPairObj->setGroup(group);
|
||||
|
||||
resultPairObj->setDenseInitializedLength(2);
|
||||
resultPairObj->initDenseElement(0, NullValue());
|
||||
resultPairObj->initDenseElement(1, NullValue());
|
||||
@ -544,8 +534,8 @@ class js::OrderedHashTableRef : public gc::BufferableRef {
|
||||
};
|
||||
|
||||
template <typename ObjectT>
|
||||
inline static MOZ_MUST_USE bool PostWriteBarrierImpl(ObjectT* obj,
|
||||
const Value& keyValue) {
|
||||
[[nodiscard]] inline static bool PostWriteBarrierImpl(ObjectT* obj,
|
||||
const Value& keyValue) {
|
||||
if (MOZ_LIKELY(!keyValue.isObject() && !keyValue.isBigInt())) {
|
||||
MOZ_ASSERT_IF(keyValue.isGCThing(), !IsInsideNursery(keyValue.toGCThing()));
|
||||
return true;
|
||||
@ -573,13 +563,13 @@ inline static MOZ_MUST_USE bool PostWriteBarrierImpl(ObjectT* obj,
|
||||
return keys->append(keyValue);
|
||||
}
|
||||
|
||||
inline static MOZ_MUST_USE bool PostWriteBarrier(MapObject* map,
|
||||
const Value& key) {
|
||||
[[nodiscard]] inline static bool PostWriteBarrier(MapObject* map,
|
||||
const Value& key) {
|
||||
return PostWriteBarrierImpl(map, key);
|
||||
}
|
||||
|
||||
inline static MOZ_MUST_USE bool PostWriteBarrier(SetObject* set,
|
||||
const Value& key) {
|
||||
[[nodiscard]] inline static bool PostWriteBarrier(SetObject* set,
|
||||
const Value& key) {
|
||||
return PostWriteBarrierImpl(set, key);
|
||||
}
|
||||
|
||||
@ -1128,8 +1118,6 @@ bool SetIteratorObject::next(SetIteratorObject* setIterator,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Note: we don't need to call setDenseElementWithType because
|
||||
// SetIteratorObject::createResult gave the elements unknown-types.
|
||||
resultObj->setDenseElement(0, range->front().get());
|
||||
range->popFront();
|
||||
return false;
|
||||
@ -1143,14 +1131,6 @@ JSObject* SetIteratorObject::createResult(JSContext* cx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<TaggedProto> proto(cx, resultObj->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupRealm::makeGroup(
|
||||
cx, resultObj->realm(), resultObj->getClass(), proto);
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
resultObj->setGroup(group);
|
||||
|
||||
resultObj->setDenseInitializedLength(1);
|
||||
resultObj->initDenseElement(0, NullValue());
|
||||
|
||||
|
@ -47,7 +47,7 @@ class HashableValue {
|
||||
|
||||
HashableValue() : value(UndefinedValue()) {}
|
||||
|
||||
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v);
|
||||
[[nodiscard]] bool setValue(JSContext* cx, HandleValue v);
|
||||
HashNumber hash(const mozilla::HashCodeScrambler& hcs) const;
|
||||
bool operator==(const HashableValue& other) const;
|
||||
HashableValue trace(JSTracer* trc) const;
|
||||
@ -69,7 +69,7 @@ template <typename Wrapper>
|
||||
class MutableWrappedPtrOperations<HashableValue, Wrapper>
|
||||
: public WrappedPtrOperations<HashableValue, Wrapper> {
|
||||
public:
|
||||
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v) {
|
||||
[[nodiscard]] bool setValue(JSContext* cx, HandleValue v) {
|
||||
return static_cast<Wrapper*>(this)->get().setValue(cx, v);
|
||||
}
|
||||
};
|
||||
@ -111,29 +111,29 @@ class MapObject : public NativeObject {
|
||||
|
||||
enum { NurseryKeysSlot, HasNurseryMemorySlot, SlotCount };
|
||||
|
||||
static MOZ_MUST_USE bool getKeysAndValuesInterleaved(
|
||||
[[nodiscard]] static bool getKeysAndValuesInterleaved(
|
||||
HandleObject obj, JS::MutableHandle<GCVector<JS::Value>> entries);
|
||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
|
||||
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static uint32_t size(JSContext* cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool get(JSContext* cx, HandleObject obj, HandleValue key,
|
||||
MutableHandleValue rval);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, HandleObject obj, HandleValue key,
|
||||
bool* rval);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
[[nodiscard]] static bool get(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, MutableHandleValue rval);
|
||||
[[nodiscard]] static bool has(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
[[nodiscard]] static bool delete_(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
|
||||
// Set call for public JSAPI exposure. Does not actually return map object
|
||||
// as stated in spec, expects caller to return a value. for instance, with
|
||||
// webidl maplike/setlike, should return interface object.
|
||||
static MOZ_MUST_USE bool set(JSContext* cx, HandleObject obj, HandleValue key,
|
||||
HandleValue val);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool iterator(JSContext* cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter);
|
||||
[[nodiscard]] static bool set(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, HandleValue val);
|
||||
[[nodiscard]] static bool clear(JSContext* cx, HandleObject obj);
|
||||
[[nodiscard]] static bool iterator(JSContext* cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter);
|
||||
|
||||
using UnbarrieredTable =
|
||||
OrderedHashMap<Value, Value, UnbarrieredHashPolicy, ZoneAllocPolicy>;
|
||||
@ -156,31 +156,31 @@ class MapObject : public NativeObject {
|
||||
static ValueMap& extract(const CallArgs& args);
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
static void finalize(JSFreeOp* fop, JSObject* obj);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool is(HandleValue v);
|
||||
static bool is(HandleObject o);
|
||||
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args,
|
||||
IteratorKind kind);
|
||||
[[nodiscard]] static bool iterator_impl(JSContext* cx, const CallArgs& args,
|
||||
IteratorKind kind);
|
||||
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class MapIteratorObject : public NativeObject {
|
||||
@ -211,8 +211,8 @@ class MapIteratorObject : public NativeObject {
|
||||
initFixedSlot(KindSlot, JS::Int32Value(int32_t(kind)));
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool next(MapIteratorObject* mapIterator,
|
||||
ArrayObject* resultPairObj);
|
||||
[[nodiscard]] static bool next(MapIteratorObject* mapIterator,
|
||||
ArrayObject* resultPairObj);
|
||||
|
||||
static JSObject* createResultPair(JSContext* cx);
|
||||
|
||||
@ -240,23 +240,23 @@ class SetObject : public NativeObject {
|
||||
|
||||
enum { NurseryKeysSlot, HasNurseryMemorySlot, SlotCount };
|
||||
|
||||
static MOZ_MUST_USE bool keys(JSContext* cx, HandleObject obj,
|
||||
JS::MutableHandle<GCVector<JS::Value>> keys);
|
||||
static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool add(JSContext* cx, HandleObject obj,
|
||||
HandleValue key);
|
||||
[[nodiscard]] static bool keys(JSContext* cx, HandleObject obj,
|
||||
JS::MutableHandle<GCVector<JS::Value>> keys);
|
||||
[[nodiscard]] static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool add(JSContext* cx, HandleObject obj,
|
||||
HandleValue key);
|
||||
|
||||
// Publicly exposed Set calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static SetObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
static uint32_t size(JSContext* cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, HandleObject obj, HandleValue key,
|
||||
bool* rval);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, HandleObject obj);
|
||||
static MOZ_MUST_USE bool iterator(JSContext* cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
[[nodiscard]] static bool has(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
[[nodiscard]] static bool clear(JSContext* cx, HandleObject obj);
|
||||
[[nodiscard]] static bool iterator(JSContext* cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter);
|
||||
[[nodiscard]] static bool delete_(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, bool* rval);
|
||||
|
||||
using UnbarrieredTable =
|
||||
OrderedHashSet<Value, UnbarrieredHashPolicy, ZoneAllocPolicy>;
|
||||
@ -286,22 +286,22 @@ class SetObject : public NativeObject {
|
||||
|
||||
static bool isBuiltinAdd(HandleValue add);
|
||||
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args,
|
||||
IteratorKind kind);
|
||||
[[nodiscard]] static bool iterator_impl(JSContext* cx, const CallArgs& args,
|
||||
IteratorKind kind);
|
||||
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool add_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool add(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool add_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class SetIteratorObject : public NativeObject {
|
||||
@ -332,8 +332,8 @@ class SetIteratorObject : public NativeObject {
|
||||
initFixedSlot(KindSlot, JS::Int32Value(int32_t(kind)));
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool next(SetIteratorObject* setIterator,
|
||||
ArrayObject* resultObj);
|
||||
[[nodiscard]] static bool next(SetIteratorObject* setIterator,
|
||||
ArrayObject* resultObj);
|
||||
|
||||
static JSObject* createResult(JSContext* cx);
|
||||
|
||||
@ -346,10 +346,10 @@ using SetInitGetPrototypeOp = NativeObject* (*)(JSContext*,
|
||||
using SetInitIsBuiltinOp = bool (*)(HandleValue);
|
||||
|
||||
template <SetInitGetPrototypeOp getPrototypeOp, SetInitIsBuiltinOp isBuiltinOp>
|
||||
static MOZ_MUST_USE bool IsOptimizableInitForSet(JSContext* cx,
|
||||
HandleObject setObject,
|
||||
HandleValue iterable,
|
||||
bool* optimized) {
|
||||
[[nodiscard]] static bool IsOptimizableInitForSet(JSContext* cx,
|
||||
HandleObject setObject,
|
||||
HandleValue iterable,
|
||||
bool* optimized) {
|
||||
MOZ_ASSERT(!*optimized);
|
||||
|
||||
if (!iterable.isObject()) {
|
||||
|
@ -100,6 +100,8 @@ function ModuleSetStatus(module, newStatus)
|
||||
//
|
||||
function ModuleResolveExport(exportName, resolveSet = [])
|
||||
{
|
||||
assert(typeof exportName === "string", "ModuleResolveExport");
|
||||
|
||||
if (!IsObject(this) || !IsModule(this)) {
|
||||
return callFunction(CallModuleMethodIfWrapped, this, exportName, resolveSet,
|
||||
"ModuleResolveExport");
|
||||
@ -135,7 +137,7 @@ function ModuleResolveExport(exportName, resolveSet = [])
|
||||
if (exportName === e.exportName) {
|
||||
let importedModule = CallModuleResolveHook(module, e.moduleRequest,
|
||||
MODULE_STATUS_UNLINKED);
|
||||
if (e.importName === "*") {
|
||||
if (e.importName === null) {
|
||||
return {module: importedModule, bindingName: "*namespace*"};
|
||||
}
|
||||
return callFunction(importedModule.resolveExport, importedModule, e.importName,
|
||||
@ -475,7 +477,7 @@ function InitializeEnvironment()
|
||||
let importedModule = CallModuleResolveHook(module, imp.moduleRequest,
|
||||
MODULE_STATUS_LINKING);
|
||||
// Step 9.c-9.d
|
||||
if (imp.importName === "*") {
|
||||
if (imp.importName === null) {
|
||||
let namespace = GetModuleNamespace(importedModule);
|
||||
CreateNamespaceBinding(env, imp.localName, namespace);
|
||||
} else {
|
||||
@ -574,6 +576,8 @@ function ModuleEvaluate()
|
||||
if (!IsObject(this) || !IsModule(this))
|
||||
return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluate");
|
||||
|
||||
const isTopLevelAwaitEnabled = IsTopLevelAwaitEnabled();
|
||||
|
||||
// Step 2
|
||||
let module = this;
|
||||
|
||||
@ -585,12 +589,37 @@ function ModuleEvaluate()
|
||||
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
|
||||
}
|
||||
|
||||
let capability = undefined;
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
// Top-level Await Step 4
|
||||
if (module.status === MODULE_STATUS_EVALUATED) {
|
||||
module = GetAsyncCycleRoot(module);
|
||||
}
|
||||
|
||||
// Top-level Await Step 5
|
||||
if (module.topLevelCapability) {
|
||||
return module.topLevelCapability;
|
||||
}
|
||||
|
||||
capability = CreateTopLevelCapability(module);
|
||||
}
|
||||
|
||||
// Step 4
|
||||
let stack = [];
|
||||
|
||||
// Steps 5-6
|
||||
try {
|
||||
InnerModuleEvaluation(module, stack, 0);
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
if (!module.asyncEvaluating) {
|
||||
ModuleTopLevelCapabilityResolve(module);
|
||||
}
|
||||
// Steps 7-8
|
||||
assert(module.status === MODULE_STATUS_EVALUATED,
|
||||
"Bad module status after successful evaluation");
|
||||
assert(stack.length === 0,
|
||||
"Stack should be empty after successful evaluation");
|
||||
}
|
||||
} catch (error) {
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
let m = stack[i];
|
||||
@ -606,23 +635,23 @@ function ModuleEvaluate()
|
||||
assert(module.status === MODULE_STATUS_EVALUATED_ERROR,
|
||||
"Bad module status after failed evaluation");
|
||||
|
||||
throw error;
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
ModuleTopLevelCapabilityReject(module, error);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 7-8
|
||||
assert(module.status === MODULE_STATUS_EVALUATED,
|
||||
"Bad module status after successful evaluation");
|
||||
assert(stack.length === 0,
|
||||
"Stack should be empty after successful evaluation");
|
||||
|
||||
// Step 9
|
||||
return undefined;
|
||||
return capability;
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#sec-innermoduleevaluation
|
||||
// ES2020 15.2.1.16.2.1 InnerModuleEvaluation
|
||||
function InnerModuleEvaluation(module, stack, index)
|
||||
{
|
||||
const isTopLevelAwaitEnabled = IsTopLevelAwaitEnabled();
|
||||
|
||||
// Step 1
|
||||
// TODO: Support module records other than Cyclic Module Records.
|
||||
|
||||
@ -647,6 +676,11 @@ function InnerModuleEvaluation(module, stack, index)
|
||||
// Steps 6-8
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_INDEX_SLOT, index);
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT, index);
|
||||
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_PENDING_ASYNC_DEPENDENCIES_SLOT, 0);
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
// Step 9
|
||||
@ -676,11 +710,41 @@ function InnerModuleEvaluation(module, stack, index)
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
|
||||
std_Math_min(module.dfsAncestorIndex,
|
||||
requiredModule.dfsAncestorIndex));
|
||||
} else {
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
requiredModule = GetAsyncCycleRoot(requiredModule);
|
||||
assert(requiredModule.status === MODULE_STATUS_EVALUATED,
|
||||
`Bad module status in InnerModuleEvaluation: ${requiredModule.status}`);
|
||||
if (requiredModule.evaluationError) {
|
||||
throw GetModuleEvaluationError(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
if (requiredModule.asyncEvaluating) {
|
||||
UnsafeSetReservedSlot(module,
|
||||
MODULE_OBJECT_PENDING_ASYNC_DEPENDENCIES_SLOT,
|
||||
module.pendingAsyncDependencies + 1);
|
||||
AppendAsyncParentModule(requiredModule, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 11
|
||||
ExecuteModule(module);
|
||||
if (isTopLevelAwaitEnabled) {
|
||||
if (module.pendingAsyncDependencies > 0) {
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_ASYNC_EVALUATING_SLOT, true);
|
||||
} else {
|
||||
if (module.async) {
|
||||
ExecuteAsyncModule(module);
|
||||
} else {
|
||||
// Step 11
|
||||
ExecuteModule(module);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Step 11
|
||||
ExecuteModule(module);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
assert(CountArrayValues(stack, module) === 1,
|
||||
@ -702,3 +766,16 @@ function InnerModuleEvaluation(module, stack, index)
|
||||
// Step 15
|
||||
return index;
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-execute-async-module
|
||||
function ExecuteAsyncModule(module) {
|
||||
// Steps 1-3.
|
||||
assert(module.status == MODULE_STATUS_EVALUATING ||
|
||||
module.status == MODULE_STATUS_EVALUATED, "bad status for async module");
|
||||
assert(module.async, "module is not async");
|
||||
UnsafeSetReservedSlot(module, MODULE_OBJECT_ASYNC_EVALUATING_SLOT, true);
|
||||
|
||||
// Step 4-11 done in AsyncAwait opcode
|
||||
|
||||
ExecuteModule(module);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,23 +5,45 @@
|
||||
#ifndef builtin_ModuleObject_h
|
||||
#define builtin_ModuleObject_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/HashTable.h" // mozilla::{HashMap, DefaultHasher}
|
||||
#include "mozilla/Maybe.h" // mozilla::Maybe
|
||||
|
||||
#include "jsapi.h"
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdint.h> // int32_t, uint32_t
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "frontend/Stencil.h"
|
||||
#include "gc/ZoneAllocator.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Id.h"
|
||||
#include "js/Modules.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
#include "builtin/SelfHostingDefines.h" // MODULE_OBJECT_*
|
||||
#include "gc/Barrier.h" // HeapPtr, PreBarrieredId
|
||||
#include "gc/Rooting.h" // HandleAtom, HandleArrayObject
|
||||
#include "gc/ZoneAllocator.h" // ZoneAllocPolicy
|
||||
#include "js/Class.h" // JSClass, ObjectOpResult
|
||||
#include "js/GCVector.h" // GCVector
|
||||
#include "js/Id.h" // jsid
|
||||
#include "js/Modules.h" // JS::DynamicImportStatus
|
||||
#include "js/PropertyDescriptor.h" // PropertyDescriptor
|
||||
#include "js/Proxy.h" // BaseProxyHandler
|
||||
#include "js/RootingAPI.h" // Rooted, Handle, MutableHandle
|
||||
#include "js/TypeDecls.h" // HandleValue, HandleId, HandleObject, HandleScript, MutableHandleValue, MutableHandleIdVector, MutableHandleObject
|
||||
#include "js/UniquePtr.h" // UniquePtr
|
||||
#include "js/Value.h" // JS::Value
|
||||
#include "vm/JSAtom.h" // JSAtom
|
||||
#include "vm/JSObject.h" // JSObject
|
||||
#include "vm/List.h" // ListObject
|
||||
#include "vm/NativeObject.h" // NativeObject
|
||||
#include "vm/PromiseObject.h" // js::PromiseObject
|
||||
#include "vm/ProxyObject.h" // ProxyObject
|
||||
#include "vm/Xdr.h" // XDRMode, XDRResult, XDRState
|
||||
|
||||
class JSFreeOp;
|
||||
class JSScript;
|
||||
class JSTracer;
|
||||
|
||||
namespace js {
|
||||
|
||||
class ArrayObject;
|
||||
class Shape;
|
||||
class Scope;
|
||||
class ScriptSourceObject;
|
||||
|
||||
class ModuleEnvironmentObject;
|
||||
class ModuleObject;
|
||||
|
||||
@ -44,8 +66,9 @@ class ImportEntryObject : public NativeObject {
|
||||
static const JSClass class_;
|
||||
static bool isInstance(HandleValue value);
|
||||
static ImportEntryObject* create(JSContext* cx, HandleAtom moduleRequest,
|
||||
HandleAtom importName, HandleAtom localName,
|
||||
uint32_t lineNumber, uint32_t columnNumber);
|
||||
HandleAtom maybeImportName,
|
||||
HandleAtom localName, uint32_t lineNumber,
|
||||
uint32_t columnNumber);
|
||||
JSAtom* moduleRequest() const;
|
||||
JSAtom* importName() const;
|
||||
JSAtom* localName() const;
|
||||
@ -152,8 +175,9 @@ class IndirectBindingMap {
|
||||
HeapPtr<Shape*> shape;
|
||||
};
|
||||
|
||||
using Map = HashMap<PreBarrieredId, Binding, DefaultHasher<PreBarrieredId>,
|
||||
ZoneAllocPolicy>;
|
||||
using Map =
|
||||
mozilla::HashMap<PreBarrieredId, Binding,
|
||||
mozilla::DefaultHasher<PreBarrieredId>, ZoneAllocPolicy>;
|
||||
|
||||
mozilla::Maybe<Map> map_;
|
||||
};
|
||||
@ -246,6 +270,11 @@ class ModuleObject : public NativeObject {
|
||||
FunctionDeclarationsSlot,
|
||||
DFSIndexSlot,
|
||||
DFSAncestorIndexSlot,
|
||||
AsyncSlot,
|
||||
AsyncEvaluatingSlot,
|
||||
TopLevelCapabilitySlot,
|
||||
AsyncParentModulesSlot,
|
||||
PendingAsyncDependenciesSlot,
|
||||
SlotCount
|
||||
};
|
||||
|
||||
@ -259,6 +288,14 @@ class ModuleObject : public NativeObject {
|
||||
"DFSIndexSlot must match self-hosting define");
|
||||
static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
|
||||
"DFSAncestorIndexSlot must match self-hosting define");
|
||||
static_assert(AsyncEvaluatingSlot == MODULE_OBJECT_ASYNC_EVALUATING_SLOT,
|
||||
"AsyncEvaluatingSlot must match self-hosting define");
|
||||
static_assert(TopLevelCapabilitySlot ==
|
||||
MODULE_OBJECT_TOP_LEVEL_CAPABILITY_SLOT,
|
||||
"topLevelCapabilitySlot must match self-hosting define");
|
||||
static_assert(PendingAsyncDependenciesSlot ==
|
||||
MODULE_OBJECT_PENDING_ASYNC_DEPENDENCIES_SLOT,
|
||||
"PendingAsyncDependenciesSlot must match self-hosting define");
|
||||
|
||||
static const JSClass class_;
|
||||
|
||||
@ -291,6 +328,8 @@ class ModuleObject : public NativeObject {
|
||||
ModuleEnvironmentObject* environment() const;
|
||||
ModuleNamespaceObject* namespace_();
|
||||
ModuleStatus status() const;
|
||||
uint32_t dfsIndex() const;
|
||||
uint32_t dfsAncestorIndex() const;
|
||||
bool hadEvaluationError() const;
|
||||
Value evaluationError() const;
|
||||
JSObject* metaObject() const;
|
||||
@ -302,8 +341,33 @@ class ModuleObject : public NativeObject {
|
||||
ArrayObject& starExportEntries() const;
|
||||
IndirectBindingMap& importBindings();
|
||||
|
||||
static PromiseObject* createTopLevelCapability(JSContext* cx,
|
||||
HandleModuleObject module);
|
||||
bool isAsync() const;
|
||||
void setAsync(bool isAsync);
|
||||
bool isAsyncEvaluating() const;
|
||||
void setAsyncEvaluating(bool isEvaluating);
|
||||
void setEvaluationError(HandleValue newValue);
|
||||
void setPendingAsyncDependencies(uint32_t newValue);
|
||||
void setInitialTopLevelCapability(HandleObject promiseObj);
|
||||
bool hasTopLevelCapability() const;
|
||||
JSObject* topLevelCapability() const;
|
||||
ListObject* asyncParentModules() const;
|
||||
uint32_t pendingAsyncDependencies() const;
|
||||
|
||||
static bool appendAsyncParentModule(JSContext* cx, HandleModuleObject self,
|
||||
HandleModuleObject parent);
|
||||
|
||||
static bool topLevelCapabilityResolve(JSContext* cx,
|
||||
HandleModuleObject module);
|
||||
static bool topLevelCapabilityReject(JSContext* cx, HandleModuleObject module,
|
||||
HandleValue error);
|
||||
|
||||
static bool Instantiate(JSContext* cx, HandleModuleObject self);
|
||||
static bool Evaluate(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
// Start evaluating the module. If TLA is enabled, rval will be a promise
|
||||
static bool Evaluate(JSContext* cx, HandleModuleObject self,
|
||||
MutableHandleValue rval);
|
||||
|
||||
static ModuleNamespaceObject* GetOrCreateModuleNamespace(
|
||||
JSContext* cx, HandleModuleObject self);
|
||||
@ -325,8 +389,11 @@ class ModuleObject : public NativeObject {
|
||||
|
||||
static bool createEnvironment(JSContext* cx, HandleModuleObject self);
|
||||
|
||||
frontend::FunctionDeclarationVector* functionDeclarations();
|
||||
void initFunctionDeclarations(frontend::FunctionDeclarationVector&& decls);
|
||||
bool initAsyncSlots(JSContext* cx, bool isAsync,
|
||||
HandleObject asyncParentModulesList);
|
||||
|
||||
// NOTE: accessor for FunctionDeclarationsSlot is defined inside
|
||||
// ModuleObject.cpp as static function.
|
||||
|
||||
private:
|
||||
static const JSClassOps classOps_;
|
||||
@ -342,13 +409,41 @@ JSObject* GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
|
||||
JSObject* CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate,
|
||||
HandleString specifier);
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-getasynccycleroot
|
||||
ModuleObject* GetAsyncCycleRoot(ModuleObject* module);
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-asyncmodulexecutionfulfilled
|
||||
void AsyncModuleExecutionFulfilled(JSContext* cx, HandleModuleObject module);
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-asyncmodulexecutionrejected
|
||||
void AsyncModuleExecutionRejected(JSContext* cx, HandleModuleObject module,
|
||||
HandleValue error);
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-asyncmodulexecutionfulfilled
|
||||
bool AsyncModuleExecutionFulfilledHandler(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
// https://tc39.es/proposal-top-level-await/#sec-asyncmodulexecutionrejected
|
||||
bool AsyncModuleExecutionRejectedHandler(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
JSObject* StartDynamicModuleImport(JSContext* cx, HandleScript script,
|
||||
HandleValue specifier);
|
||||
|
||||
bool FinishDynamicModuleImport(JSContext* cx, JS::DynamicImportStatus status,
|
||||
bool OnModuleEvaluationFailure(JSContext* cx, HandleObject evaluationPromise);
|
||||
|
||||
bool FinishDynamicModuleImport(JSContext* cx, HandleObject evaluationPromise,
|
||||
HandleValue referencingPrivate,
|
||||
HandleString specifier, HandleObject promise);
|
||||
|
||||
// This is used so that Top Level Await functionality can be turned off
|
||||
// entirely. It will be removed in bug#1676612.
|
||||
bool FinishDynamicModuleImport_NoTLA(JSContext* cx,
|
||||
JS::DynamicImportStatus status,
|
||||
HandleValue referencingPrivate,
|
||||
HandleString specifier,
|
||||
HandleObject promise);
|
||||
|
||||
template <XDRMode mode>
|
||||
XDRResult XDRModuleObject(XDRState<mode>* xdr, MutableHandleModuleObject modp);
|
||||
|
||||
|
@ -53,57 +53,41 @@ function Number_isNaN(num) {
|
||||
return num !== num;
|
||||
}
|
||||
|
||||
// ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54
|
||||
// ES2021 draft rev 889f2f30cf554b7ed812c0984626db1c8a4997c7
|
||||
// 20.1.2.3 Number.isInteger ( number )
|
||||
function Number_isInteger(number) {
|
||||
// Step 1.
|
||||
// Step 1. (Inlined call to IsIntegralNumber)
|
||||
|
||||
// 7.2.6 IsIntegralNumber, step 1.
|
||||
if (typeof number !== "number")
|
||||
return false;
|
||||
|
||||
// -(2**31) is an int32, but abs(-(2**31)) isn't. Avoid bailouts below by
|
||||
// special casing it here.
|
||||
if (number === -(2 ** 31))
|
||||
return true;
|
||||
var integer = std_Math_trunc(number);
|
||||
|
||||
// Step 3.
|
||||
// Note: We're using abs + floor instead ceil to workaround bug 1379626.
|
||||
var absNumber = std_Math_abs(number);
|
||||
var integer = std_Math_floor(absNumber);
|
||||
|
||||
// Steps 2, 4.
|
||||
if (absNumber - integer !== 0)
|
||||
return false;
|
||||
|
||||
// Step 5.
|
||||
return true;
|
||||
// 7.2.6 IsIntegralNumber, steps 2-4.
|
||||
// |number - integer| ensures Infinity correctly returns false, because
|
||||
// |Infinity - Infinity| yields NaN.
|
||||
return number - integer === 0;
|
||||
}
|
||||
|
||||
// ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54
|
||||
// ES2021 draft rev 889f2f30cf554b7ed812c0984626db1c8a4997c7
|
||||
// 20.1.2.5 Number.isSafeInteger ( number )
|
||||
function Number_isSafeInteger(number) {
|
||||
// Step 1.
|
||||
// Step 1. (Inlined call to IsIntegralNumber)
|
||||
|
||||
// 7.2.6 IsIntegralNumber, step 1.
|
||||
if (typeof number !== "number")
|
||||
return false;
|
||||
|
||||
// -(2**31) is an int32, but abs(-(2**31)) isn't. Avoid bailouts below by
|
||||
// special casing it here.
|
||||
if (number === -(2 ** 31))
|
||||
return true;
|
||||
var integer = std_Math_trunc(number);
|
||||
|
||||
// Step 3.
|
||||
var absNumber = std_Math_abs(number);
|
||||
var integer = std_Math_floor(absNumber);
|
||||
|
||||
// Steps 2, 4.
|
||||
if (absNumber - integer !== 0)
|
||||
// 7.2.6 IsIntegralNumber, steps 2-4.
|
||||
// |number - integer| to handle the Infinity case correctly.
|
||||
if (number - integer !== 0)
|
||||
return false;
|
||||
|
||||
// Step 5.
|
||||
if (integer <= (2 ** 53) - 1)
|
||||
return true;
|
||||
|
||||
// Step 6.
|
||||
return false;
|
||||
// Steps 1.a, 2.
|
||||
return -((2 ** 53) - 1) <= integer && integer <= (2 ** 53) - 1;
|
||||
}
|
||||
|
||||
function Global_isNaN(number) {
|
||||
|
@ -32,7 +32,8 @@
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/StringObject.h"
|
||||
#include "vm/ToSource.h" // js::ValueToSource
|
||||
#include "vm/ToSource.h" // js::ValueToSource
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
@ -93,8 +94,9 @@ bool js::obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
/* Step 3. */
|
||||
PropertyResult prop;
|
||||
if (obj->isNative() && NativeLookupOwnProperty<NoGC>(
|
||||
cx, &obj->as<NativeObject>(), id, &prop)) {
|
||||
if (obj->is<NativeObject>() &&
|
||||
NativeLookupOwnProperty<NoGC>(cx, &obj->as<NativeObject>(), id,
|
||||
&prop)) {
|
||||
/* Step 4. */
|
||||
if (!prop) {
|
||||
args.rval().setBoolean(false);
|
||||
@ -493,59 +495,48 @@ JSString* js::ObjectToSource(JSContext* cx, HandleObject obj) {
|
||||
return buf.finishString();
|
||||
}
|
||||
|
||||
static bool GetBuiltinTagSlow(JSContext* cx, HandleObject obj,
|
||||
MutableHandleString builtinTag) {
|
||||
static JSString* GetBuiltinTagSlow(JSContext* cx, HandleObject obj) {
|
||||
// Step 4.
|
||||
bool isArray;
|
||||
if (!IsArray(cx, obj, &isArray)) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
if (isArray) {
|
||||
builtinTag.set(cx->names().objectArray);
|
||||
return true;
|
||||
return cx->names().objectArray;
|
||||
}
|
||||
|
||||
// Steps 6-13.
|
||||
// Steps 6-14.
|
||||
ESClass cls;
|
||||
if (!JS::GetBuiltinClass(cx, obj, &cls)) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (cls) {
|
||||
case ESClass::String:
|
||||
builtinTag.set(cx->names().objectString);
|
||||
return true;
|
||||
return cx->names().objectString;
|
||||
case ESClass::Arguments:
|
||||
builtinTag.set(cx->names().objectArguments);
|
||||
return true;
|
||||
return cx->names().objectArguments;
|
||||
case ESClass::Error:
|
||||
builtinTag.set(cx->names().objectError);
|
||||
return true;
|
||||
return cx->names().objectError;
|
||||
case ESClass::Boolean:
|
||||
builtinTag.set(cx->names().objectBoolean);
|
||||
return true;
|
||||
return cx->names().objectBoolean;
|
||||
case ESClass::Number:
|
||||
builtinTag.set(cx->names().objectNumber);
|
||||
return true;
|
||||
return cx->names().objectNumber;
|
||||
case ESClass::Date:
|
||||
builtinTag.set(cx->names().objectDate);
|
||||
return true;
|
||||
return cx->names().objectDate;
|
||||
case ESClass::RegExp:
|
||||
builtinTag.set(cx->names().objectRegExp);
|
||||
return true;
|
||||
return cx->names().objectRegExp;
|
||||
default:
|
||||
if (obj->isCallable()) {
|
||||
// Non-standard: Prevent <object> from showing up as Function.
|
||||
RootedObject unwrapped(cx, CheckedUnwrapDynamic(obj, cx));
|
||||
JSObject* unwrapped = CheckedUnwrapDynamic(obj, cx);
|
||||
if (!unwrapped || !unwrapped->getClass()->isDOMClass()) {
|
||||
builtinTag.set(cx->names().objectFunction);
|
||||
return true;
|
||||
return cx->names().objectFunction;
|
||||
}
|
||||
}
|
||||
builtinTag.set(nullptr);
|
||||
return true;
|
||||
return cx->names().objectObject;
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,12 +544,11 @@ static MOZ_ALWAYS_INLINE JSString* GetBuiltinTagFast(JSObject* obj,
|
||||
const JSClass* clasp,
|
||||
JSContext* cx) {
|
||||
MOZ_ASSERT(clasp == obj->getClass());
|
||||
MOZ_ASSERT(!clasp->isProxy());
|
||||
MOZ_ASSERT(!clasp->isProxyObject());
|
||||
|
||||
// Optimize the non-proxy case to bypass GetBuiltinClass.
|
||||
if (clasp == &PlainObject::class_) {
|
||||
// This is not handled by GetBuiltinTagSlow, but this case is by far
|
||||
// the most common so we optimize it here.
|
||||
// This case is by far the most common so we handle it first.
|
||||
return cx->names().objectObject;
|
||||
}
|
||||
|
||||
@ -603,7 +593,7 @@ static MOZ_ALWAYS_INLINE JSString* GetBuiltinTagFast(JSObject* obj,
|
||||
return cx->names().objectFunction;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return cx->names().objectObject;
|
||||
}
|
||||
|
||||
// For primitive values we try to avoid allocating the object if we can
|
||||
@ -679,33 +669,14 @@ bool js::obj_toString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
obj = &args.thisv().toObject();
|
||||
}
|
||||
|
||||
// When |obj| is a non-proxy object, compute |builtinTag| only when needed.
|
||||
RootedString builtinTag(cx);
|
||||
const JSClass* clasp = obj->getClass();
|
||||
if (MOZ_UNLIKELY(clasp->isProxy())) {
|
||||
if (!GetBuiltinTagSlow(cx, obj, &builtinTag)) {
|
||||
if (MOZ_UNLIKELY(clasp->isProxyObject())) {
|
||||
builtinTag = GetBuiltinTagSlow(cx, obj);
|
||||
if (!builtinTag) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
builtinTag = GetBuiltinTagFast(obj, clasp, cx);
|
||||
#ifdef DEBUG
|
||||
// Assert this fast path is correct and matches BuiltinTagSlow. The
|
||||
// only exception is the PlainObject case: we special-case it here
|
||||
// because it's so common, but BuiltinTagSlow doesn't handle this.
|
||||
RootedString builtinTagSlow(cx);
|
||||
if (!GetBuiltinTagSlow(cx, obj, &builtinTagSlow)) {
|
||||
return false;
|
||||
}
|
||||
if (clasp == &PlainObject::class_) {
|
||||
MOZ_ASSERT(!builtinTagSlow);
|
||||
} else {
|
||||
MOZ_ASSERT(builtinTagSlow == builtinTag);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Step 14.
|
||||
if (!builtinTag) {
|
||||
builtinTag = cx->names().objectObject;
|
||||
}
|
||||
|
||||
// Step 15.
|
||||
@ -717,6 +688,18 @@ bool js::obj_toString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
// Step 16.
|
||||
if (!tag.isString()) {
|
||||
if (!builtinTag) {
|
||||
builtinTag = GetBuiltinTagFast(obj, clasp, cx);
|
||||
#ifdef DEBUG
|
||||
// Assert this fast path is correct and matches BuiltinTagSlow.
|
||||
JSString* builtinTagSlow = GetBuiltinTagSlow(cx, obj);
|
||||
if (!builtinTagSlow) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(builtinTagSlow == builtinTag);
|
||||
#endif
|
||||
}
|
||||
|
||||
args.rval().setString(builtinTag);
|
||||
return true;
|
||||
}
|
||||
@ -736,21 +719,14 @@ bool js::obj_toString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString* js::ObjectClassToString(JSContext* cx, HandleObject obj) {
|
||||
const JSClass* clasp = obj->getClass();
|
||||
JSString* js::ObjectClassToString(JSContext* cx, JSObject* obj) {
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
if (JSString* tag = GetBuiltinTagFast(obj, clasp, cx)) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
const char* className = clasp->name;
|
||||
StringBuffer sb(cx);
|
||||
if (!sb.append("[object ") || !sb.append(className, strlen(className)) ||
|
||||
!sb.append(']')) {
|
||||
if (MaybeHasInterestingSymbolProperty(cx, obj,
|
||||
cx->wellKnownSymbols().toStringTag)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sb.finishAtom();
|
||||
return GetBuiltinTagFast(obj, obj->getClass(), cx);
|
||||
}
|
||||
|
||||
static bool obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
@ -798,7 +774,7 @@ static bool obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
static bool PropertyIsEnumerable(JSContext* cx, HandleObject obj, HandleId id,
|
||||
bool* enumerable) {
|
||||
PropertyResult prop;
|
||||
if (obj->isNative() &&
|
||||
if (obj->is<NativeObject>() &&
|
||||
NativeLookupOwnProperty<NoGC>(cx, &obj->as<NativeObject>(), id, &prop)) {
|
||||
if (!prop) {
|
||||
*enumerable = false;
|
||||
@ -823,7 +799,7 @@ static bool TryAssignNative(JSContext* cx, HandleObject to, HandleObject from,
|
||||
bool* optimized) {
|
||||
*optimized = false;
|
||||
|
||||
if (!from->isNative() || !to->isNative()) {
|
||||
if (!from->is<NativeObject>() || !to->is<NativeObject>()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -868,7 +844,7 @@ static bool TryAssignNative(JSContext* cx, HandleObject to, HandleObject from,
|
||||
|
||||
// Ensure |from| is still native: a getter/setter might have been swapped
|
||||
// with a non-native object.
|
||||
if (MOZ_LIKELY(from->isNative() &&
|
||||
if (MOZ_LIKELY(from->is<NativeObject>() &&
|
||||
from->as<NativeObject>().lastProperty() == fromShape &&
|
||||
shape->isDataProperty())) {
|
||||
if (!shape->enumerable()) {
|
||||
@ -993,7 +969,7 @@ static bool obj_assign(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* ES5 15.2.4.6. */
|
||||
static bool obj_isPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
bool js::obj_isPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Step 1. */
|
||||
@ -1018,30 +994,10 @@ static bool obj_isPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
PlainObject* js::ObjectCreateImpl(JSContext* cx, HandleObject proto,
|
||||
NewObjectKind newKind,
|
||||
HandleObjectGroup group) {
|
||||
NewObjectKind newKind) {
|
||||
// Give the new object a small number of fixed slots, like we do for empty
|
||||
// object literals ({}).
|
||||
gc::AllocKind allocKind = GuessObjectGCKind(0);
|
||||
|
||||
if (!proto) {
|
||||
// Object.create(null) is common, optimize it by using an allocation
|
||||
// site specific ObjectGroup. Because GetCallerInitGroup is pretty
|
||||
// slow, the caller can pass in the group if it's known and we use that
|
||||
// instead.
|
||||
RootedObjectGroup ngroup(cx, group);
|
||||
if (!ngroup) {
|
||||
ngroup = ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Null);
|
||||
if (!ngroup) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!ngroup->proto().toObjectOrNull());
|
||||
|
||||
return NewObjectWithGroup<PlainObject>(cx, ngroup, allocKind, newKind);
|
||||
}
|
||||
|
||||
return NewObjectWithGivenProtoAndKinds<PlainObject>(cx, proto, allocKind,
|
||||
newKind);
|
||||
}
|
||||
@ -1049,8 +1005,7 @@ PlainObject* js::ObjectCreateImpl(JSContext* cx, HandleObject proto,
|
||||
PlainObject* js::ObjectCreateWithTemplate(JSContext* cx,
|
||||
HandlePlainObject templateObj) {
|
||||
RootedObject proto(cx, templateObj->staticPrototype());
|
||||
RootedObjectGroup group(cx, templateObj->group());
|
||||
return ObjectCreateImpl(cx, proto, GenericObject, group);
|
||||
return ObjectCreateImpl(cx, proto, GenericObject);
|
||||
}
|
||||
|
||||
// ES 2017 draft 19.1.2.3.1
|
||||
@ -1309,7 +1264,7 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj,
|
||||
// they're only marked as indexed after their enumerate hook ran. And
|
||||
// because their enumerate hook is slowish, it's more performant to
|
||||
// exclude them directly instead of executing the hook first.
|
||||
if (!obj->isNative() || obj->as<NativeObject>().isIndexed() ||
|
||||
if (!obj->is<NativeObject>() || obj->as<NativeObject>().isIndexed() ||
|
||||
obj->getClass()->getNewEnumerate() || obj->is<StringObject>()) {
|
||||
return true;
|
||||
}
|
||||
@ -1371,7 +1326,7 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj,
|
||||
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
Handle<TypedArrayObject*> tobj = obj.as<TypedArrayObject>();
|
||||
uint32_t len = tobj->length().deprecatedGetUint32();
|
||||
size_t len = tobj->length().get();
|
||||
|
||||
// Fail early if the typed array contains too many elements for a
|
||||
// dense array, because we likely OOM anyway when trying to allocate
|
||||
@ -1421,7 +1376,7 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj,
|
||||
|
||||
// Up to this point no side-effects through accessor properties are
|
||||
// possible which could have replaced |obj| with a non-native object.
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(obj->is<NativeObject>());
|
||||
|
||||
if (kind == EnumerableOwnPropertiesKind::Keys ||
|
||||
kind == EnumerableOwnPropertiesKind::Names ||
|
||||
@ -1507,7 +1462,7 @@ static bool TryEnumerableOwnPropertiesNative(JSContext* cx, HandleObject obj,
|
||||
|
||||
// Ensure |obj| is still native: a getter might have been swapped with a
|
||||
// non-native object.
|
||||
if (obj->isNative() &&
|
||||
if (obj->is<NativeObject>() &&
|
||||
obj->as<NativeObject>().lastProperty() == objShape &&
|
||||
shape->isDataProperty()) {
|
||||
if (!shape->enumerable()) {
|
||||
@ -1761,7 +1716,7 @@ bool js::GetOwnPropertyKeys(JSContext* cx, HandleObject obj, unsigned flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
array->ensureDenseInitializedLength(cx, 0, keys.length());
|
||||
array->ensureDenseInitializedLength(0, keys.length());
|
||||
|
||||
RootedValue val(cx);
|
||||
for (size_t i = 0, len = keys.length(); i < len; i++) {
|
||||
@ -2015,7 +1970,7 @@ static JSObject* CreateObjectConstructor(JSContext* cx, JSProtoKey key) {
|
||||
/* Create the Object function now that we have a [[Prototype]] for it. */
|
||||
JSFunction* fun = NewNativeConstructor(
|
||||
cx, obj_construct, 1, HandlePropertyName(cx->names().Object),
|
||||
gc::AllocKind::FUNCTION, SingletonObject);
|
||||
gc::AllocKind::FUNCTION, TenuredObject);
|
||||
if (!fun) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2026,14 +1981,14 @@ static JSObject* CreateObjectConstructor(JSContext* cx, JSProtoKey key) {
|
||||
|
||||
static JSObject* CreateObjectPrototype(JSContext* cx, JSProtoKey key) {
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
MOZ_ASSERT(cx->global()->isNative());
|
||||
MOZ_ASSERT(cx->global()->is<NativeObject>());
|
||||
|
||||
/*
|
||||
* Create |Object.prototype| first, mirroring CreateBlankProto but for the
|
||||
* prototype of the created object.
|
||||
*/
|
||||
RootedPlainObject objectProto(
|
||||
cx, NewSingletonObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
cx, NewTenuredObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
if (!objectProto) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2087,7 +2042,7 @@ static bool FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor,
|
||||
*/
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
if (global->shouldSplicePrototype()) {
|
||||
if (!JSObject::splicePrototype(cx, global, tagged)) {
|
||||
if (!GlobalObject::splicePrototype(cx, global, tagged)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -15,44 +15,45 @@ namespace js {
|
||||
class PlainObject;
|
||||
|
||||
// Object constructor native. Exposed only so the JIT can know its address.
|
||||
MOZ_MUST_USE bool obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
[[nodiscard]] bool obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
PlainObject* ObjectCreateImpl(JSContext* cx, HandleObject proto,
|
||||
NewObjectKind newKind = GenericObject,
|
||||
HandleObjectGroup group = nullptr);
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
PlainObject* ObjectCreateWithTemplate(JSContext* cx,
|
||||
Handle<PlainObject*> templateObj);
|
||||
|
||||
// Object methods exposed so they can be installed in the self-hosting global.
|
||||
MOZ_MUST_USE bool obj_propertyIsEnumerable(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] bool obj_propertyIsEnumerable(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool obj_create(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
[[nodiscard]] bool obj_isPrototypeOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool obj_is(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
[[nodiscard]] bool obj_create(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool obj_toString(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
[[nodiscard]] bool obj_is(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool obj_setProto(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
[[nodiscard]] bool obj_toString(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
JSString* ObjectClassToString(JSContext* cx, HandleObject obj);
|
||||
[[nodiscard]] bool obj_setProto(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool GetOwnPropertyKeys(JSContext* cx, HandleObject obj,
|
||||
unsigned flags,
|
||||
JS::MutableHandleValue rval);
|
||||
JSString* ObjectClassToString(JSContext* cx, JSObject* obj);
|
||||
|
||||
[[nodiscard]] bool GetOwnPropertyKeys(JSContext* cx, HandleObject obj,
|
||||
unsigned flags,
|
||||
JS::MutableHandleValue rval);
|
||||
|
||||
// Exposed for SelfHosting.cpp
|
||||
MOZ_MUST_USE bool GetOwnPropertyDescriptorToArray(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] bool GetOwnPropertyDescriptorToArray(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
|
||||
/*
|
||||
* Like IdToValue, but convert int jsids to strings. This is used when
|
||||
* exposing a jsid to script for Object.getOwnProperty{Names,Symbols}
|
||||
* or scriptable proxy traps.
|
||||
*/
|
||||
MOZ_MUST_USE bool IdToStringOrSymbol(JSContext* cx, JS::HandleId id,
|
||||
JS::MutableHandleValue result);
|
||||
[[nodiscard]] bool IdToStringOrSymbol(JSContext* cx, JS::HandleId id,
|
||||
JS::MutableHandleValue result);
|
||||
|
||||
// Object.prototype.toSource. Function.prototype.toSource and uneval use this.
|
||||
JSString* ObjectToSource(JSContext* cx, JS::HandleObject obj);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef MOZ_CALLGRIND
|
||||
@ -36,8 +37,6 @@
|
||||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
|
||||
/* Thread-unsafe error management */
|
||||
|
||||
static char gLastError[2000];
|
||||
@ -500,7 +499,7 @@ bool js_StartPerf() {
|
||||
mainPidStr, "--output", outfile};
|
||||
|
||||
Vector<const char*, 0, SystemAllocPolicy> args;
|
||||
if (!args.append(defaultArgs, ArrayLength(defaultArgs))) {
|
||||
if (!args.append(defaultArgs, std::size(defaultArgs))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -27,35 +27,35 @@ typedef int pid_t;
|
||||
*
|
||||
* Returns true if no profilers fail to start.
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool JS_StartProfiling(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool JS_StartProfiling(
|
||||
const char* profileName, pid_t pid);
|
||||
|
||||
/**
|
||||
* Stop any profilers that were previously started with JS_StartProfiling.
|
||||
* Returns true if no profilers fail to stop.
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool JS_StopProfiling(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool JS_StopProfiling(
|
||||
const char* profileName);
|
||||
|
||||
/**
|
||||
* Write the current profile data to the given file, if applicable to whatever
|
||||
* profiler is being used.
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool JS_DumpProfile(const char* outfile,
|
||||
const char* profileName);
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool JS_DumpProfile(const char* outfile,
|
||||
const char* profileName);
|
||||
|
||||
/**
|
||||
* Pause currently active profilers (only supported by some profilers). Returns
|
||||
* whether any profilers failed to pause. (Profilers that do not support
|
||||
* pause/resume do not count.)
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool JS_PauseProfilers(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool JS_PauseProfilers(
|
||||
const char* profileName);
|
||||
|
||||
/**
|
||||
* Resume suspended profilers
|
||||
*/
|
||||
extern MOZ_MUST_USE JS_PUBLIC_API bool JS_ResumeProfilers(
|
||||
[[nodiscard]] extern JS_PUBLIC_API bool JS_ResumeProfilers(
|
||||
const char* profileName);
|
||||
|
||||
/**
|
||||
@ -67,19 +67,19 @@ JS_PUBLIC_API const char* JS_UnsafeGetLastProfilingError();
|
||||
|
||||
#ifdef MOZ_CALLGRIND
|
||||
|
||||
extern MOZ_MUST_USE JS_FRIEND_API bool js_StopCallgrind();
|
||||
[[nodiscard]] extern JS_FRIEND_API bool js_StopCallgrind();
|
||||
|
||||
extern MOZ_MUST_USE JS_FRIEND_API bool js_StartCallgrind();
|
||||
[[nodiscard]] extern JS_FRIEND_API bool js_StartCallgrind();
|
||||
|
||||
extern MOZ_MUST_USE JS_FRIEND_API bool js_DumpCallgrind(const char* outfile);
|
||||
[[nodiscard]] extern JS_FRIEND_API bool js_DumpCallgrind(const char* outfile);
|
||||
|
||||
#endif /* MOZ_CALLGRIND */
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
extern MOZ_MUST_USE JS_FRIEND_API bool js_StartPerf();
|
||||
[[nodiscard]] extern JS_FRIEND_API bool js_StartPerf();
|
||||
|
||||
extern MOZ_MUST_USE JS_FRIEND_API bool js_StopPerf();
|
||||
[[nodiscard]] extern JS_FRIEND_API bool js_StopPerf();
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
|
@ -316,7 +316,7 @@ class MutableWrappedPtrOperations<PromiseCombinatorElements, Wrapper>
|
||||
elements().setElementNeedsWrapping = needsWrapping;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool pushUndefined(JSContext* cx) {
|
||||
[[nodiscard]] bool pushUndefined(JSContext* cx) {
|
||||
// Helper for the AutoRealm we need to work with |array|. We mostly do this
|
||||
// for performance; we could go ahead and do the define via a cross-
|
||||
// compartment proxy instead...
|
||||
@ -340,7 +340,8 @@ class MutableWrappedPtrOperations<PromiseCombinatorElements, Wrapper>
|
||||
// Promise.all/allSettled/any function, which isn't necessarily the same
|
||||
// compartment as unwrappedArray as explained in NewPromiseCombinatorElements.
|
||||
// So before storing |val| we may need to enter unwrappedArray's compartment.
|
||||
MOZ_MUST_USE bool setElement(JSContext* cx, uint32_t index, HandleValue val) {
|
||||
[[nodiscard]] bool setElement(JSContext* cx, uint32_t index,
|
||||
HandleValue val) {
|
||||
// The index is guaranteed to be initialized to `undefined`.
|
||||
MOZ_ASSERT(unwrappedArray()->getDenseElement(index).isUndefined());
|
||||
|
||||
@ -585,7 +586,7 @@ static bool MaybeGetAndClearExceptionAndStack(JSContext* cx,
|
||||
return GetAndClearExceptionAndStack(cx, rval, stack);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool RunRejectFunction(
|
||||
[[nodiscard]] static bool RunRejectFunction(
|
||||
JSContext* cx, HandleObject onRejectedFunc, HandleValue result,
|
||||
HandleObject promiseObj, HandleSavedFrame unwrappedRejectionStack,
|
||||
UnhandledRejectionBehavior behavior);
|
||||
@ -862,7 +863,7 @@ static bool ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool RejectPromiseFunction(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// ES2016, 25.4.1.3.
|
||||
static MOZ_MUST_USE MOZ_ALWAYS_INLINE bool CreateResolvingFunctions(
|
||||
[[nodiscard]] static MOZ_ALWAYS_INLINE bool CreateResolvingFunctions(
|
||||
JSContext* cx, HandleObject promise, MutableHandleObject resolveFn,
|
||||
MutableHandleObject rejectFn) {
|
||||
HandlePropertyName funName = cx->names().empty;
|
||||
@ -912,12 +913,12 @@ static bool IsSettledMaybeWrappedPromise(JSObject* promise) {
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.7.
|
||||
static MOZ_MUST_USE bool RejectMaybeWrappedPromise(
|
||||
[[nodiscard]] static bool RejectMaybeWrappedPromise(
|
||||
JSContext* cx, HandleObject promiseObj, HandleValue reason,
|
||||
HandleSavedFrame unwrappedRejectionStack);
|
||||
|
||||
// ES2016, 25.4.1.7.
|
||||
static MOZ_MUST_USE bool RejectPromiseInternal(
|
||||
[[nodiscard]] static bool RejectPromiseInternal(
|
||||
JSContext* cx, Handle<PromiseObject*> promise, HandleValue reason,
|
||||
HandleSavedFrame unwrappedRejectionStack = nullptr);
|
||||
|
||||
@ -964,15 +965,15 @@ static bool RejectPromiseFunction(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool FulfillMaybeWrappedPromise(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleValue value_);
|
||||
[[nodiscard]] static bool FulfillMaybeWrappedPromise(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleValue value_);
|
||||
|
||||
static MOZ_MUST_USE bool EnqueuePromiseResolveThenableJob(
|
||||
[[nodiscard]] static bool EnqueuePromiseResolveThenableJob(
|
||||
JSContext* cx, HandleValue promiseToResolve, HandleValue thenable,
|
||||
HandleValue thenVal);
|
||||
|
||||
static MOZ_MUST_USE bool EnqueuePromiseResolveThenableBuiltinJob(
|
||||
[[nodiscard]] static bool EnqueuePromiseResolveThenableBuiltinJob(
|
||||
JSContext* cx, HandleObject promiseToResolve, HandleObject thenable);
|
||||
|
||||
static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal,
|
||||
@ -980,9 +981,9 @@ static bool Promise_then_impl(JSContext* cx, HandleValue promiseVal,
|
||||
MutableHandleValue rval, bool rvalUsed);
|
||||
|
||||
// ES2016, 25.4.1.3.2, steps 6-13.
|
||||
static MOZ_MUST_USE bool ResolvePromiseInternal(JSContext* cx,
|
||||
HandleObject promise,
|
||||
HandleValue resolutionVal) {
|
||||
[[nodiscard]] static bool ResolvePromiseInternal(JSContext* cx,
|
||||
HandleObject promise,
|
||||
HandleValue resolutionVal) {
|
||||
cx->check(promise, resolutionVal);
|
||||
MOZ_ASSERT(!IsSettledMaybeWrappedPromise(promise));
|
||||
|
||||
@ -1124,7 +1125,7 @@ static bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp);
|
||||
* targetState - The PromiseState this reaction job targets. This decides
|
||||
* whether the onFulfilled or onRejected handler is called.
|
||||
*/
|
||||
MOZ_MUST_USE static bool EnqueuePromiseReactionJob(
|
||||
[[nodiscard]] static bool EnqueuePromiseReactionJob(
|
||||
JSContext* cx, HandleObject reactionObj, HandleValue handlerArg_,
|
||||
JS::PromiseState targetState) {
|
||||
MOZ_ASSERT(targetState == JS::PromiseState::Fulfilled ||
|
||||
@ -1257,10 +1258,10 @@ MOZ_MUST_USE static bool EnqueuePromiseReactionJob(
|
||||
return cx->runtime()->enqueuePromiseJob(cx, job, promise, global);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool TriggerPromiseReactions(JSContext* cx,
|
||||
HandleValue reactionsVal,
|
||||
JS::PromiseState state,
|
||||
HandleValue valueOrReason);
|
||||
[[nodiscard]] static bool TriggerPromiseReactions(JSContext* cx,
|
||||
HandleValue reactionsVal,
|
||||
JS::PromiseState state,
|
||||
HandleValue valueOrReason);
|
||||
|
||||
// ES2016, Commoned-out implementation of 25.4.1.4. and 25.4.1.7.
|
||||
//
|
||||
@ -1268,7 +1269,7 @@ static MOZ_MUST_USE bool TriggerPromiseReactions(JSContext* cx,
|
||||
// which is only used for debugging purposes.
|
||||
// It allows callers to to pass in the stack of some exception which
|
||||
// triggered the rejection of the promise.
|
||||
static MOZ_MUST_USE bool ResolvePromise(
|
||||
[[nodiscard]] static bool ResolvePromise(
|
||||
JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueOrReason,
|
||||
JS::PromiseState state,
|
||||
HandleSavedFrame unwrappedRejectionStack = nullptr) {
|
||||
@ -1311,7 +1312,7 @@ static MOZ_MUST_USE bool ResolvePromise(
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.7.
|
||||
static MOZ_MUST_USE bool RejectPromiseInternal(
|
||||
[[nodiscard]] static bool RejectPromiseInternal(
|
||||
JSContext* cx, Handle<PromiseObject*> promise, HandleValue reason,
|
||||
HandleSavedFrame unwrappedRejectionStack) {
|
||||
return ResolvePromise(cx, promise, reason, JS::PromiseState::Rejected,
|
||||
@ -1319,9 +1320,9 @@ static MOZ_MUST_USE bool RejectPromiseInternal(
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.4.
|
||||
static MOZ_MUST_USE bool FulfillMaybeWrappedPromise(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleValue value_) {
|
||||
[[nodiscard]] static bool FulfillMaybeWrappedPromise(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleValue value_) {
|
||||
Rooted<PromiseObject*> promise(cx);
|
||||
RootedValue value(cx, value_);
|
||||
|
||||
@ -1347,7 +1348,7 @@ static MOZ_MUST_USE bool FulfillMaybeWrappedPromise(JSContext* cx,
|
||||
|
||||
static bool GetCapabilitiesExecutor(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool PromiseConstructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE PromiseObject* CreatePromiseObjectInternal(
|
||||
[[nodiscard]] static PromiseObject* CreatePromiseObjectInternal(
|
||||
JSContext* cx, HandleObject proto = nullptr, bool protoIsWrapped = false,
|
||||
bool informDebugger = true);
|
||||
|
||||
@ -1356,7 +1357,7 @@ enum GetCapabilitiesExecutorSlots {
|
||||
GetCapabilitiesExecutorSlots_Reject
|
||||
};
|
||||
|
||||
static MOZ_MUST_USE PromiseObject*
|
||||
[[nodiscard]] static PromiseObject*
|
||||
CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx) {
|
||||
PromiseObject* promise = CreatePromiseObjectInternal(cx);
|
||||
if (!promise) {
|
||||
@ -1367,7 +1368,7 @@ CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE PromiseObject* CreatePromiseWithDefaultResolutionFunctions(
|
||||
[[nodiscard]] static PromiseObject* CreatePromiseWithDefaultResolutionFunctions(
|
||||
JSContext* cx, MutableHandleObject resolve, MutableHandleObject reject) {
|
||||
// ES2016, 25.4.3.1., as if called with GetCapabilitiesExecutor as the
|
||||
// executor argument.
|
||||
@ -1394,7 +1395,7 @@ static MOZ_MUST_USE PromiseObject* CreatePromiseWithDefaultResolutionFunctions(
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.5.
|
||||
static MOZ_MUST_USE bool NewPromiseCapability(
|
||||
[[nodiscard]] static bool NewPromiseCapability(
|
||||
JSContext* cx, HandleObject C, MutableHandle<PromiseCapability> capability,
|
||||
bool canOmitResolutionFunctions) {
|
||||
RootedValue cVal(cx, ObjectValue(*C));
|
||||
@ -1509,7 +1510,7 @@ static bool GetCapabilitiesExecutor(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.7.
|
||||
static MOZ_MUST_USE bool RejectMaybeWrappedPromise(
|
||||
[[nodiscard]] static bool RejectMaybeWrappedPromise(
|
||||
JSContext* cx, HandleObject promiseObj, HandleValue reason_,
|
||||
HandleSavedFrame unwrappedRejectionStack) {
|
||||
Rooted<PromiseObject*> promise(cx);
|
||||
@ -1608,10 +1609,10 @@ static bool ForEachReaction(JSContext* cx, HandleValue reactionsVal, F f) {
|
||||
}
|
||||
|
||||
// ES2016, 25.4.1.8.
|
||||
static MOZ_MUST_USE bool TriggerPromiseReactions(JSContext* cx,
|
||||
HandleValue reactionsVal,
|
||||
JS::PromiseState state,
|
||||
HandleValue valueOrReason) {
|
||||
[[nodiscard]] static bool TriggerPromiseReactions(JSContext* cx,
|
||||
HandleValue reactionsVal,
|
||||
JS::PromiseState state,
|
||||
HandleValue valueOrReason) {
|
||||
MOZ_ASSERT(state == JS::PromiseState::Fulfilled ||
|
||||
state == JS::PromiseState::Rejected);
|
||||
|
||||
@ -1620,15 +1621,15 @@ static MOZ_MUST_USE bool TriggerPromiseReactions(JSContext* cx,
|
||||
});
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool RunFulfillFunction(JSContext* cx,
|
||||
HandleObject onFulfilledFunc,
|
||||
HandleValue result,
|
||||
HandleObject promiseObj);
|
||||
[[nodiscard]] static bool RunFulfillFunction(JSContext* cx,
|
||||
HandleObject onFulfilledFunc,
|
||||
HandleValue result,
|
||||
HandleObject promiseObj);
|
||||
|
||||
// Implements PromiseReactionJob optimized for the case when the reaction
|
||||
// handler is one of the default resolving functions as created by the
|
||||
// CreateResolvingFunctions abstract operation.
|
||||
static MOZ_MUST_USE bool DefaultResolvingPromiseReactionJob(
|
||||
[[nodiscard]] static bool DefaultResolvingPromiseReactionJob(
|
||||
JSContext* cx, Handle<PromiseReactionRecord*> reaction) {
|
||||
MOZ_ASSERT(reaction->targetState() != JS::PromiseState::Pending);
|
||||
|
||||
@ -1680,7 +1681,7 @@ static MOZ_MUST_USE bool DefaultResolvingPromiseReactionJob(
|
||||
reaction->unhandledRejectionBehavior());
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool AsyncFunctionPromiseReactionJob(
|
||||
[[nodiscard]] static bool AsyncFunctionPromiseReactionJob(
|
||||
JSContext* cx, Handle<PromiseReactionRecord*> reaction) {
|
||||
MOZ_ASSERT(reaction->isAsyncFunction());
|
||||
|
||||
@ -1700,7 +1701,7 @@ static MOZ_MUST_USE bool AsyncFunctionPromiseReactionJob(
|
||||
return AsyncFunctionAwaitedRejected(cx, generator, argument);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool AsyncGeneratorPromiseReactionJob(
|
||||
[[nodiscard]] static bool AsyncGeneratorPromiseReactionJob(
|
||||
JSContext* cx, Handle<PromiseReactionRecord*> reaction) {
|
||||
MOZ_ASSERT(reaction->isAsyncGenerator());
|
||||
|
||||
@ -1984,7 +1985,7 @@ static bool PromiseResolveThenableJob(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return Call(cx, rejectVal, UndefinedHandleValue, rval, &rval);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool OriginalPromiseThenWithoutSettleHandlers(
|
||||
[[nodiscard]] static bool OriginalPromiseThenWithoutSettleHandlers(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseObject*> promiseToResolve);
|
||||
|
||||
@ -2050,7 +2051,7 @@ static bool PromiseResolveBuiltinThenableJob(JSContext* cx, unsigned argc,
|
||||
* thenable_ - The thenable to resolve the Promise with.
|
||||
* thenVal - The `then` function to invoke with the `thenable` as the receiver.
|
||||
*/
|
||||
static MOZ_MUST_USE bool EnqueuePromiseResolveThenableJob(
|
||||
[[nodiscard]] static bool EnqueuePromiseResolveThenableJob(
|
||||
JSContext* cx, HandleValue promiseToResolve_, HandleValue thenable_,
|
||||
HandleValue thenVal) {
|
||||
// Need to re-root these to enable wrapping them below.
|
||||
@ -2118,7 +2119,7 @@ static MOZ_MUST_USE bool EnqueuePromiseResolveThenableJob(
|
||||
* promiseToResolve - The promise to resolve, obviously.
|
||||
* thenable - The thenable to resolve the Promise with.
|
||||
*/
|
||||
static MOZ_MUST_USE bool EnqueuePromiseResolveThenableBuiltinJob(
|
||||
[[nodiscard]] static bool EnqueuePromiseResolveThenableBuiltinJob(
|
||||
JSContext* cx, HandleObject promiseToResolve, HandleObject thenable) {
|
||||
cx->check(promiseToResolve, thenable);
|
||||
MOZ_ASSERT(promiseToResolve->is<PromiseObject>());
|
||||
@ -2143,11 +2144,11 @@ static MOZ_MUST_USE bool EnqueuePromiseResolveThenableBuiltinJob(
|
||||
incumbentGlobal);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool AddDummyPromiseReactionForDebugger(
|
||||
[[nodiscard]] static bool AddDummyPromiseReactionForDebugger(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
HandleObject dependentPromise);
|
||||
|
||||
static MOZ_MUST_USE bool AddPromiseReaction(
|
||||
[[nodiscard]] static bool AddPromiseReaction(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseReactionRecord*> reaction);
|
||||
|
||||
@ -2222,7 +2223,7 @@ static void ClearResolutionFunctionSlots(JSFunction* resolutionFun) {
|
||||
}
|
||||
|
||||
// ES2016, 25.4.3.1. steps 3-7.
|
||||
static MOZ_MUST_USE MOZ_ALWAYS_INLINE PromiseObject*
|
||||
[[nodiscard]] static MOZ_ALWAYS_INLINE PromiseObject*
|
||||
CreatePromiseObjectInternal(JSContext* cx, HandleObject proto /* = nullptr */,
|
||||
bool protoIsWrapped /* = false */,
|
||||
bool informDebugger /* = true */) {
|
||||
@ -2484,22 +2485,22 @@ class MOZ_STACK_CLASS PromiseForOfIterator : public JS::ForOfIterator {
|
||||
}
|
||||
};
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseAll(
|
||||
[[nodiscard]] static bool PerformPromiseAll(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done);
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseAllSettled(
|
||||
[[nodiscard]] static bool PerformPromiseAllSettled(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done);
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseAny(
|
||||
[[nodiscard]] static bool PerformPromiseAny(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done);
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseRace(
|
||||
[[nodiscard]] static bool PerformPromiseRace(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done);
|
||||
@ -2517,8 +2518,8 @@ enum class CombinatorKind { All, AllSettled, Any, Race };
|
||||
// https://tc39.es/proposal-promise-any/
|
||||
//
|
||||
// Promise.any ( iterable )
|
||||
static MOZ_MUST_USE bool CommonPromiseCombinator(JSContext* cx, CallArgs& args,
|
||||
CombinatorKind kind) {
|
||||
[[nodiscard]] static bool CommonPromiseCombinator(JSContext* cx, CallArgs& args,
|
||||
CombinatorKind kind) {
|
||||
HandleValue iterable = args.get(0);
|
||||
|
||||
// Step 2 (moved from NewPromiseCapability, step 1).
|
||||
@ -2651,11 +2652,11 @@ static bool Promise_static_all(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return CommonPromiseCombinator(cx, args, CombinatorKind::All);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseThen(
|
||||
[[nodiscard]] static bool PerformPromiseThen(
|
||||
JSContext* cx, Handle<PromiseObject*> promise, HandleValue onFulfilled_,
|
||||
HandleValue onRejected_, Handle<PromiseCapability> resultCapability);
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseThenWithoutSettleHandlers(
|
||||
[[nodiscard]] static bool PerformPromiseThenWithoutSettleHandlers(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseObject*> promiseToResolve,
|
||||
Handle<PromiseCapability> resultCapability);
|
||||
@ -2668,7 +2669,7 @@ static bool PromiseAllResolveElementFunction(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
// Unforgeable version of ES2016, 25.4.4.1.
|
||||
MOZ_MUST_USE JSObject* js::GetWaitForAllPromise(
|
||||
[[nodiscard]] JSObject* js::GetWaitForAllPromise(
|
||||
JSContext* cx, JS::HandleObjectVector promises) {
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0, len = promises.length(); i < len; i++) {
|
||||
@ -2709,7 +2710,7 @@ MOZ_MUST_USE JSObject* js::GetWaitForAllPromise(
|
||||
if (!valuesArray) {
|
||||
return nullptr;
|
||||
}
|
||||
valuesArray->ensureDenseInitializedLength(cx, 0, promiseCount);
|
||||
valuesArray->ensureDenseInitializedLength(0, promiseCount);
|
||||
|
||||
values.initialize(valuesArray);
|
||||
}
|
||||
@ -2794,10 +2795,10 @@ MOZ_MUST_USE JSObject* js::GetWaitForAllPromise(
|
||||
return resultCapability.promise();
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool RunFulfillFunction(JSContext* cx,
|
||||
HandleObject onFulfilledFunc,
|
||||
HandleValue result,
|
||||
HandleObject promiseObj) {
|
||||
[[nodiscard]] static bool RunFulfillFunction(JSContext* cx,
|
||||
HandleObject onFulfilledFunc,
|
||||
HandleValue result,
|
||||
HandleObject promiseObj) {
|
||||
cx->check(onFulfilledFunc);
|
||||
cx->check(result);
|
||||
cx->check(promiseObj);
|
||||
@ -2828,7 +2829,7 @@ static MOZ_MUST_USE bool RunFulfillFunction(JSContext* cx,
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool RunRejectFunction(
|
||||
[[nodiscard]] static bool RunRejectFunction(
|
||||
JSContext* cx, HandleObject onRejectedFunc, HandleValue result,
|
||||
HandleObject promiseObj, HandleSavedFrame unwrappedRejectionStack,
|
||||
UnhandledRejectionBehavior behavior) {
|
||||
@ -2877,7 +2878,7 @@ static MOZ_MUST_USE bool RunRejectFunction(
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE JSObject* CommonStaticResolveRejectImpl(
|
||||
[[nodiscard]] static JSObject* CommonStaticResolveRejectImpl(
|
||||
JSContext* cx, HandleValue thisVal, HandleValue argVal,
|
||||
ResolutionMode mode);
|
||||
|
||||
@ -2892,7 +2893,7 @@ static bool IsPromiseSpecies(JSContext* cx, JSFunction* species);
|
||||
// https://tc39.es/proposal-promise-any/
|
||||
// Runtime Semantics: PerformPromiseAny, steps 6-8.
|
||||
template <typename T>
|
||||
static MOZ_MUST_USE bool CommonPerformPromiseCombinator(
|
||||
[[nodiscard]] static bool CommonPerformPromiseCombinator(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
HandleObject resultPromise, HandleValue promiseResolve, bool* done,
|
||||
bool resolveReturnsUndefined, T getResolveAndReject) {
|
||||
@ -3175,7 +3176,7 @@ static MOZ_MUST_USE bool CommonPerformPromiseCombinator(
|
||||
|
||||
// Create the elements for the Promise combinators Promise.all and
|
||||
// Promise.allSettled.
|
||||
static MOZ_MUST_USE bool NewPromiseCombinatorElements(
|
||||
[[nodiscard]] static bool NewPromiseCombinatorElements(
|
||||
JSContext* cx, Handle<PromiseCapability> resultCapability,
|
||||
MutableHandle<PromiseCombinatorElements> elements) {
|
||||
// We have to be very careful about which compartments we create things for
|
||||
@ -3227,7 +3228,7 @@ static MOZ_MUST_USE bool NewPromiseCombinatorElements(
|
||||
}
|
||||
|
||||
// Retrieve the combinator elements from the data holder.
|
||||
static MOZ_MUST_USE bool GetPromiseCombinatorElements(
|
||||
[[nodiscard]] static bool GetPromiseCombinatorElements(
|
||||
JSContext* cx, Handle<PromiseCombinatorDataHolder*> data,
|
||||
MutableHandle<PromiseCombinatorElements> elements) {
|
||||
bool needsWrapping = false;
|
||||
@ -3308,7 +3309,7 @@ static bool PromiseCombinatorElementFunctionAlreadyCalled(
|
||||
|
||||
// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
|
||||
// 25.6.4.1.1 PerformPromiseAll (iteratorRecord, constructor, resultCapability)
|
||||
static MOZ_MUST_USE bool PerformPromiseAll(
|
||||
[[nodiscard]] static bool PerformPromiseAll(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done) {
|
||||
@ -3445,7 +3446,7 @@ static bool Promise_static_race(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
|
||||
// 25.6.4.3.1 PerformPromiseRace (iteratorRecord, constructor, resultCapability)
|
||||
static MOZ_MUST_USE bool PerformPromiseRace(
|
||||
[[nodiscard]] static bool PerformPromiseRace(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done) {
|
||||
@ -3500,7 +3501,7 @@ static bool Promise_static_allSettled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
// 25.6.4.2 Promise.allSettled ( iterable )
|
||||
//
|
||||
// PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability )
|
||||
static MOZ_MUST_USE bool PerformPromiseAllSettled(
|
||||
[[nodiscard]] static bool PerformPromiseAllSettled(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done) {
|
||||
@ -3711,7 +3712,7 @@ static void ThrowAggregateError(JSContext* cx,
|
||||
// https://tc39.es/proposal-promise-any/
|
||||
//
|
||||
// PerformPromiseAny ( iteratorRecord, constructor, resultCapability )
|
||||
static MOZ_MUST_USE bool PerformPromiseAny(
|
||||
[[nodiscard]] static bool PerformPromiseAny(
|
||||
JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
|
||||
Handle<PromiseCapability> resultCapability, HandleValue promiseResolve,
|
||||
bool* done) {
|
||||
@ -3917,7 +3918,7 @@ static void ThrowAggregateError(JSContext* cx,
|
||||
// 25.6.4.4 Promise.reject ( r )
|
||||
// 25.6.4.5 Promise.resolve ( x )
|
||||
// 25.6.4.5.1 PromiseResolve ( C, x )
|
||||
static MOZ_MUST_USE JSObject* CommonStaticResolveRejectImpl(
|
||||
[[nodiscard]] static JSObject* CommonStaticResolveRejectImpl(
|
||||
JSContext* cx, HandleValue thisVal, HandleValue argVal,
|
||||
ResolutionMode mode) {
|
||||
// Steps 1-2 of Promise.reject and Promise.resolve.
|
||||
@ -3994,9 +3995,9 @@ static MOZ_MUST_USE JSObject* CommonStaticResolveRejectImpl(
|
||||
return promise;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE JSObject* js::PromiseResolve(JSContext* cx,
|
||||
HandleObject constructor,
|
||||
HandleValue value) {
|
||||
[[nodiscard]] JSObject* js::PromiseResolve(JSContext* cx,
|
||||
HandleObject constructor,
|
||||
HandleValue value) {
|
||||
RootedValue C(cx, ObjectValue(*constructor));
|
||||
return CommonStaticResolveRejectImpl(cx, C, value, ResolveMode);
|
||||
}
|
||||
@ -4284,10 +4285,10 @@ static bool PromiseThenNewPromiseCapability(
|
||||
}
|
||||
|
||||
// ES2016, 25.4.5.3., steps 3-5.
|
||||
MOZ_MUST_USE PromiseObject* js::OriginalPromiseThen(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleObject onFulfilled,
|
||||
HandleObject onRejected) {
|
||||
[[nodiscard]] PromiseObject* js::OriginalPromiseThen(JSContext* cx,
|
||||
HandleObject promiseObj,
|
||||
HandleObject onFulfilled,
|
||||
HandleObject onRejected) {
|
||||
cx->check(promiseObj);
|
||||
cx->check(onFulfilled);
|
||||
cx->check(onRejected);
|
||||
@ -4328,7 +4329,7 @@ MOZ_MUST_USE PromiseObject* js::OriginalPromiseThen(JSContext* cx,
|
||||
return newPromise;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool OriginalPromiseThenWithoutSettleHandlers(
|
||||
[[nodiscard]] static bool OriginalPromiseThenWithoutSettleHandlers(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseObject*> promiseToResolve) {
|
||||
cx->check(promise);
|
||||
@ -4346,11 +4347,11 @@ static MOZ_MUST_USE bool OriginalPromiseThenWithoutSettleHandlers(
|
||||
resultCapability);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseThenWithReaction(
|
||||
[[nodiscard]] static bool PerformPromiseThenWithReaction(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseReactionRecord*> reaction);
|
||||
|
||||
MOZ_MUST_USE bool js::ReactToUnwrappedPromise(
|
||||
[[nodiscard]] bool js::ReactToUnwrappedPromise(
|
||||
JSContext* cx, Handle<PromiseObject*> unwrappedPromise,
|
||||
HandleObject onFulfilled_, HandleObject onRejected_,
|
||||
UnhandledRejectionBehavior behavior) {
|
||||
@ -4430,7 +4431,7 @@ static bool OriginalPromiseThenBuiltin(JSContext* cx, HandleValue promiseVal,
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool js::RejectPromiseWithPendingError(
|
||||
[[nodiscard]] bool js::RejectPromiseWithPendingError(
|
||||
JSContext* cx, Handle<PromiseObject*> promise) {
|
||||
cx->check(promise);
|
||||
|
||||
@ -4451,7 +4452,7 @@ MOZ_MUST_USE bool js::RejectPromiseWithPendingError(
|
||||
// js/src/builtin/AsyncFunction.cpp, to call Promise internal functions.
|
||||
|
||||
// ES 2018 draft 14.6.11 and 14.7.14 step 1.
|
||||
MOZ_MUST_USE PromiseObject* js::CreatePromiseObjectForAsync(JSContext* cx) {
|
||||
[[nodiscard]] PromiseObject* js::CreatePromiseObjectForAsync(JSContext* cx) {
|
||||
// Step 1.
|
||||
PromiseObject* promise = CreatePromiseObjectWithoutResolutionFunctions(cx);
|
||||
if (!promise) {
|
||||
@ -4467,7 +4468,7 @@ bool js::IsPromiseForAsyncFunctionOrGenerator(JSObject* promise) {
|
||||
PromiseHasAnyFlag(promise->as<PromiseObject>(), PROMISE_FLAG_ASYNC);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE PromiseObject* CreatePromiseObjectForAsyncGenerator(
|
||||
[[nodiscard]] static PromiseObject* CreatePromiseObjectForAsyncGenerator(
|
||||
JSContext* cx) {
|
||||
PromiseObject* promise = CreatePromiseObjectWithoutResolutionFunctions(cx);
|
||||
if (!promise) {
|
||||
@ -4480,9 +4481,9 @@ static MOZ_MUST_USE PromiseObject* CreatePromiseObjectForAsyncGenerator(
|
||||
|
||||
// ES2019 draft rev 7428c89bef626548084cd4e697a19ece7168f24c
|
||||
// 25.7.5.1 AsyncFunctionStart, steps 3.f-g.
|
||||
MOZ_MUST_USE bool js::AsyncFunctionThrown(JSContext* cx,
|
||||
Handle<PromiseObject*> resultPromise,
|
||||
HandleValue reason) {
|
||||
[[nodiscard]] bool js::AsyncFunctionThrown(JSContext* cx,
|
||||
Handle<PromiseObject*> resultPromise,
|
||||
HandleValue reason) {
|
||||
if (resultPromise->state() != JS::PromiseState::Pending) {
|
||||
// OOM after resolving promise.
|
||||
// Report a warning and ignore the result.
|
||||
@ -4499,7 +4500,7 @@ MOZ_MUST_USE bool js::AsyncFunctionThrown(JSContext* cx,
|
||||
|
||||
// ES2019 draft rev 7428c89bef626548084cd4e697a19ece7168f24c
|
||||
// 25.7.5.1 AsyncFunctionStart, steps 3.d-e, 3.g.
|
||||
MOZ_MUST_USE bool js::AsyncFunctionReturned(
|
||||
[[nodiscard]] bool js::AsyncFunctionReturned(
|
||||
JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value) {
|
||||
return ResolvePromiseInternal(cx, resultPromise, value);
|
||||
}
|
||||
@ -4509,10 +4510,11 @@ MOZ_MUST_USE bool js::AsyncFunctionReturned(
|
||||
// Helper function that performs 6.2.3.1 Await(promise) steps 2 and 9.
|
||||
// The same steps are also used in a few other places in the spec.
|
||||
template <typename T>
|
||||
static MOZ_MUST_USE bool InternalAwait(JSContext* cx, HandleValue value,
|
||||
HandleObject resultPromise,
|
||||
PromiseHandler onFulfilled,
|
||||
PromiseHandler onRejected, T extraStep) {
|
||||
[[nodiscard]] static bool InternalAwait(JSContext* cx, HandleValue value,
|
||||
HandleObject resultPromise,
|
||||
PromiseHandler onFulfilled,
|
||||
PromiseHandler onRejected,
|
||||
T extraStep) {
|
||||
// Step 2: Let promise be ? PromiseResolve(%Promise%, « value »).
|
||||
RootedObject promise(cx, PromiseObject::unforgeableResolve(cx, value));
|
||||
if (!promise) {
|
||||
@ -4549,7 +4551,7 @@ static MOZ_MUST_USE bool InternalAwait(JSContext* cx, HandleValue value,
|
||||
//
|
||||
// 6.2.3.1 Await(promise) steps 2-10 when the running execution context is
|
||||
// evaluating an `await` expression in an async function.
|
||||
MOZ_MUST_USE JSObject* js::AsyncFunctionAwait(
|
||||
[[nodiscard]] JSObject* js::AsyncFunctionAwait(
|
||||
JSContext* cx, Handle<AsyncFunctionGeneratorObject*> genObj,
|
||||
HandleValue value) {
|
||||
auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
|
||||
@ -4565,7 +4567,7 @@ MOZ_MUST_USE JSObject* js::AsyncFunctionAwait(
|
||||
|
||||
// 6.2.3.1 Await(promise) steps 2-10 when the running execution context is
|
||||
// evaluating an `await` expression in an async generator.
|
||||
MOZ_MUST_USE bool js::AsyncGeneratorAwait(
|
||||
[[nodiscard]] bool js::AsyncGeneratorAwait(
|
||||
JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value) {
|
||||
auto extra = [&](Handle<PromiseReactionRecord*> reaction) {
|
||||
@ -4785,12 +4787,12 @@ bool js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args,
|
||||
|
||||
enum class ResumeNextKind { Enqueue, Reject, Resolve };
|
||||
|
||||
static MOZ_MUST_USE bool AsyncGeneratorResumeNext(
|
||||
[[nodiscard]] static bool AsyncGeneratorResumeNext(
|
||||
JSContext* cx, Handle<AsyncGeneratorObject*> generator, ResumeNextKind kind,
|
||||
HandleValue valueOrException = UndefinedHandleValue, bool done = false);
|
||||
|
||||
// 25.5.3.3 AsyncGeneratorResolve ( generator, value, done )
|
||||
MOZ_MUST_USE bool js::AsyncGeneratorResolve(
|
||||
[[nodiscard]] bool js::AsyncGeneratorResolve(
|
||||
JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value,
|
||||
bool done) {
|
||||
return AsyncGeneratorResumeNext(cx, asyncGenObj, ResumeNextKind::Resolve,
|
||||
@ -4798,7 +4800,7 @@ MOZ_MUST_USE bool js::AsyncGeneratorResolve(
|
||||
}
|
||||
|
||||
// 25.5.3.4 AsyncGeneratorReject ( generator, exception )
|
||||
MOZ_MUST_USE bool js::AsyncGeneratorReject(
|
||||
[[nodiscard]] bool js::AsyncGeneratorReject(
|
||||
JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue exception) {
|
||||
return AsyncGeneratorResumeNext(cx, asyncGenObj, ResumeNextKind::Reject,
|
||||
@ -4809,7 +4811,7 @@ MOZ_MUST_USE bool js::AsyncGeneratorReject(
|
||||
// 25.5.3.3 AsyncGeneratorResolve ( generator, value, done )
|
||||
// 25.5.3.4 AsyncGeneratorReject ( generator, exception )
|
||||
// 25.5.3.5 AsyncGeneratorResumeNext ( generator )
|
||||
static MOZ_MUST_USE bool AsyncGeneratorResumeNext(
|
||||
[[nodiscard]] static bool AsyncGeneratorResumeNext(
|
||||
JSContext* cx, Handle<AsyncGeneratorObject*> generator, ResumeNextKind kind,
|
||||
HandleValue valueOrException_ /* = UndefinedHandleValue */,
|
||||
bool done /* = false */) {
|
||||
@ -5033,11 +5035,11 @@ static MOZ_MUST_USE bool AsyncGeneratorResumeNext(
|
||||
}
|
||||
|
||||
// 25.5.3.6 AsyncGeneratorEnqueue ( generator, completion )
|
||||
MOZ_MUST_USE bool js::AsyncGeneratorEnqueue(JSContext* cx,
|
||||
HandleValue asyncGenVal,
|
||||
CompletionKind completionKind,
|
||||
HandleValue completionValue,
|
||||
MutableHandleValue result) {
|
||||
[[nodiscard]] bool js::AsyncGeneratorEnqueue(JSContext* cx,
|
||||
HandleValue asyncGenVal,
|
||||
CompletionKind completionKind,
|
||||
HandleValue completionValue,
|
||||
MutableHandleValue result) {
|
||||
// Step 1 (implicit).
|
||||
|
||||
// Step 3.
|
||||
@ -5264,7 +5266,7 @@ bool js::Promise_then(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
// ES2016, 25.4.5.3.1.
|
||||
static MOZ_MUST_USE bool PerformPromiseThen(
|
||||
[[nodiscard]] static bool PerformPromiseThen(
|
||||
JSContext* cx, Handle<PromiseObject*> promise, HandleValue onFulfilled_,
|
||||
HandleValue onRejected_, Handle<PromiseCapability> resultCapability) {
|
||||
// Step 1 (implicit).
|
||||
@ -5293,7 +5295,7 @@ static MOZ_MUST_USE bool PerformPromiseThen(
|
||||
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseThenWithoutSettleHandlers(
|
||||
[[nodiscard]] static bool PerformPromiseThenWithoutSettleHandlers(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
Handle<PromiseObject*> promiseToResolve,
|
||||
Handle<PromiseCapability> resultCapability) {
|
||||
@ -5321,7 +5323,7 @@ static MOZ_MUST_USE bool PerformPromiseThenWithoutSettleHandlers(
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-performpromisethen
|
||||
// 25.6.5.4.1 PerformPromiseThen steps 8-11.
|
||||
static MOZ_MUST_USE bool PerformPromiseThenWithReaction(
|
||||
[[nodiscard]] static bool PerformPromiseThenWithReaction(
|
||||
JSContext* cx, Handle<PromiseObject*> unwrappedPromise,
|
||||
Handle<PromiseReactionRecord*> reaction) {
|
||||
// Step 8: If promise.[[PromiseState]] is "pending", then
|
||||
@ -5380,7 +5382,7 @@ static MOZ_MUST_USE bool PerformPromiseThenWithReaction(
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool AddPromiseReaction(
|
||||
[[nodiscard]] static bool AddPromiseReaction(
|
||||
JSContext* cx, Handle<PromiseObject*> unwrappedPromise,
|
||||
Handle<PromiseReactionRecord*> reaction) {
|
||||
MOZ_RELEASE_ASSERT(reaction->is<PromiseReactionRecord>());
|
||||
@ -5454,7 +5456,7 @@ static MOZ_MUST_USE bool AddPromiseReaction(
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool AddDummyPromiseReactionForDebugger(
|
||||
[[nodiscard]] static bool AddDummyPromiseReactionForDebugger(
|
||||
JSContext* cx, Handle<PromiseObject*> promise,
|
||||
HandleObject dependentPromise) {
|
||||
if (promise->state() != JS::PromiseState::Pending) {
|
||||
@ -5693,14 +5695,20 @@ void PromiseObject::copyUserInteractionFlagsFrom(PromiseObject& rhs) {
|
||||
//
|
||||
// Currently we only support skipping jobs when the async function is resumed
|
||||
// at least once.
|
||||
static MOZ_MUST_USE bool IsTopMostAsyncFunctionCall(JSContext* cx) {
|
||||
[[nodiscard]] static bool IsTopMostAsyncFunctionCall(JSContext* cx) {
|
||||
FrameIter iter(cx);
|
||||
|
||||
// The current frame should be the async function.
|
||||
if (iter.done()) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(iter.isFunctionFrame());
|
||||
|
||||
if (!iter.isFunctionFrame() && iter.isModuleFrame()) {
|
||||
// The iterator is not a function frame, it is a module frame.
|
||||
// Ignore this optimization for now.
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(iter.calleeTemplate()->isAsync());
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -5752,8 +5760,8 @@ static MOZ_MUST_USE bool IsTopMostAsyncFunctionCall(JSContext* cx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool js::TrySkipAwait(JSContext* cx, HandleValue val,
|
||||
bool* canSkip, MutableHandleValue resolved) {
|
||||
[[nodiscard]] bool js::CanSkipAwait(JSContext* cx, HandleValue val,
|
||||
bool* canSkip) {
|
||||
if (!cx->canSkipEnqueuingJobs) {
|
||||
*canSkip = false;
|
||||
return true;
|
||||
@ -5767,7 +5775,6 @@ MOZ_MUST_USE bool js::TrySkipAwait(JSContext* cx, HandleValue val,
|
||||
// Primitive values cannot be 'thenables', so we can trivially skip the
|
||||
// await operation.
|
||||
if (!val.isObject()) {
|
||||
resolved.set(val);
|
||||
*canSkip = true;
|
||||
return true;
|
||||
}
|
||||
@ -5797,11 +5804,36 @@ MOZ_MUST_USE bool js::TrySkipAwait(JSContext* cx, HandleValue val,
|
||||
return true;
|
||||
}
|
||||
|
||||
resolved.set(promise->value());
|
||||
*canSkip = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool js::ExtractAwaitValue(JSContext* cx, HandleValue val,
|
||||
MutableHandleValue resolved) {
|
||||
// Ensure all callers of this are jumping past the
|
||||
// extract if it's not possible to extract.
|
||||
#ifdef DEBUG
|
||||
bool canSkip;
|
||||
if (!CanSkipAwait(cx, val, &canSkip)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(canSkip == true);
|
||||
#endif
|
||||
|
||||
// Primitive values cannot be 'thenables', so we can trivially skip the
|
||||
// await operation.
|
||||
if (!val.isObject()) {
|
||||
resolved.set(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* obj = &val.toObject();
|
||||
PromiseObject* promise = &obj->as<PromiseObject>();
|
||||
resolved.set(promise->value());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::AutoDebuggerJobQueueInterruption::AutoDebuggerJobQueueInterruption()
|
||||
: cx(nullptr) {}
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "js/Promise.h"
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jsapi.h" // js::CompletionKind
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
@ -46,15 +44,15 @@ extern bool Promise_static_resolve(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
* Asserts that all objects in the `promises` vector are, maybe wrapped,
|
||||
* instances of `Promise` or a subclass of `Promise`.
|
||||
*/
|
||||
MOZ_MUST_USE JSObject* GetWaitForAllPromise(JSContext* cx,
|
||||
JS::HandleObjectVector promises);
|
||||
[[nodiscard]] JSObject* GetWaitForAllPromise(JSContext* cx,
|
||||
JS::HandleObjectVector promises);
|
||||
|
||||
/**
|
||||
* Enqueues resolve/reject reactions in the given Promise's reactions lists
|
||||
* as though by calling the original value of Promise.prototype.then, and
|
||||
* without regard to any Promise subclassing used in `promiseObj` itself.
|
||||
*/
|
||||
MOZ_MUST_USE PromiseObject* OriginalPromiseThen(
|
||||
[[nodiscard]] PromiseObject* OriginalPromiseThen(
|
||||
JSContext* cx, JS::Handle<JSObject*> promiseObj,
|
||||
JS::Handle<JSObject*> onFulfilled, JS::Handle<JSObject*> onRejected);
|
||||
|
||||
@ -82,7 +80,7 @@ enum class UnhandledRejectionBehavior { Ignore, Report };
|
||||
* 0. The sense of "react" here is the sense of the term as defined by Web IDL:
|
||||
* https://heycam.github.io/webidl/#dfn-perform-steps-once-promise-is-settled
|
||||
*/
|
||||
extern MOZ_MUST_USE bool ReactToUnwrappedPromise(
|
||||
[[nodiscard]] extern bool ReactToUnwrappedPromise(
|
||||
JSContext* cx, JS::Handle<PromiseObject*> unwrappedPromise,
|
||||
JS::Handle<JSObject*> onFulfilled_, JS::Handle<JSObject*> onRejected_,
|
||||
UnhandledRejectionBehavior behavior);
|
||||
@ -93,9 +91,9 @@ extern MOZ_MUST_USE bool ReactToUnwrappedPromise(
|
||||
* The abstract operation PromiseResolve, given a constructor and a value,
|
||||
* returns a new promise resolved with that value.
|
||||
*/
|
||||
MOZ_MUST_USE JSObject* PromiseResolve(JSContext* cx,
|
||||
JS::Handle<JSObject*> constructor,
|
||||
JS::Handle<JS::Value> value);
|
||||
[[nodiscard]] JSObject* PromiseResolve(JSContext* cx,
|
||||
JS::Handle<JSObject*> constructor,
|
||||
JS::Handle<JS::Value> value);
|
||||
|
||||
/**
|
||||
* Reject |promise| with the value of the current pending exception.
|
||||
@ -103,59 +101,60 @@ MOZ_MUST_USE JSObject* PromiseResolve(JSContext* cx,
|
||||
* |promise| must be from the current realm. Callers must enter the realm of
|
||||
* |promise| if they are not already in it.
|
||||
*/
|
||||
MOZ_MUST_USE bool RejectPromiseWithPendingError(
|
||||
[[nodiscard]] bool RejectPromiseWithPendingError(
|
||||
JSContext* cx, JS::Handle<PromiseObject*> promise);
|
||||
|
||||
/**
|
||||
* Create the promise object which will be used as the return value of an async
|
||||
* function.
|
||||
*/
|
||||
MOZ_MUST_USE PromiseObject* CreatePromiseObjectForAsync(JSContext* cx);
|
||||
[[nodiscard]] PromiseObject* CreatePromiseObjectForAsync(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Returns true if the given object is a promise created by
|
||||
* either CreatePromiseObjectForAsync function or async generator's method.
|
||||
*/
|
||||
MOZ_MUST_USE bool IsPromiseForAsyncFunctionOrGenerator(JSObject* promise);
|
||||
[[nodiscard]] bool IsPromiseForAsyncFunctionOrGenerator(JSObject* promise);
|
||||
|
||||
MOZ_MUST_USE bool AsyncFunctionReturned(
|
||||
[[nodiscard]] bool AsyncFunctionReturned(
|
||||
JSContext* cx, JS::Handle<PromiseObject*> resultPromise,
|
||||
JS::Handle<JS::Value> value);
|
||||
|
||||
MOZ_MUST_USE bool AsyncFunctionThrown(JSContext* cx,
|
||||
JS::Handle<PromiseObject*> resultPromise,
|
||||
JS::Handle<JS::Value> reason);
|
||||
[[nodiscard]] bool AsyncFunctionThrown(JSContext* cx,
|
||||
JS::Handle<PromiseObject*> resultPromise,
|
||||
JS::Handle<JS::Value> reason);
|
||||
|
||||
// Start awaiting `value` in an async function (, but doesn't suspend the
|
||||
// async function's execution!). Returns the async function's result promise.
|
||||
MOZ_MUST_USE JSObject* AsyncFunctionAwait(
|
||||
[[nodiscard]] JSObject* AsyncFunctionAwait(
|
||||
JSContext* cx, JS::Handle<AsyncFunctionGeneratorObject*> genObj,
|
||||
JS::Handle<JS::Value> value);
|
||||
|
||||
// If the await operation can be skipped and the resolution value for `val` can
|
||||
// be acquired, stored the resolved value to `resolved` and `true` to
|
||||
// `*canSkip`. Otherwise, stores `false` to `*canSkip`.
|
||||
MOZ_MUST_USE bool TrySkipAwait(JSContext* cx, JS::Handle<JS::Value> val,
|
||||
bool* canSkip,
|
||||
JS::MutableHandle<JS::Value> resolved);
|
||||
[[nodiscard]] bool CanSkipAwait(JSContext* cx, JS::Handle<JS::Value> val,
|
||||
bool* canSkip);
|
||||
[[nodiscard]] bool ExtractAwaitValue(JSContext* cx, JS::Handle<JS::Value> val,
|
||||
JS::MutableHandle<JS::Value> resolved);
|
||||
|
||||
MOZ_MUST_USE bool AsyncGeneratorAwait(
|
||||
[[nodiscard]] bool AsyncGeneratorAwait(
|
||||
JSContext* cx, JS::Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
JS::Handle<JS::Value> value);
|
||||
|
||||
MOZ_MUST_USE bool AsyncGeneratorResolve(
|
||||
[[nodiscard]] bool AsyncGeneratorResolve(
|
||||
JSContext* cx, JS::Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
JS::Handle<JS::Value> value, bool done);
|
||||
|
||||
MOZ_MUST_USE bool AsyncGeneratorReject(
|
||||
[[nodiscard]] bool AsyncGeneratorReject(
|
||||
JSContext* cx, JS::Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
JS::Handle<JS::Value> exception);
|
||||
|
||||
MOZ_MUST_USE bool AsyncGeneratorEnqueue(JSContext* cx,
|
||||
JS::Handle<JS::Value> asyncGenVal,
|
||||
CompletionKind completionKind,
|
||||
JS::Handle<JS::Value> completionValue,
|
||||
JS::MutableHandle<JS::Value> result);
|
||||
[[nodiscard]] bool AsyncGeneratorEnqueue(JSContext* cx,
|
||||
JS::Handle<JS::Value> asyncGenVal,
|
||||
CompletionKind completionKind,
|
||||
JS::Handle<JS::Value> completionValue,
|
||||
JS::MutableHandle<JS::Value> result);
|
||||
|
||||
bool AsyncFromSyncIteratorMethod(JSContext* cx, JS::CallArgs& args,
|
||||
CompletionKind completionKind);
|
||||
@ -175,9 +174,9 @@ struct PromiseReactionRecordBuilder {
|
||||
// Some reaction records refer to internal resolution or rejection functions
|
||||
// that are not naturally represented as debuggee JavaScript functions. In
|
||||
// this case, resolve and reject may be nullptr.
|
||||
virtual MOZ_MUST_USE bool then(JSContext* cx, JS::Handle<JSObject*> resolve,
|
||||
JS::Handle<JSObject*> reject,
|
||||
JS::Handle<JSObject*> result) = 0;
|
||||
[[nodiscard]] virtual bool then(JSContext* cx, JS::Handle<JSObject*> resolve,
|
||||
JS::Handle<JSObject*> reject,
|
||||
JS::Handle<JSObject*> result) = 0;
|
||||
|
||||
// A reaction record created when one native promise is resolved to another.
|
||||
// The 'promise' argument is the promise that will be settled in the same way
|
||||
@ -185,7 +184,7 @@ struct PromiseReactionRecordBuilder {
|
||||
//
|
||||
// Note that promise may not be same-compartment with cx. This function
|
||||
// presents the promise exactly as it appears in the reaction record.
|
||||
virtual MOZ_MUST_USE bool direct(
|
||||
[[nodiscard]] virtual bool direct(
|
||||
JSContext* cx, JS::Handle<PromiseObject*> unwrappedPromise) = 0;
|
||||
|
||||
// A reaction record that resumes an asynchronous function suspended at an
|
||||
@ -194,7 +193,7 @@ struct PromiseReactionRecordBuilder {
|
||||
//
|
||||
// Note that generator may not be same-compartment with cx. This function
|
||||
// presents the generator exactly as it appears in the reaction record.
|
||||
virtual MOZ_MUST_USE bool asyncFunction(
|
||||
[[nodiscard]] virtual bool asyncFunction(
|
||||
JSContext* cx,
|
||||
JS::Handle<AsyncFunctionGeneratorObject*> unwrappedGenerator) = 0;
|
||||
|
||||
@ -204,7 +203,7 @@ struct PromiseReactionRecordBuilder {
|
||||
//
|
||||
// Note that generator may not be same-compartment with cx. This function
|
||||
// presents the generator exactly as it appears in the reaction record.
|
||||
virtual MOZ_MUST_USE bool asyncGenerator(
|
||||
[[nodiscard]] virtual bool asyncGenerator(
|
||||
JSContext* cx, JS::Handle<AsyncGeneratorObject*> unwrappedGenerator) = 0;
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ static bool Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!DeleteProperty(cx, target, key, result)) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(result.reallyOk());
|
||||
args.rval().setBoolean(result.ok());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ static bool Reflect_preventExtensions(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!PreventExtensions(cx, target, result)) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(result.reallyOk());
|
||||
args.rval().setBoolean(result.ok());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ static bool Reflect_set(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!SetProperty(cx, target, key, value, receiver, result)) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(result.reallyOk());
|
||||
args.rval().setBoolean(result.ok());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ static bool Reflect_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!SetPrototype(cx, obj, proto, result)) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setBoolean(result.reallyOk());
|
||||
args.rval().setBoolean(result.ok());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -211,6 +211,9 @@ static const JSFunctionSpec reflect_methods[] = {
|
||||
JS_FN("setPrototypeOf", Reflect_setPrototypeOf, 2, 0),
|
||||
JS_FS_END};
|
||||
|
||||
static const JSPropertySpec reflect_properties[] = {
|
||||
JS_STRING_SYM_PS(toStringTag, "Reflect", JSPROP_READONLY), JS_PS_END};
|
||||
|
||||
/*** Setup ******************************************************************/
|
||||
|
||||
static JSObject* CreateReflectObject(JSContext* cx, JSProtoKey key) {
|
||||
@ -219,11 +222,11 @@ static JSObject* CreateReflectObject(JSContext* cx, JSProtoKey key) {
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
return NewSingletonObjectWithGivenProto<PlainObject>(cx, proto);
|
||||
return NewTenuredObjectWithGivenProto<PlainObject>(cx, proto);
|
||||
}
|
||||
|
||||
static const ClassSpec ReflectClassSpec = {CreateReflectObject, nullptr,
|
||||
reflect_methods, nullptr};
|
||||
reflect_methods, reflect_properties};
|
||||
|
||||
const JSClass js::ReflectClass = {"Reflect", 0, JS_NULL_CLASS_OPS,
|
||||
&ReflectClassSpec};
|
||||
|
@ -15,14 +15,14 @@ extern const JSClass ReflectClass;
|
||||
|
||||
namespace js {
|
||||
|
||||
extern MOZ_MUST_USE bool Reflect_getPrototypeOf(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool Reflect_getPrototypeOf(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool Reflect_isExtensible(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool Reflect_isExtensible(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool Reflect_ownKeys(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool Reflect_ownKeys(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
} // namespace js
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "builtin/Array.h"
|
||||
#include "builtin/Reflect.h"
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "frontend/CompilationStencil.h"
|
||||
#include "frontend/ModuleSharedContext.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/Parser.h"
|
||||
@ -289,7 +289,7 @@ class NodeBuilder {
|
||||
callbacks(cx),
|
||||
userv(c) {}
|
||||
|
||||
MOZ_MUST_USE bool init(HandleObject userobj = nullptr) {
|
||||
[[nodiscard]] bool init(HandleObject userobj = nullptr) {
|
||||
if (src) {
|
||||
if (!atomValue(src, &srcval)) {
|
||||
return false;
|
||||
@ -343,9 +343,9 @@ class NodeBuilder {
|
||||
}
|
||||
|
||||
private:
|
||||
MOZ_MUST_USE bool callbackHelper(HandleValue fun, const InvokeArgs& args,
|
||||
size_t i, TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
[[nodiscard]] bool callbackHelper(HandleValue fun, const InvokeArgs& args,
|
||||
size_t i, TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
// The end of the implementation of callback(). All arguments except
|
||||
// loc have already been stored in range [0, i).
|
||||
if (saveLoc) {
|
||||
@ -361,9 +361,9 @@ class NodeBuilder {
|
||||
// that convert to HandleValue, so this isn't as template-y as it seems,
|
||||
// just variadic.
|
||||
template <typename... Arguments>
|
||||
MOZ_MUST_USE bool callbackHelper(HandleValue fun, const InvokeArgs& args,
|
||||
size_t i, HandleValue head,
|
||||
Arguments&&... tail) {
|
||||
[[nodiscard]] bool callbackHelper(HandleValue fun, const InvokeArgs& args,
|
||||
size_t i, HandleValue head,
|
||||
Arguments&&... tail) {
|
||||
// Recursive loop to store the arguments into args. This eventually
|
||||
// bottoms out in a call to the non-template callbackHelper() above.
|
||||
args[i].set(head);
|
||||
@ -375,7 +375,7 @@ class NodeBuilder {
|
||||
// bool callback(HandleValue fun, HandleValue... args, TokenPos* pos,
|
||||
// MutableHandleValue dst);
|
||||
template <typename... Arguments>
|
||||
MOZ_MUST_USE bool callback(HandleValue fun, Arguments&&... args) {
|
||||
[[nodiscard]] bool callback(HandleValue fun, Arguments&&... args) {
|
||||
InvokeArgs iargs(cx);
|
||||
if (!iargs.init(cx, sizeof...(args) - 2 + size_t(saveLoc))) {
|
||||
return false;
|
||||
@ -393,7 +393,7 @@ class NodeBuilder {
|
||||
return v.isMagic(JS_SERIALIZE_NO_NODE) ? JS::UndefinedHandleValue : v;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool atomValue(const char* s, MutableHandleValue dst) {
|
||||
[[nodiscard]] bool atomValue(const char* s, MutableHandleValue dst) {
|
||||
/*
|
||||
* Bug 575416: instead of Atomize, lookup constant atoms in tbl file
|
||||
*/
|
||||
@ -406,7 +406,7 @@ class NodeBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool newObject(MutableHandleObject dst) {
|
||||
[[nodiscard]] bool newObject(MutableHandleObject dst) {
|
||||
RootedPlainObject nobj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!nobj) {
|
||||
return false;
|
||||
@ -416,12 +416,12 @@ class NodeBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool newArray(NodeVector& elts, MutableHandleValue dst);
|
||||
[[nodiscard]] bool newArray(NodeVector& elts, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool createNode(ASTType type, TokenPos* pos,
|
||||
MutableHandleObject dst);
|
||||
[[nodiscard]] bool createNode(ASTType type, TokenPos* pos,
|
||||
MutableHandleObject dst);
|
||||
|
||||
MOZ_MUST_USE bool newNodeHelper(HandleObject obj, MutableHandleValue dst) {
|
||||
[[nodiscard]] bool newNodeHelper(HandleObject obj, MutableHandleValue dst) {
|
||||
// The end of the implementation of newNode().
|
||||
MOZ_ASSERT(obj);
|
||||
dst.setObject(*obj);
|
||||
@ -429,8 +429,8 @@ class NodeBuilder {
|
||||
}
|
||||
|
||||
template <typename... Arguments>
|
||||
MOZ_MUST_USE bool newNodeHelper(HandleObject obj, const char* name,
|
||||
HandleValue value, Arguments&&... rest) {
|
||||
[[nodiscard]] bool newNodeHelper(HandleObject obj, const char* name,
|
||||
HandleValue value, Arguments&&... rest) {
|
||||
// Recursive loop to define properties. Note that the newNodeHelper()
|
||||
// call below passes two fewer arguments than we received, as we omit
|
||||
// `name` and `value`. This eventually bottoms out in a call to the
|
||||
@ -447,15 +447,15 @@ class NodeBuilder {
|
||||
// {const char *name0, HandleValue value0,}...
|
||||
// MutableHandleValue dst);
|
||||
template <typename... Arguments>
|
||||
MOZ_MUST_USE bool newNode(ASTType type, TokenPos* pos, Arguments&&... args) {
|
||||
[[nodiscard]] bool newNode(ASTType type, TokenPos* pos, Arguments&&... args) {
|
||||
RootedObject node(cx);
|
||||
return createNode(type, pos, &node) &&
|
||||
newNodeHelper(node, std::forward<Arguments>(args)...);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool listNode(ASTType type, const char* propName,
|
||||
NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
[[nodiscard]] bool listNode(ASTType type, const char* propName,
|
||||
NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
RootedValue array(cx);
|
||||
if (!newArray(elts, &array)) {
|
||||
return false;
|
||||
@ -469,8 +469,8 @@ class NodeBuilder {
|
||||
return newNode(type, pos, propName, array, dst);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool defineProperty(HandleObject obj, const char* name,
|
||||
HandleValue val) {
|
||||
[[nodiscard]] bool defineProperty(HandleObject obj, const char* name,
|
||||
HandleValue val) {
|
||||
MOZ_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
|
||||
|
||||
/*
|
||||
@ -488,9 +488,9 @@ class NodeBuilder {
|
||||
return DefineDataProperty(cx, obj, atom->asPropertyName(), optVal);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool newNodeLoc(TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool newNodeLoc(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool setNodeLoc(HandleObject node, TokenPos* pos);
|
||||
[[nodiscard]] bool setNodeLoc(HandleObject node, TokenPos* pos);
|
||||
|
||||
public:
|
||||
/*
|
||||
@ -506,228 +506,239 @@ class NodeBuilder {
|
||||
* misc nodes
|
||||
*/
|
||||
|
||||
MOZ_MUST_USE bool program(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool program(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool literal(HandleValue val, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool literal(HandleValue val, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool identifier(HandleValue name, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool identifier(HandleValue name, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool function(ASTType type, TokenPos* pos, HandleValue id,
|
||||
NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest,
|
||||
GeneratorStyle generatorStyle, bool isAsync,
|
||||
bool isExpression, MutableHandleValue dst);
|
||||
[[nodiscard]] bool function(ASTType type, TokenPos* pos, HandleValue id,
|
||||
NodeVector& args, NodeVector& defaults,
|
||||
HandleValue body, HandleValue rest,
|
||||
GeneratorStyle generatorStyle, bool isAsync,
|
||||
bool isExpression, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool variableDeclarator(HandleValue id, HandleValue init,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool variableDeclarator(HandleValue id, HandleValue init,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool switchCase(HandleValue expr, NodeVector& elts,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool catchClause(HandleValue var, HandleValue body,
|
||||
[[nodiscard]] bool switchCase(HandleValue expr, NodeVector& elts,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool prototypeMutation(HandleValue val, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
MOZ_MUST_USE bool propertyInitializer(HandleValue key, HandleValue val,
|
||||
PropKind kind, bool isShorthand,
|
||||
bool isMethod, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool catchClause(HandleValue var, HandleValue body,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool prototypeMutation(HandleValue val, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool propertyInitializer(HandleValue key, HandleValue val,
|
||||
PropKind kind, bool isShorthand,
|
||||
bool isMethod, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
/*
|
||||
* statements
|
||||
*/
|
||||
|
||||
MOZ_MUST_USE bool blockStatement(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool expressionStatement(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool emptyStatement(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool ifStatement(HandleValue test, HandleValue cons,
|
||||
HandleValue alt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool breakStatement(HandleValue label, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool continueStatement(HandleValue label, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool labeledStatement(HandleValue label, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool throwStatement(HandleValue arg, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool returnStatement(HandleValue arg, TokenPos* pos,
|
||||
[[nodiscard]] bool blockStatement(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool forStatement(HandleValue init, HandleValue test,
|
||||
HandleValue update, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool expressionStatement(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool forInStatement(HandleValue var, HandleValue expr,
|
||||
HandleValue stmt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool emptyStatement(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool forOfStatement(HandleValue var, HandleValue expr,
|
||||
HandleValue stmt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool withStatement(HandleValue expr, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool whileStatement(HandleValue test, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool doWhileStatement(HandleValue stmt, HandleValue test,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool switchStatement(HandleValue disc, NodeVector& elts,
|
||||
bool lexical, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool tryStatement(HandleValue body, HandleValue handler,
|
||||
HandleValue finally, TokenPos* pos,
|
||||
[[nodiscard]] bool ifStatement(HandleValue test, HandleValue cons,
|
||||
HandleValue alt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool debuggerStatement(TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool breakStatement(HandleValue label, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool importDeclaration(NodeVector& elts, HandleValue moduleSpec,
|
||||
[[nodiscard]] bool continueStatement(HandleValue label, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool labeledStatement(HandleValue label, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool importSpecifier(HandleValue importName,
|
||||
HandleValue bindingName, TokenPos* pos,
|
||||
[[nodiscard]] bool throwStatement(HandleValue arg, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool exportDeclaration(HandleValue decl, NodeVector& elts,
|
||||
HandleValue moduleSpec,
|
||||
HandleValue isDefault, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool returnStatement(HandleValue arg, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool exportSpecifier(HandleValue bindingName,
|
||||
HandleValue exportName, TokenPos* pos,
|
||||
[[nodiscard]] bool forStatement(HandleValue init, HandleValue test,
|
||||
HandleValue update, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool forInStatement(HandleValue var, HandleValue expr,
|
||||
HandleValue stmt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool forOfStatement(HandleValue var, HandleValue expr,
|
||||
HandleValue stmt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool classDefinition(bool expr, HandleValue name,
|
||||
HandleValue heritage, HandleValue block,
|
||||
[[nodiscard]] bool withStatement(HandleValue expr, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool whileStatement(HandleValue test, HandleValue stmt,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
MOZ_MUST_USE bool classMembers(NodeVector& members, MutableHandleValue dst);
|
||||
MOZ_MUST_USE bool classMethod(HandleValue name, HandleValue body,
|
||||
PropKind kind, bool isStatic, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
MOZ_MUST_USE bool classField(HandleValue name, HandleValue initializer,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool doWhileStatement(HandleValue stmt, HandleValue test,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool switchStatement(HandleValue disc, NodeVector& elts,
|
||||
bool lexical, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool tryStatement(HandleValue body, HandleValue handler,
|
||||
HandleValue finally, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool debuggerStatement(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool importDeclaration(NodeVector& elts, HandleValue moduleSpec,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool importSpecifier(HandleValue importName,
|
||||
HandleValue bindingName, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool importNamespaceSpecifier(HandleValue bindingName,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool exportDeclaration(HandleValue decl, NodeVector& elts,
|
||||
HandleValue moduleSpec,
|
||||
HandleValue isDefault, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool exportSpecifier(HandleValue bindingName,
|
||||
HandleValue exportName, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool exportNamespaceSpecifier(HandleValue exportName,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool exportBatchSpecifier(TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool classDefinition(bool expr, HandleValue name,
|
||||
HandleValue heritage, HandleValue block,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool classMembers(NodeVector& members, MutableHandleValue dst);
|
||||
[[nodiscard]] bool classMethod(HandleValue name, HandleValue body,
|
||||
PropKind kind, bool isStatic, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool classField(HandleValue name, HandleValue initializer,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
/*
|
||||
* expressions
|
||||
*/
|
||||
|
||||
MOZ_MUST_USE bool binaryExpression(BinaryOperator op, HandleValue left,
|
||||
HandleValue right, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool unaryExpression(UnaryOperator op, HandleValue expr,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool assignmentExpression(AssignmentOperator op, HandleValue lhs,
|
||||
HandleValue rhs, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool updateExpression(HandleValue expr, bool incr, bool prefix,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool logicalExpression(ParseNodeKind pnk, HandleValue left,
|
||||
[[nodiscard]] bool binaryExpression(BinaryOperator op, HandleValue left,
|
||||
HandleValue right, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool conditionalExpression(HandleValue test, HandleValue cons,
|
||||
HandleValue alt, TokenPos* pos,
|
||||
[[nodiscard]] bool unaryExpression(UnaryOperator op, HandleValue expr,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool assignmentExpression(AssignmentOperator op,
|
||||
HandleValue lhs, HandleValue rhs,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool sequenceExpression(NodeVector& elts, TokenPos* pos,
|
||||
[[nodiscard]] bool updateExpression(HandleValue expr, bool incr, bool prefix,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool logicalExpression(ParseNodeKind pnk, HandleValue left,
|
||||
HandleValue right, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool newExpression(HandleValue callee, NodeVector& args,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool conditionalExpression(HandleValue test, HandleValue cons,
|
||||
HandleValue alt, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool callExpression(HandleValue callee, NodeVector& args,
|
||||
TokenPos* pos, MutableHandleValue dst,
|
||||
bool isOptional = false);
|
||||
[[nodiscard]] bool sequenceExpression(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool memberExpression(bool computed, HandleValue expr,
|
||||
HandleValue member, TokenPos* pos,
|
||||
MutableHandleValue dst,
|
||||
bool isOptional = false);
|
||||
|
||||
MOZ_MUST_USE bool arrayExpression(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool templateLiteral(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool taggedTemplate(HandleValue callee, NodeVector& args,
|
||||
[[nodiscard]] bool newExpression(HandleValue callee, NodeVector& args,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool callSiteObj(NodeVector& raw, NodeVector& cooked,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool callExpression(HandleValue callee, NodeVector& args,
|
||||
TokenPos* pos, MutableHandleValue dst,
|
||||
bool isOptional = false);
|
||||
|
||||
MOZ_MUST_USE bool spreadExpression(HandleValue expr, TokenPos* pos,
|
||||
[[nodiscard]] bool memberExpression(bool computed, HandleValue expr,
|
||||
HandleValue member, TokenPos* pos,
|
||||
MutableHandleValue dst,
|
||||
bool isOptional = false);
|
||||
|
||||
[[nodiscard]] bool arrayExpression(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool optionalExpression(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool deleteOptionalExpression(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool computedName(HandleValue name, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool objectExpression(NodeVector& elts, TokenPos* pos,
|
||||
[[nodiscard]] bool templateLiteral(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool thisExpression(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool yieldExpression(HandleValue arg, YieldKind kind,
|
||||
[[nodiscard]] bool taggedTemplate(HandleValue callee, NodeVector& args,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool metaProperty(HandleValue meta, HandleValue property,
|
||||
[[nodiscard]] bool callSiteObj(NodeVector& raw, NodeVector& cooked,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool callImportExpression(HandleValue ident, HandleValue arg,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool spreadExpression(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool super(TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool optionalExpression(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool deleteOptionalExpression(HandleValue expr, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool computedName(HandleValue name, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool objectExpression(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool thisExpression(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool yieldExpression(HandleValue arg, YieldKind kind,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool metaProperty(HandleValue meta, HandleValue property,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool callImportExpression(HandleValue ident, HandleValue arg,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool super(TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
/*
|
||||
* declarations
|
||||
*/
|
||||
|
||||
MOZ_MUST_USE bool variableDeclaration(NodeVector& elts, VarDeclKind kind,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
[[nodiscard]] bool variableDeclaration(NodeVector& elts, VarDeclKind kind,
|
||||
TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
/*
|
||||
* patterns
|
||||
*/
|
||||
|
||||
MOZ_MUST_USE bool arrayPattern(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool objectPattern(NodeVector& elts, TokenPos* pos,
|
||||
[[nodiscard]] bool arrayPattern(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
MOZ_MUST_USE bool propertyPattern(HandleValue key, HandleValue patt,
|
||||
bool isShorthand, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
[[nodiscard]] bool objectPattern(NodeVector& elts, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
|
||||
[[nodiscard]] bool propertyPattern(HandleValue key, HandleValue patt,
|
||||
bool isShorthand, TokenPos* pos,
|
||||
MutableHandleValue dst);
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
@ -1393,6 +1404,17 @@ bool NodeBuilder::importSpecifier(HandleValue importName,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool NodeBuilder::importNamespaceSpecifier(HandleValue bindingName,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
RootedValue cb(cx, callbacks[AST_IMPORT_NAMESPACE_SPEC]);
|
||||
if (!cb.isNull()) {
|
||||
return callback(cb, bindingName, pos, dst);
|
||||
}
|
||||
|
||||
return newNode(AST_IMPORT_NAMESPACE_SPEC, pos, "name", bindingName, dst);
|
||||
}
|
||||
|
||||
bool NodeBuilder::exportDeclaration(HandleValue decl, NodeVector& elts,
|
||||
HandleValue moduleSpec,
|
||||
HandleValue isDefault, TokenPos* pos,
|
||||
@ -1424,6 +1446,17 @@ bool NodeBuilder::exportSpecifier(HandleValue bindingName,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool NodeBuilder::exportNamespaceSpecifier(HandleValue exportName,
|
||||
TokenPos* pos,
|
||||
MutableHandleValue dst) {
|
||||
RootedValue cb(cx, callbacks[AST_EXPORT_NAMESPACE_SPEC]);
|
||||
if (!cb.isNull()) {
|
||||
return callback(cb, exportName, pos, dst);
|
||||
}
|
||||
|
||||
return newNode(AST_EXPORT_NAMESPACE_SPEC, pos, "name", exportName, dst);
|
||||
}
|
||||
|
||||
bool NodeBuilder::exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst) {
|
||||
RootedValue cb(cx, callbacks[AST_EXPORT_BATCH_SPEC]);
|
||||
if (!cb.isNull()) {
|
||||
@ -1675,8 +1708,10 @@ class ASTSerializer {
|
||||
bool variableDeclarator(ParseNode* pn, MutableHandleValue dst);
|
||||
bool importDeclaration(BinaryNode* importNode, MutableHandleValue dst);
|
||||
bool importSpecifier(BinaryNode* importSpec, MutableHandleValue dst);
|
||||
bool importNamespaceSpecifier(UnaryNode* importSpec, MutableHandleValue dst);
|
||||
bool exportDeclaration(ParseNode* exportNode, MutableHandleValue dst);
|
||||
bool exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst);
|
||||
bool exportNamespaceSpecifier(UnaryNode* exportSpec, MutableHandleValue dst);
|
||||
bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst);
|
||||
|
||||
bool optStatement(ParseNode* pn, MutableHandleValue dst) {
|
||||
@ -1725,6 +1760,7 @@ class ASTSerializer {
|
||||
|
||||
bool identifier(HandleAtom atom, TokenPos* pos, MutableHandleValue dst);
|
||||
bool identifier(NameNode* id, MutableHandleValue dst);
|
||||
bool identifierOrLiteral(ParseNode* id, MutableHandleValue dst);
|
||||
bool literal(ParseNode* pn, MutableHandleValue dst);
|
||||
|
||||
bool optPattern(ParseNode* pn, MutableHandleValue dst) {
|
||||
@ -2046,10 +2082,17 @@ bool ASTSerializer::importDeclaration(BinaryNode* importNode,
|
||||
}
|
||||
|
||||
for (ParseNode* item : specList->contents()) {
|
||||
BinaryNode* spec = &item->as<BinaryNode>();
|
||||
RootedValue elt(cx);
|
||||
if (!importSpecifier(spec, &elt)) {
|
||||
return false;
|
||||
if (item->is<UnaryNode>()) {
|
||||
auto* spec = &item->as<UnaryNode>();
|
||||
if (!importNamespaceSpecifier(spec, &elt)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto* spec = &item->as<BinaryNode>();
|
||||
if (!importSpecifier(spec, &elt)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elts.infallibleAppend(elt);
|
||||
}
|
||||
@ -2067,12 +2110,23 @@ bool ASTSerializer::importSpecifier(BinaryNode* importSpec,
|
||||
|
||||
RootedValue importName(cx);
|
||||
RootedValue bindingName(cx);
|
||||
return identifier(importNameNode, &importName) &&
|
||||
return identifierOrLiteral(importNameNode, &importName) &&
|
||||
identifier(bindingNameNode, &bindingName) &&
|
||||
builder.importSpecifier(importName, bindingName, &importSpec->pn_pos,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::importNamespaceSpecifier(UnaryNode* importSpec,
|
||||
MutableHandleValue dst) {
|
||||
MOZ_ASSERT(importSpec->isKind(ParseNodeKind::ImportNamespaceSpec));
|
||||
NameNode* bindingNameNode = &importSpec->kid()->as<NameNode>();
|
||||
|
||||
RootedValue bindingName(cx);
|
||||
return identifier(bindingNameNode, &bindingName) &&
|
||||
builder.importNamespaceSpecifier(bindingName, &importSpec->pn_pos,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
|
||||
MutableHandleValue dst) {
|
||||
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportStmt) ||
|
||||
@ -2103,7 +2157,12 @@ bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
|
||||
if (!exportSpecifier(&spec->as<BinaryNode>(), &elt)) {
|
||||
return false;
|
||||
}
|
||||
} else if (spec->isKind(ParseNodeKind::ExportNamespaceSpec)) {
|
||||
if (!exportNamespaceSpecifier(&spec->as<UnaryNode>(), &elt)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportBatchSpecStmt));
|
||||
if (!builder.exportBatchSpecifier(&exportNode->pn_pos, &elt)) {
|
||||
return false;
|
||||
}
|
||||
@ -2165,12 +2224,22 @@ bool ASTSerializer::exportSpecifier(BinaryNode* exportSpec,
|
||||
|
||||
RootedValue bindingName(cx);
|
||||
RootedValue exportName(cx);
|
||||
return identifier(bindingNameNode, &bindingName) &&
|
||||
identifier(exportNameNode, &exportName) &&
|
||||
return identifierOrLiteral(bindingNameNode, &bindingName) &&
|
||||
identifierOrLiteral(exportNameNode, &exportName) &&
|
||||
builder.exportSpecifier(bindingName, exportName, &exportSpec->pn_pos,
|
||||
dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::exportNamespaceSpecifier(UnaryNode* exportSpec,
|
||||
MutableHandleValue dst) {
|
||||
MOZ_ASSERT(exportSpec->isKind(ParseNodeKind::ExportNamespaceSpec));
|
||||
NameNode* exportNameNode = &exportSpec->kid()->as<NameNode>();
|
||||
|
||||
RootedValue exportName(cx);
|
||||
return identifierOrLiteral(exportNameNode, &exportName) &&
|
||||
builder.exportNamespaceSpecifier(exportName, &exportSpec->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::switchCase(CaseClause* caseClause, MutableHandleValue dst) {
|
||||
MOZ_ASSERT_IF(
|
||||
caseClause->caseExpression(),
|
||||
@ -2550,7 +2619,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
|
||||
return false;
|
||||
}
|
||||
members.infallibleAppend(prop);
|
||||
} else {
|
||||
} else if (!item->isKind(ParseNodeKind::DefaultConstructor)) {
|
||||
ClassMethod* method = &item->as<ClassMethod>();
|
||||
MOZ_ASSERT(memberList->pn_pos.encloses(method->pn_pos));
|
||||
|
||||
@ -3286,8 +3355,9 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
|
||||
|
||||
case ParseNodeKind::RegExpExpr: {
|
||||
RegExpObject* re = pn->as<RegExpLiteral>().create(
|
||||
cx, parser->getCompilationInfo().input.atomCache,
|
||||
parser->getCompilationInfo().stencil);
|
||||
cx, parser->parserAtoms(),
|
||||
parser->getCompilationState().input.atomCache,
|
||||
parser->getCompilationState());
|
||||
if (!re) {
|
||||
return false;
|
||||
}
|
||||
@ -3301,7 +3371,8 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
|
||||
break;
|
||||
|
||||
case ParseNodeKind::BigIntExpr: {
|
||||
BigInt* x = pn->as<BigIntLiteral>().create(cx);
|
||||
auto index = pn->as<BigIntLiteral>().index();
|
||||
BigInt* x = parser->compilationState_.bigIntData[index].createBigInt(cx);
|
||||
if (!x) {
|
||||
return false;
|
||||
}
|
||||
@ -3453,6 +3524,13 @@ bool ASTSerializer::identifier(NameNode* id, MutableHandleValue dst) {
|
||||
return identifier(pnAtom, &id->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::identifierOrLiteral(ParseNode* id, MutableHandleValue dst) {
|
||||
if (id->getKind() == ParseNodeKind::Name) {
|
||||
return identifier(&id->as<NameNode>(), dst);
|
||||
}
|
||||
return literal(id, dst);
|
||||
}
|
||||
|
||||
bool ASTSerializer::function(FunctionNode* funNode, ASTType type,
|
||||
MutableHandleValue dst) {
|
||||
FunctionBox* funbox = funNode->funbox();
|
||||
@ -3770,25 +3848,27 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
options.allowHTMLComments = target == ParseGoal::Script;
|
||||
mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
|
||||
|
||||
Rooted<CompilationInfo> compilationInfo(cx, CompilationInfo(cx, options));
|
||||
Rooted<CompilationInput> input(cx, CompilationInput(options));
|
||||
if (target == ParseGoal::Script) {
|
||||
if (!compilationInfo.get().input.initForGlobal(cx)) {
|
||||
if (!input.get().initForGlobal(cx)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!compilationInfo.get().input.initForModule(cx)) {
|
||||
if (!input.get().initForModule(cx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
frontend::CompilationState compilationState(cx, allocScope, options,
|
||||
compilationInfo.get().stencil);
|
||||
frontend::CompilationState compilationState(cx, allocScope, input.get());
|
||||
if (!compilationState.init(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Parser<FullParseHandler, char16_t> parser(
|
||||
cx, options, chars.begin().get(), chars.length(),
|
||||
/* foldConstants = */ false, compilationInfo.get(), compilationState,
|
||||
nullptr, nullptr);
|
||||
/* foldConstants = */ false, compilationState,
|
||||
/* syntaxParser = */ nullptr);
|
||||
if (!parser.checkOptions()) {
|
||||
return false;
|
||||
}
|
||||
@ -3811,7 +3891,7 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
uint32_t len = chars.length();
|
||||
SourceExtent extent =
|
||||
SourceExtent::makeGlobalExtent(len, options.lineno, options.column);
|
||||
ModuleSharedContext modulesc(cx, compilationInfo.get(), builder, extent);
|
||||
ModuleSharedContext modulesc(cx, options, builder, extent);
|
||||
pn = parser.moduleBody(&modulesc);
|
||||
if (!pn) {
|
||||
return false;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "vm/EnvironmentObject-inl.h"
|
||||
#include "vm/JSObject-inl.h"
|
||||
@ -36,8 +37,22 @@ using JS::CompileOptions;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
// Allocate an object for the |.groups| or |.indices.groups| property
|
||||
// of a regexp match result.
|
||||
static PlainObject* CreateGroupsObject(JSContext* cx,
|
||||
HandlePlainObject groupsTemplate) {
|
||||
if (groupsTemplate->inDictionaryMode()) {
|
||||
return NewObjectWithGivenProto<PlainObject>(cx, nullptr);
|
||||
}
|
||||
|
||||
PlainObject* result;
|
||||
JS_TRY_VAR_OR_RETURN_NULL(
|
||||
cx, result, PlainObject::createWithTemplate(cx, groupsTemplate));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ES 2021 draft 21.2.5.2.2: Steps 16-28
|
||||
* Implements RegExpBuiltinExec: Steps 18-35
|
||||
* https://tc39.es/ecma262/#sec-regexpbuiltinexec
|
||||
*/
|
||||
bool js::CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
@ -55,44 +70,35 @@ bool js::CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
* input: input string
|
||||
* index: start index for the match
|
||||
* groups: named capture groups for the match
|
||||
* indices: capture indices for the match, if required
|
||||
*/
|
||||
|
||||
bool hasIndices = re->hasIndices();
|
||||
|
||||
// Get the templateObject that defines the shape and type of the output
|
||||
// object.
|
||||
RegExpRealm::ResultTemplateKind kind =
|
||||
hasIndices ? RegExpRealm::ResultTemplateKind::WithIndices
|
||||
: RegExpRealm::ResultTemplateKind::Normal;
|
||||
ArrayObject* templateObject =
|
||||
cx->realm()->regExps.getOrCreateMatchResultTemplateObject(cx);
|
||||
cx->realm()->regExps.getOrCreateMatchResultTemplateObject(cx, kind);
|
||||
if (!templateObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 16
|
||||
// Steps 18-19
|
||||
size_t numPairs = matches.length();
|
||||
MOZ_ASSERT(numPairs > 0);
|
||||
|
||||
// Steps 18-19
|
||||
// Steps 20-21: Allocate the match result object.
|
||||
RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(
|
||||
cx, numPairs, templateObject));
|
||||
if (!arr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 24 (reordered)
|
||||
RootedPlainObject groups(cx);
|
||||
bool groupsInDictionaryMode = false;
|
||||
if (re->numNamedCaptures() > 0) {
|
||||
RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
|
||||
if (groupsTemplate->inDictionaryMode()) {
|
||||
groups = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
|
||||
groups->setGroup(groupsTemplate->group());
|
||||
groupsInDictionaryMode = true;
|
||||
} else {
|
||||
JS_TRY_VAR_OR_RETURN_FALSE(
|
||||
cx, groups, PlainObject::createWithTemplate(cx, groupsTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 22-23 and 27 a-e.
|
||||
// Store a Value for each pair.
|
||||
// Steps 28-29 and 33 a-d: Initialize the elements of the match result.
|
||||
// Store a Value for each match pair.
|
||||
for (size_t i = 0; i < numPairs; i++) {
|
||||
const MatchPair& pair = matches[i];
|
||||
|
||||
@ -111,18 +117,82 @@ bool js::CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
}
|
||||
}
|
||||
|
||||
// Step 27 f.
|
||||
// The groups template object stores the names of the named captures in the
|
||||
// the order in which they are defined. The named capture indices vector
|
||||
// stores the corresponding capture indices. If we are not in dictionary mode,
|
||||
// we simply fill in the slots with the correct values. In dictionary mode,
|
||||
// we have to define the properties explicitly.
|
||||
if (!groupsInDictionaryMode) {
|
||||
for (uint32_t i = 0; i < re->numNamedCaptures(); i++) {
|
||||
uint32_t idx = re->getNamedCaptureIndex(i);
|
||||
groups->setSlot(i, arr->getDenseElement(idx));
|
||||
// Step 34a (reordered): Allocate and initialize the indices object if needed.
|
||||
// This is an inlined implementation of MakeIndicesArray:
|
||||
// https://tc39.es/ecma262/#sec-makeindicesarray
|
||||
RootedArrayObject indices(cx);
|
||||
RootedPlainObject indicesGroups(cx);
|
||||
if (hasIndices) {
|
||||
// MakeIndicesArray: step 8
|
||||
ArrayObject* indicesTemplate =
|
||||
cx->realm()->regExps.getOrCreateMatchResultTemplateObject(
|
||||
cx, RegExpRealm::ResultTemplateKind::Indices);
|
||||
if (!indicesTemplate) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
indices =
|
||||
NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, indicesTemplate);
|
||||
if (!indices) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MakeIndicesArray: steps 10-12
|
||||
if (re->numNamedCaptures() > 0) {
|
||||
RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
|
||||
indicesGroups = CreateGroupsObject(cx, groupsTemplate);
|
||||
if (!indicesGroups) {
|
||||
return false;
|
||||
}
|
||||
indices->setSlot(RegExpRealm::IndicesGroupsSlot,
|
||||
ObjectValue(*indicesGroups));
|
||||
} else {
|
||||
indices->setSlot(RegExpRealm::IndicesGroupsSlot, UndefinedValue());
|
||||
}
|
||||
|
||||
// MakeIndicesArray: step 13 a-d. (Step 13.e is implemented below.)
|
||||
for (size_t i = 0; i < numPairs; i++) {
|
||||
const MatchPair& pair = matches[i];
|
||||
|
||||
if (pair.isUndefined()) {
|
||||
// Since we had a match, first pair must be present.
|
||||
MOZ_ASSERT(i != 0);
|
||||
indices->setDenseInitializedLength(i + 1);
|
||||
indices->initDenseElement(i, UndefinedValue());
|
||||
} else {
|
||||
RootedArrayObject indexPair(cx, NewDenseFullyAllocatedArray(cx, 2));
|
||||
if (!indexPair) {
|
||||
return false;
|
||||
}
|
||||
indexPair->setDenseInitializedLength(2);
|
||||
indexPair->initDenseElement(0, Int32Value(pair.start));
|
||||
indexPair->initDenseElement(1, Int32Value(pair.limit));
|
||||
|
||||
indices->setDenseInitializedLength(i + 1);
|
||||
indices->initDenseElement(i, ObjectValue(*indexPair));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 30-31 (reordered): Allocate the groups object (if needed).
|
||||
RootedPlainObject groups(cx);
|
||||
bool groupsInDictionaryMode = false;
|
||||
if (re->numNamedCaptures() > 0) {
|
||||
RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
|
||||
groupsInDictionaryMode = groupsTemplate->inDictionaryMode();
|
||||
groups = CreateGroupsObject(cx, groupsTemplate);
|
||||
if (!groups) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 33 e-f: Initialize the properties of |groups| and |indices.groups|.
|
||||
// The groups template object stores the names of the named captures
|
||||
// in the the order in which they are defined. The named capture
|
||||
// indices vector stores the corresponding capture indices. In
|
||||
// dictionary mode, we have to define the properties explicitly. If
|
||||
// we are not in dictionary mode, we simply fill in the slots with
|
||||
// the correct values.
|
||||
if (groupsInDictionaryMode) {
|
||||
RootedIdVector keys(cx);
|
||||
RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
|
||||
if (!GetPropertyKeys(cx, groupsTemplate, 0, &keys)) {
|
||||
@ -138,23 +208,48 @@ bool js::CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
if (!NativeDefineDataProperty(cx, groups, key, val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
// MakeIndicesArray: Step 13.e (reordered)
|
||||
if (hasIndices) {
|
||||
val = indices->getDenseElement(idx);
|
||||
if (!NativeDefineDataProperty(cx, indicesGroups, key, val,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < re->numNamedCaptures(); i++) {
|
||||
uint32_t idx = re->getNamedCaptureIndex(i);
|
||||
groups->setSlot(i, arr->getDenseElement(idx));
|
||||
|
||||
// MakeIndicesArray: Step 13.e (reordered)
|
||||
if (hasIndices) {
|
||||
indicesGroups->setSlot(i, indices->getDenseElement(idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 20 (reordered).
|
||||
// Step 22 (reordered).
|
||||
// Set the |index| property.
|
||||
arr->setSlot(RegExpRealm::MatchResultObjectIndexSlot,
|
||||
Int32Value(matches[0].start));
|
||||
|
||||
// Step 21 (reordered).
|
||||
// Step 23 (reordered).
|
||||
// Set the |input| property.
|
||||
arr->setSlot(RegExpRealm::MatchResultObjectInputSlot, StringValue(input));
|
||||
|
||||
// Steps 25-26 (reordered)
|
||||
// Step 32 (reordered)
|
||||
// Set the |groups| property.
|
||||
arr->setSlot(RegExpRealm::MatchResultObjectGroupsSlot,
|
||||
groups ? ObjectValue(*groups) : UndefinedValue());
|
||||
|
||||
// Step 34b
|
||||
// Set the |indices| property.
|
||||
if (re->hasIndices()) {
|
||||
arr->setSlot(RegExpRealm::MatchResultObjectIndicesSlot,
|
||||
ObjectValue(*indices));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RootedValue test(cx);
|
||||
RootedId id(cx, NameToId(cx->names().index));
|
||||
@ -169,7 +264,7 @@ bool js::CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
MOZ_ASSERT(test == arr->getSlot(RegExpRealm::MatchResultObjectInputSlot));
|
||||
#endif
|
||||
|
||||
// Step 28.
|
||||
// Step 35.
|
||||
rval.setObject(*arr);
|
||||
return true;
|
||||
}
|
||||
@ -661,188 +756,146 @@ bool js::regexp_construct_raw_flags(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool IsRegExpPrototype(HandleValue v, JSContext* cx) {
|
||||
return (v.isObject() &&
|
||||
cx->global()->maybeGetRegExpPrototype() == &v.toObject());
|
||||
// This is a specialized implementation of "UnwrapAndTypeCheckThis" for RegExp
|
||||
// getters that need to return a special value for same-realm
|
||||
// %RegExp.prototype%.
|
||||
template <typename Fn>
|
||||
static bool RegExpGetter(JSContext* cx, CallArgs& args, const char* methodName,
|
||||
Fn&& fn,
|
||||
HandleValue fallbackValue = UndefinedHandleValue) {
|
||||
JSObject* obj = nullptr;
|
||||
if (args.thisv().isObject()) {
|
||||
obj = &args.thisv().toObject();
|
||||
if (IsWrapper(obj)) {
|
||||
obj = CheckedUnwrapStatic(obj);
|
||||
if (!obj) {
|
||||
ReportAccessDenied(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
// Step 4ff
|
||||
if (obj->is<RegExpObject>()) {
|
||||
return fn(&obj->as<RegExpObject>());
|
||||
}
|
||||
|
||||
// Step 3.a. "If SameValue(R, %RegExp.prototype%) is true, return
|
||||
// undefined."
|
||||
// Or `return "(?:)"` for get RegExp.prototype.source.
|
||||
if (obj == cx->global()->maybeGetRegExpPrototype()) {
|
||||
args.rval().set(fallbackValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
// fall-through
|
||||
}
|
||||
|
||||
// Step 2. and Step 3.b.
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_INCOMPATIBLE_REGEXP_GETTER, methodName,
|
||||
InformalValueTypeName(args.thisv()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.4.
|
||||
MOZ_ALWAYS_INLINE bool regexp_global_impl(JSContext* cx, const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->global());
|
||||
return true;
|
||||
bool js::regexp_hasIndices(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return RegExpGetter(cx, args, "hasIndices", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->hasIndices());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.5 get RegExp.prototype.global
|
||||
bool js::regexp_global(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "global", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->global());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_global_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.5.
|
||||
MOZ_ALWAYS_INLINE bool regexp_ignoreCase_impl(JSContext* cx,
|
||||
const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->ignoreCase());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.6 get RegExp.prototype.ignoreCase
|
||||
bool js::regexp_ignoreCase(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "ignoreCase", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->ignoreCase());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_ignoreCase_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.7.
|
||||
MOZ_ALWAYS_INLINE bool regexp_multiline_impl(JSContext* cx,
|
||||
const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->multiline());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.9 get RegExp.prototype.multiline
|
||||
bool js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "multiline", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->multiline());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_multiline_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.10.
|
||||
MOZ_ALWAYS_INLINE bool regexp_source_impl(JSContext* cx, const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Step 5.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
RootedAtom src(cx, reObj->getSource());
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
JSString* str = EscapeRegExpPattern(cx, src);
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.12 get RegExp.prototype.source
|
||||
static bool regexp_source(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
// Step 3.a. Return "(?:)" for %RegExp.prototype%.
|
||||
RootedValue fallback(cx, StringValue(cx->names().emptyRegExp));
|
||||
return RegExpGetter(
|
||||
cx, args, "source",
|
||||
[cx, args](RegExpObject* unwrapped) {
|
||||
RootedAtom src(cx, unwrapped->getSource());
|
||||
MOZ_ASSERT(src);
|
||||
// Mark potentially cross-compartment JSAtom.
|
||||
cx->markAtom(src);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setString(cx->names().emptyRegExp);
|
||||
return true;
|
||||
}
|
||||
// Step 7.
|
||||
JSString* escaped = EscapeRegExpPattern(cx, src);
|
||||
if (!escaped) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 1-4.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_source_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2020 draft 21.2.5.3.
|
||||
MOZ_ALWAYS_INLINE bool regexp_dotAll_impl(JSContext* cx, const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->dotAll());
|
||||
return true;
|
||||
args.rval().setString(escaped);
|
||||
return true;
|
||||
},
|
||||
fallback);
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.3 get RegExp.prototype.dotAll
|
||||
bool js::regexp_dotAll(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "dotAll", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->dotAll());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_dotAll_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.12.
|
||||
MOZ_ALWAYS_INLINE bool regexp_sticky_impl(JSContext* cx, const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->sticky());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.14 get RegExp.prototype.sticky
|
||||
bool js::regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "sticky", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->sticky());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_sticky_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES 2017 draft 21.2.5.15.
|
||||
MOZ_ALWAYS_INLINE bool regexp_unicode_impl(JSContext* cx,
|
||||
const CallArgs& args) {
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
// Steps 4-6.
|
||||
RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
|
||||
args.rval().setBoolean(reObj->unicode());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// ES2021 draft rev 0b3a808af87a9123890767152a26599cc8fde161
|
||||
// 21.2.5.17 get RegExp.prototype.unicode
|
||||
bool js::regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 3.a.
|
||||
if (IsRegExpPrototype(args.thisv(), cx)) {
|
||||
args.rval().setUndefined();
|
||||
return RegExpGetter(cx, args, "unicode", [args](RegExpObject* unwrapped) {
|
||||
args.rval().setBoolean(unwrapped->unicode());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 1-3.
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_unicode_impl>(cx, args);
|
||||
});
|
||||
}
|
||||
|
||||
const JSPropertySpec js::regexp_properties[] = {
|
||||
JS_SELF_HOSTED_GET("flags", "$RegExpFlagsGetter", 0),
|
||||
JS_PSG("hasIndices", regexp_hasIndices, 0),
|
||||
JS_PSG("global", regexp_global, 0),
|
||||
JS_PSG("ignoreCase", regexp_ignoreCase, 0),
|
||||
JS_PSG("multiline", regexp_multiline, 0),
|
||||
@ -1834,7 +1887,7 @@ bool js::RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp) {
|
||||
bool js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto) {
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
AutoAssertNoPendingException aanpe(cx);
|
||||
if (!proto->isNative()) {
|
||||
if (!proto->is<NativeObject>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1869,6 +1922,16 @@ bool js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSNative hasIndicesGetter;
|
||||
if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().hasIndices),
|
||||
&hasIndicesGetter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasIndicesGetter != regexp_hasIndices) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSNative ignoreCaseGetter;
|
||||
if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().ignoreCase),
|
||||
&ignoreCaseGetter)) {
|
||||
@ -2060,7 +2123,7 @@ bool js::intrinsic_GetElemBaseForLambda(JSContext* cx, unsigned argc,
|
||||
|
||||
JSObject& bobj = b.toObject();
|
||||
const JSClass* clasp = bobj.getClass();
|
||||
if (!clasp->isNative() || clasp->getOpsLookupProperty() ||
|
||||
if (!clasp->isNativeObject() || clasp->getOpsLookupProperty() ||
|
||||
clasp->getOpsGetProperty()) {
|
||||
return true;
|
||||
}
|
||||
@ -2080,7 +2143,7 @@ bool js::intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc,
|
||||
MOZ_ASSERT(args.length() == 2);
|
||||
|
||||
RootedObject obj(cx, &args[0].toObject());
|
||||
if (!obj->isNative()) {
|
||||
if (!obj->is<NativeObject>()) {
|
||||
// The object is already checked to be native in GetElemBaseForLambda,
|
||||
// but it can be swapped to another class that is non-native.
|
||||
// Return undefined to mark failure to get the property.
|
||||
|
@ -23,49 +23,50 @@ JSObject* InitRegExpClass(JSContext* cx, HandleObject obj);
|
||||
* |input| may be nullptr if there is no JSString corresponding to
|
||||
* |chars| and |length|.
|
||||
*/
|
||||
MOZ_MUST_USE bool ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res,
|
||||
Handle<RegExpObject*> reobj,
|
||||
HandleLinearString input,
|
||||
size_t* lastIndex, bool test,
|
||||
MutableHandleValue rval);
|
||||
[[nodiscard]] bool ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res,
|
||||
Handle<RegExpObject*> reobj,
|
||||
HandleLinearString input,
|
||||
size_t* lastIndex, bool test,
|
||||
MutableHandleValue rval);
|
||||
|
||||
// Translation from MatchPairs to a JS array in regexp_exec()'s output format.
|
||||
MOZ_MUST_USE bool CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
HandleString input,
|
||||
const MatchPairs& matches,
|
||||
MutableHandleValue rval);
|
||||
[[nodiscard]] bool CreateRegExpMatchResult(JSContext* cx, HandleRegExpShared re,
|
||||
HandleString input,
|
||||
const MatchPairs& matches,
|
||||
MutableHandleValue rval);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpMatcher(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpMatcherRaw(JSContext* cx, HandleObject regexp,
|
||||
HandleString input,
|
||||
int32_t maybeLastIndex,
|
||||
MatchPairs* maybeMatches,
|
||||
MutableHandleValue output);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpSearcher(JSContext* cx, unsigned argc,
|
||||
[[nodiscard]] extern bool RegExpMatcher(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpSearcherRaw(JSContext* cx, HandleObject regexp,
|
||||
[[nodiscard]] extern bool RegExpMatcherRaw(JSContext* cx, HandleObject regexp,
|
||||
HandleString input,
|
||||
int32_t lastIndex,
|
||||
int32_t maybeLastIndex,
|
||||
MatchPairs* maybeMatches,
|
||||
int32_t* result);
|
||||
MutableHandleValue output);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpTester(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] extern bool RegExpSearcher(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpTesterRaw(JSContext* cx, HandleObject regexp,
|
||||
HandleString input, int32_t lastIndex,
|
||||
int32_t* endIndex);
|
||||
[[nodiscard]] extern bool RegExpSearcherRaw(JSContext* cx, HandleObject regexp,
|
||||
HandleString input,
|
||||
int32_t lastIndex,
|
||||
MatchPairs* maybeMatches,
|
||||
int32_t* result);
|
||||
|
||||
extern MOZ_MUST_USE bool intrinsic_GetElemBaseForLambda(JSContext* cx,
|
||||
unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool RegExpTester(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool intrinsic_GetStringDataProperty(JSContext* cx,
|
||||
[[nodiscard]] extern bool RegExpTesterRaw(JSContext* cx, HandleObject regexp,
|
||||
HandleString input, int32_t lastIndex,
|
||||
int32_t* endIndex);
|
||||
|
||||
[[nodiscard]] extern bool intrinsic_GetElemBaseForLambda(JSContext* cx,
|
||||
unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
[[nodiscard]] extern bool intrinsic_GetStringDataProperty(JSContext* cx,
|
||||
unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
/*
|
||||
* The following functions are for use by self-hosted code.
|
||||
*/
|
||||
@ -79,62 +80,64 @@ extern MOZ_MUST_USE bool intrinsic_GetStringDataProperty(JSContext* cx,
|
||||
* Dedicated function for RegExp.prototype[@@replace] and
|
||||
* RegExp.prototype[@@split] optimized paths.
|
||||
*/
|
||||
extern MOZ_MUST_USE bool regexp_construct_raw_flags(JSContext* cx,
|
||||
[[nodiscard]] extern bool regexp_construct_raw_flags(JSContext* cx,
|
||||
unsigned argc, Value* vp);
|
||||
|
||||
[[nodiscard]] extern bool IsRegExp(JSContext* cx, HandleValue value,
|
||||
bool* result);
|
||||
|
||||
[[nodiscard]] extern bool RegExpCreate(JSContext* cx, HandleValue pattern,
|
||||
HandleValue flags,
|
||||
MutableHandleValue rval);
|
||||
|
||||
[[nodiscard]] extern bool RegExpPrototypeOptimizable(JSContext* cx,
|
||||
unsigned argc, Value* vp);
|
||||
|
||||
[[nodiscard]] extern bool RegExpPrototypeOptimizableRaw(JSContext* cx,
|
||||
JSObject* proto);
|
||||
|
||||
[[nodiscard]] extern bool RegExpInstanceOptimizable(JSContext* cx,
|
||||
unsigned argc, Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool IsRegExp(JSContext* cx, HandleValue value,
|
||||
bool* result);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpCreate(JSContext* cx, HandleValue pattern,
|
||||
HandleValue flags,
|
||||
MutableHandleValue rval);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpPrototypeOptimizable(JSContext* cx,
|
||||
unsigned argc, Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpPrototypeOptimizableRaw(JSContext* cx,
|
||||
[[nodiscard]] extern bool RegExpInstanceOptimizableRaw(JSContext* cx,
|
||||
JSObject* obj,
|
||||
JSObject* proto);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpInstanceOptimizable(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpInstanceOptimizableRaw(JSContext* cx,
|
||||
JSObject* obj,
|
||||
JSObject* proto);
|
||||
|
||||
extern MOZ_MUST_USE bool RegExpGetSubstitution(
|
||||
[[nodiscard]] extern bool RegExpGetSubstitution(
|
||||
JSContext* cx, HandleArrayObject matchResult, HandleLinearString string,
|
||||
size_t position, HandleLinearString replacement, size_t firstDollarIndex,
|
||||
HandleValue namedCaptures, MutableHandleValue rval);
|
||||
|
||||
extern MOZ_MUST_USE bool GetFirstDollarIndex(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool GetFirstDollarIndex(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern MOZ_MUST_USE bool GetFirstDollarIndexRaw(JSContext* cx, JSString* str,
|
||||
int32_t* index);
|
||||
[[nodiscard]] extern bool GetFirstDollarIndexRaw(JSContext* cx, JSString* str,
|
||||
int32_t* index);
|
||||
|
||||
extern int32_t GetFirstDollarIndexRawFlat(JSLinearString* text);
|
||||
|
||||
// RegExp ClassSpec members used in RegExpObject.cpp.
|
||||
extern MOZ_MUST_USE bool regexp_construct(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool regexp_construct(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
extern const JSPropertySpec regexp_static_props[];
|
||||
extern const JSPropertySpec regexp_properties[];
|
||||
extern const JSFunctionSpec regexp_methods[];
|
||||
|
||||
// Used in RegExpObject::isOriginalFlagGetter.
|
||||
extern MOZ_MUST_USE bool regexp_global(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
extern MOZ_MUST_USE bool regexp_ignoreCase(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
extern MOZ_MUST_USE bool regexp_multiline(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
extern MOZ_MUST_USE bool regexp_dotAll(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
extern MOZ_MUST_USE bool regexp_sticky(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
extern MOZ_MUST_USE bool regexp_unicode(JSContext* cx, unsigned argc,
|
||||
[[nodiscard]] extern bool regexp_hasIndices(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_global(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_ignoreCase(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_multiline(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_dotAll(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_sticky(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
[[nodiscard]] extern bool regexp_unicode(JSContext* cx, unsigned argc,
|
||||
JS::Value* vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -16,30 +16,34 @@ function $RegExpFlagsGetter() {
|
||||
var result = "";
|
||||
|
||||
// Steps 4-5.
|
||||
if (R.hasIndices)
|
||||
result += "d";
|
||||
|
||||
// Steps 6-7.
|
||||
if (R.global)
|
||||
result += "g";
|
||||
|
||||
// Steps 6-7.
|
||||
// Steps 8-9.
|
||||
if (R.ignoreCase)
|
||||
result += "i";
|
||||
|
||||
// Steps 8-9.
|
||||
// Steps 10-11.
|
||||
if (R.multiline)
|
||||
result += "m";
|
||||
|
||||
// Steps 10-11.
|
||||
// Steps 12-13.
|
||||
if (R.dotAll)
|
||||
result += "s";
|
||||
|
||||
// Steps 12-13.
|
||||
// Steps 14-15.
|
||||
if (R.unicode)
|
||||
result += "u";
|
||||
|
||||
// Steps 14-15.
|
||||
// Steps 16-17
|
||||
if (R.sticky)
|
||||
result += "y";
|
||||
|
||||
// Step 16.
|
||||
// Step 18.
|
||||
return result;
|
||||
}
|
||||
_SetCanonicalName($RegExpFlagsGetter, "get flags");
|
||||
@ -229,6 +233,7 @@ function RegExpGlobalMatchOpt(rx, S, fullUnicode) {
|
||||
// Checks if following properties and getters are not modified, and accessing
|
||||
// them not observed by content script:
|
||||
// * flags
|
||||
// * hasIndices
|
||||
// * global
|
||||
// * ignoreCase
|
||||
// * multiline
|
||||
|
@ -89,6 +89,7 @@
|
||||
#define REGEXP_STICKY_FLAG 0x08
|
||||
#define REGEXP_UNICODE_FLAG 0x10
|
||||
#define REGEXP_DOTALL_FLAG 0x20
|
||||
#define REGEXP_HASINDICES_FLAG 0x40
|
||||
|
||||
#define REGEXP_STRING_ITERATOR_REGEXP_SLOT 0
|
||||
#define REGEXP_STRING_ITERATOR_STRING_SLOT 1
|
||||
@ -99,11 +100,18 @@
|
||||
#define REGEXP_STRING_ITERATOR_LASTINDEX_DONE -1
|
||||
#define REGEXP_STRING_ITERATOR_LASTINDEX_SLOW -2
|
||||
|
||||
#define DATE_METHOD_LOCALE_TIME_STRING 0
|
||||
#define DATE_METHOD_LOCALE_DATE_STRING 1
|
||||
#define DATE_METHOD_LOCALE_STRING 2
|
||||
|
||||
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
|
||||
#define MODULE_OBJECT_STATUS_SLOT 3
|
||||
#define MODULE_OBJECT_EVALUATION_ERROR_SLOT 4
|
||||
#define MODULE_OBJECT_DFS_INDEX_SLOT 14
|
||||
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 15
|
||||
#define MODULE_OBJECT_ASYNC_EVALUATING_SLOT 17
|
||||
#define MODULE_OBJECT_TOP_LEVEL_CAPABILITY_SLOT 18
|
||||
#define MODULE_OBJECT_PENDING_ASYNC_DEPENDENCIES_SLOT 20
|
||||
|
||||
// rev b012019fea18f29737a67c36911340a3e25bfc63
|
||||
// 15.2.1.16 Cyclic Module Records
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "vm/PromiseObject.h" // js::PromiseObject, js::PromiseResolvedWithUndefined
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "builtin/streams/HandlerFunction-inl.h" // js::NewHandler
|
||||
#include "builtin/HandlerFunction-inl.h" // js::NewHandler
|
||||
#include "builtin/streams/ReadableStreamReader-inl.h" // js::Unwrap{ReaderFromStream{,NoThrow},StreamFromReader}
|
||||
#include "vm/Compartment-inl.h"
|
||||
#include "vm/List-inl.h" // js::ListObject, js::StoreNewListInFixedSlot
|
||||
@ -105,7 +105,7 @@ const JSClass ByteStreamChunk::class_ = {
|
||||
* Note: All arguments must be same-compartment with cx. ReadableStream
|
||||
* controllers are always created in the same compartment as the stream.
|
||||
*/
|
||||
static MOZ_MUST_USE ReadableByteStreamController*
|
||||
[[nodiscard]] static ReadableByteStreamController*
|
||||
CreateReadableByteStreamController(JSContext* cx,
|
||||
Handle<ReadableStream*> stream,
|
||||
HandleValue underlyingByteSource,
|
||||
@ -252,7 +252,7 @@ class MOZ_RAII AutoClearUnderlyingSource {
|
||||
* Version of SetUpReadableByteStreamController that's specialized for handling
|
||||
* external, embedding-provided, underlying sources.
|
||||
*/
|
||||
MOZ_MUST_USE bool js::SetUpExternalReadableByteStreamController(
|
||||
[[nodiscard]] bool js::SetUpExternalReadableByteStreamController(
|
||||
JSContext* cx, Handle<ReadableStream*> stream,
|
||||
JS::ReadableStreamUnderlyingSource* source) {
|
||||
// Done elsewhere in the standard: Create the controller object.
|
||||
@ -388,13 +388,13 @@ JS_STREAMS_CLASS_SPEC(ReadableByteStreamController, 0, SlotCount,
|
||||
// Streams spec, 3.11.5.1. [[CancelSteps]] ()
|
||||
// Unified with 3.9.5.1 above.
|
||||
|
||||
static MOZ_MUST_USE bool ReadableByteStreamControllerHandleQueueDrain(
|
||||
[[nodiscard]] static bool ReadableByteStreamControllerHandleQueueDrain(
|
||||
JSContext* cx, Handle<ReadableStreamController*> unwrappedController);
|
||||
|
||||
/**
|
||||
* Streams spec, 3.11.5.2. [[PullSteps]] ( forAuthorCode )
|
||||
*/
|
||||
static MOZ_MUST_USE PromiseObject* ReadableByteStreamControllerPullSteps(
|
||||
[[nodiscard]] static PromiseObject* ReadableByteStreamControllerPullSteps(
|
||||
JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
|
||||
// Step 1: Let stream be this.[[controlledReadableByteStream]].
|
||||
Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
|
||||
@ -579,7 +579,7 @@ static MOZ_MUST_USE PromiseObject* ReadableByteStreamControllerPullSteps(
|
||||
* and
|
||||
* Streams spec, 3.11.5.2. [[PullSteps]] ( forAuthorCode )
|
||||
*/
|
||||
MOZ_MUST_USE PromiseObject* js::ReadableStreamControllerPullSteps(
|
||||
[[nodiscard]] PromiseObject* js::ReadableStreamControllerPullSteps(
|
||||
JSContext* cx, Handle<ReadableStreamController*> unwrappedController) {
|
||||
if (unwrappedController->is<ReadableStreamDefaultController>()) {
|
||||
Rooted<ReadableStreamDefaultController*> unwrappedDefaultController(
|
||||
@ -605,14 +605,14 @@ MOZ_MUST_USE PromiseObject* js::ReadableStreamControllerPullSteps(
|
||||
// ReadableByteStreamControllerCallPullIfNeeded ( controller )
|
||||
// Unified with 3.9.2 above.
|
||||
|
||||
static MOZ_MUST_USE bool ReadableByteStreamControllerInvalidateBYOBRequest(
|
||||
[[nodiscard]] static bool ReadableByteStreamControllerInvalidateBYOBRequest(
|
||||
JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController);
|
||||
|
||||
/**
|
||||
* Streams spec, 3.13.5.
|
||||
* ReadableByteStreamControllerClearPendingPullIntos ( controller )
|
||||
*/
|
||||
MOZ_MUST_USE bool js::ReadableByteStreamControllerClearPendingPullIntos(
|
||||
[[nodiscard]] bool js::ReadableByteStreamControllerClearPendingPullIntos(
|
||||
JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
|
||||
// Step 1: Perform
|
||||
// ! ReadableByteStreamControllerInvalidateBYOBRequest(controller).
|
||||
@ -630,7 +630,7 @@ MOZ_MUST_USE bool js::ReadableByteStreamControllerClearPendingPullIntos(
|
||||
/**
|
||||
* Streams spec, 3.13.6. ReadableByteStreamControllerClose ( controller )
|
||||
*/
|
||||
MOZ_MUST_USE bool js::ReadableByteStreamControllerClose(
|
||||
[[nodiscard]] bool js::ReadableByteStreamControllerClose(
|
||||
JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
|
||||
// Step 1: Let stream be controller.[[controlledReadableByteStream]].
|
||||
Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
|
||||
@ -707,7 +707,7 @@ MOZ_MUST_USE bool js::ReadableByteStreamControllerClose(
|
||||
* Streams spec, 3.13.15.
|
||||
* ReadableByteStreamControllerHandleQueueDrain ( controller )
|
||||
*/
|
||||
static MOZ_MUST_USE bool ReadableByteStreamControllerHandleQueueDrain(
|
||||
[[nodiscard]] static bool ReadableByteStreamControllerHandleQueueDrain(
|
||||
JSContext* cx, Handle<ReadableStreamController*> unwrappedController) {
|
||||
MOZ_ASSERT(unwrappedController->is<ReadableByteStreamController>());
|
||||
|
||||
@ -744,7 +744,7 @@ enum BYOBRequestSlots {
|
||||
* Streams spec 3.13.16.
|
||||
* ReadableByteStreamControllerInvalidateBYOBRequest ( controller )
|
||||
*/
|
||||
static MOZ_MUST_USE bool ReadableByteStreamControllerInvalidateBYOBRequest(
|
||||
[[nodiscard]] static bool ReadableByteStreamControllerInvalidateBYOBRequest(
|
||||
JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
|
||||
// Step 1: If controller.[[byobRequest]] is undefined, return.
|
||||
RootedValue unwrappedBYOBRequestVal(cx, unwrappedController->byobRequest());
|
||||
|
@ -5,8 +5,6 @@
|
||||
#ifndef builtin_Stream_h
|
||||
#define builtin_Stream_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
#include "js/RootingAPI.h" // JS::Handle
|
||||
|
||||
@ -18,15 +16,15 @@ class PromiseObject;
|
||||
class ReadableByteStreamController;
|
||||
class ReadableStreamController;
|
||||
|
||||
extern MOZ_MUST_USE bool ReadableByteStreamControllerClearPendingPullIntos(
|
||||
[[nodiscard]] extern bool ReadableByteStreamControllerClearPendingPullIntos(
|
||||
JSContext* cx,
|
||||
JS::Handle<ReadableByteStreamController*> unwrappedController);
|
||||
|
||||
extern MOZ_MUST_USE bool ReadableByteStreamControllerClose(
|
||||
[[nodiscard]] extern bool ReadableByteStreamControllerClose(
|
||||
JSContext* cx,
|
||||
JS::Handle<ReadableByteStreamController*> unwrappedController);
|
||||
|
||||
extern MOZ_MUST_USE PromiseObject* ReadableStreamControllerPullSteps(
|
||||
[[nodiscard]] extern PromiseObject* ReadableStreamControllerPullSteps(
|
||||
JSContext* cx, JS::Handle<ReadableStreamController*> unwrappedController);
|
||||
|
||||
} // namespace js
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "builtin/String.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
@ -57,7 +56,8 @@
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/ToSource.h" // js::ValueToSource
|
||||
#include "vm/ToSource.h" // js::ValueToSource
|
||||
#include "vm/WellKnownAtom.h" // js_*_str
|
||||
|
||||
#include "vm/InlineCharBuffer-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
@ -1998,7 +1998,7 @@ class StringSegmentRange {
|
||||
explicit StringSegmentRange(JSContext* cx)
|
||||
: stack(cx, StackVector(cx)), cur(cx) {}
|
||||
|
||||
MOZ_MUST_USE bool init(JSString* str) {
|
||||
[[nodiscard]] bool init(JSString* str) {
|
||||
MOZ_ASSERT(stack.empty());
|
||||
return settle(str);
|
||||
}
|
||||
@ -2010,7 +2010,7 @@ class StringSegmentRange {
|
||||
return cur;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool popFront() {
|
||||
[[nodiscard]] bool popFront() {
|
||||
MOZ_ASSERT(!empty());
|
||||
if (stack.empty()) {
|
||||
cur = nullptr;
|
||||
@ -3296,21 +3296,9 @@ JSString* js::str_replaceAll_string_raw(JSContext* cx, HandleString string,
|
||||
return ReplaceAll<Latin1Char, Latin1Char>(cx, str, search, repl);
|
||||
}
|
||||
|
||||
static ArrayObject* NewFullyAllocatedStringArray(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
uint32_t length) {
|
||||
ArrayObject* array = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static ArrayObject* SingleElementStringArray(JSContext* cx,
|
||||
HandleObjectGroup group,
|
||||
HandleLinearString str) {
|
||||
ArrayObject* array = NewFullyAllocatedStringArray(cx, group, 1);
|
||||
ArrayObject* array = NewDenseFullyAllocatedArray(cx, 1);
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -3321,8 +3309,7 @@ static ArrayObject* SingleElementStringArray(JSContext* cx,
|
||||
|
||||
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
|
||||
static ArrayObject* SplitHelper(JSContext* cx, HandleLinearString str,
|
||||
uint32_t limit, HandleLinearString sep,
|
||||
HandleObjectGroup group) {
|
||||
uint32_t limit, HandleLinearString sep) {
|
||||
size_t strLength = str->length();
|
||||
size_t sepLength = sep->length();
|
||||
MOZ_ASSERT(sepLength != 0);
|
||||
@ -3334,11 +3321,11 @@ static ArrayObject* SplitHelper(JSContext* cx, HandleLinearString str,
|
||||
|
||||
// Step 12.b.
|
||||
if (match != -1) {
|
||||
return NewFullyAllocatedArrayTryUseGroup(cx, group, 0);
|
||||
return NewDenseEmptyArray(cx);
|
||||
}
|
||||
|
||||
// Steps 12.c-e.
|
||||
return SingleElementStringArray(cx, group, str);
|
||||
return SingleElementStringArray(cx, str);
|
||||
}
|
||||
|
||||
// Step 3 (reordered).
|
||||
@ -3397,8 +3384,7 @@ static ArrayObject* SplitHelper(JSContext* cx, HandleLinearString str,
|
||||
|
||||
// Step 14.c.ii.5.
|
||||
if (splits.length() == limit) {
|
||||
return NewCopiedArrayTryUseGroup(cx, group, splits.begin(),
|
||||
splits.length());
|
||||
return NewDenseCopiedArray(cx, splits.length(), splits.begin());
|
||||
}
|
||||
|
||||
// Step 14.c.ii.6.
|
||||
@ -3418,15 +3404,15 @@ static ArrayObject* SplitHelper(JSContext* cx, HandleLinearString str,
|
||||
}
|
||||
|
||||
// Step 18.
|
||||
return NewCopiedArrayTryUseGroup(cx, group, splits.begin(), splits.length());
|
||||
return NewDenseCopiedArray(cx, splits.length(), splits.begin());
|
||||
}
|
||||
|
||||
// Fast-path for splitting a string into a character array via split("").
|
||||
static ArrayObject* CharSplitHelper(JSContext* cx, HandleLinearString str,
|
||||
uint32_t limit, HandleObjectGroup group) {
|
||||
uint32_t limit) {
|
||||
size_t strLength = str->length();
|
||||
if (strLength == 0) {
|
||||
return NewFullyAllocatedArrayTryUseGroup(cx, group, 0);
|
||||
return NewDenseEmptyArray(cx);
|
||||
}
|
||||
|
||||
js::StaticStrings& staticStrings = cx->staticStrings();
|
||||
@ -3435,8 +3421,7 @@ static ArrayObject* CharSplitHelper(JSContext* cx, HandleLinearString str,
|
||||
"Neither limit nor strLength is zero, so resultlen is greater "
|
||||
"than zero.");
|
||||
|
||||
RootedArrayObject splits(cx,
|
||||
NewFullyAllocatedStringArray(cx, group, resultlen));
|
||||
RootedArrayObject splits(cx, NewDenseFullyAllocatedArray(cx, resultlen));
|
||||
if (!splits) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -3452,7 +3437,7 @@ static ArrayObject* CharSplitHelper(JSContext* cx, HandleLinearString str,
|
||||
splits->initDenseElement(i, StringValue(staticStrings.getUnit(c)));
|
||||
}
|
||||
} else {
|
||||
splits->ensureDenseInitializedLength(cx, 0, resultlen);
|
||||
splits->ensureDenseInitializedLength(0, resultlen);
|
||||
|
||||
for (size_t i = 0; i < resultlen; ++i) {
|
||||
JSString* sub = staticStrings.getUnitStringForElement(cx, str, i);
|
||||
@ -3469,7 +3454,7 @@ static ArrayObject* CharSplitHelper(JSContext* cx, HandleLinearString str,
|
||||
template <typename TextChar>
|
||||
static MOZ_ALWAYS_INLINE ArrayObject* SplitSingleCharHelper(
|
||||
JSContext* cx, HandleLinearString str, const TextChar* text,
|
||||
uint32_t textLen, char16_t patCh, HandleObjectGroup group) {
|
||||
uint32_t textLen, char16_t patCh) {
|
||||
// Count the number of occurrences of patCh within text.
|
||||
uint32_t count = 0;
|
||||
for (size_t index = 0; index < textLen; index++) {
|
||||
@ -3480,16 +3465,15 @@ static MOZ_ALWAYS_INLINE ArrayObject* SplitSingleCharHelper(
|
||||
|
||||
// Handle zero-occurrence case - return input string in an array.
|
||||
if (count == 0) {
|
||||
return SingleElementStringArray(cx, group, str);
|
||||
return SingleElementStringArray(cx, str);
|
||||
}
|
||||
|
||||
// Create the result array for the substring values.
|
||||
RootedArrayObject splits(cx,
|
||||
NewFullyAllocatedStringArray(cx, group, count + 1));
|
||||
RootedArrayObject splits(cx, NewDenseFullyAllocatedArray(cx, count + 1));
|
||||
if (!splits) {
|
||||
return nullptr;
|
||||
}
|
||||
splits->ensureDenseInitializedLength(cx, 0, count + 1);
|
||||
splits->ensureDenseInitializedLength(0, count + 1);
|
||||
|
||||
// Add substrings.
|
||||
uint32_t splitsIndex = 0;
|
||||
@ -3519,8 +3503,7 @@ static MOZ_ALWAYS_INLINE ArrayObject* SplitSingleCharHelper(
|
||||
|
||||
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
|
||||
static ArrayObject* SplitSingleCharHelper(JSContext* cx, HandleLinearString str,
|
||||
char16_t ch,
|
||||
HandleObjectGroup group) {
|
||||
char16_t ch) {
|
||||
// Step 12.
|
||||
size_t strLength = str->length();
|
||||
|
||||
@ -3531,17 +3514,16 @@ static ArrayObject* SplitSingleCharHelper(JSContext* cx, HandleLinearString str,
|
||||
|
||||
if (linearChars.isLatin1()) {
|
||||
return SplitSingleCharHelper(cx, str, linearChars.latin1Chars(), strLength,
|
||||
ch, group);
|
||||
ch);
|
||||
}
|
||||
|
||||
return SplitSingleCharHelper(cx, str, linearChars.twoByteChars(), strLength,
|
||||
ch, group);
|
||||
ch);
|
||||
}
|
||||
|
||||
// ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
|
||||
ArrayObject* js::StringSplitString(JSContext* cx, HandleObjectGroup group,
|
||||
HandleString str, HandleString sep,
|
||||
uint32_t limit) {
|
||||
ArrayObject* js::StringSplitString(JSContext* cx, HandleString str,
|
||||
HandleString sep, uint32_t limit) {
|
||||
MOZ_ASSERT(limit > 0, "Only called for strictly positive limit.");
|
||||
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
@ -3555,15 +3537,15 @@ ArrayObject* js::StringSplitString(JSContext* cx, HandleObjectGroup group,
|
||||
}
|
||||
|
||||
if (linearSep->length() == 0) {
|
||||
return CharSplitHelper(cx, linearStr, limit, group);
|
||||
return CharSplitHelper(cx, linearStr, limit);
|
||||
}
|
||||
|
||||
if (linearSep->length() == 1 && limit >= static_cast<uint32_t>(INT32_MAX)) {
|
||||
char16_t ch = linearSep->latin1OrTwoByteChar(0);
|
||||
return SplitSingleCharHelper(cx, linearStr, ch, group);
|
||||
return SplitSingleCharHelper(cx, linearStr, ch);
|
||||
}
|
||||
|
||||
return SplitHelper(cx, linearStr, limit, linearSep, group);
|
||||
return SplitHelper(cx, linearStr, limit, linearSep);
|
||||
}
|
||||
|
||||
static const JSFunctionSpec string_methods[] = {
|
||||
|
@ -5,8 +5,6 @@
|
||||
#ifndef builtin_String_h
|
||||
#define builtin_String_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
@ -55,8 +53,8 @@ extern bool str_endsWith(JSContext* cx, unsigned argc, Value* vp);
|
||||
*
|
||||
* Usage: lowerCase = intl_toLocaleLowerCase(string, locale)
|
||||
*/
|
||||
extern MOZ_MUST_USE bool intl_toLocaleLowerCase(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool intl_toLocaleLowerCase(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
/**
|
||||
* Returns the input string converted to upper case based on the language
|
||||
@ -64,13 +62,12 @@ extern MOZ_MUST_USE bool intl_toLocaleLowerCase(JSContext* cx, unsigned argc,
|
||||
*
|
||||
* Usage: upperCase = intl_toLocaleUpperCase(string, locale)
|
||||
*/
|
||||
extern MOZ_MUST_USE bool intl_toLocaleUpperCase(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] extern bool intl_toLocaleUpperCase(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
#endif
|
||||
|
||||
ArrayObject* StringSplitString(JSContext* cx, Handle<ObjectGroup*> group,
|
||||
HandleString str, HandleString sep,
|
||||
uint32_t limit);
|
||||
ArrayObject* StringSplitString(JSContext* cx, HandleString str,
|
||||
HandleString sep, uint32_t limit);
|
||||
|
||||
JSString* StringFlatReplaceString(JSContext* cx, HandleString string,
|
||||
HandleString pattern,
|
||||
|
@ -35,24 +35,25 @@ class SymbolObject : public NativeObject {
|
||||
setFixedSlot(PRIMITIVE_VALUE_SLOT, SymbolValue(symbol));
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Static methods.
|
||||
static MOZ_MUST_USE bool for_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool keyFor(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool for_(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool keyFor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Methods defined on Symbol.prototype.
|
||||
static MOZ_MUST_USE bool toString_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool valueOf_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool valueOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool toPrimitive(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool toString_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool toString(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool valueOf_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool valueOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool toPrimitive(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
// Properties defined on Symbol.prototype.
|
||||
static MOZ_MUST_USE bool descriptionGetter_impl(JSContext* cx,
|
||||
const CallArgs& args);
|
||||
static MOZ_MUST_USE bool descriptionGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] static bool descriptionGetter_impl(JSContext* cx,
|
||||
const CallArgs& args);
|
||||
[[nodiscard]] static bool descriptionGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/TextUtils.h"
|
||||
@ -21,6 +22,7 @@
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_DARWIN)
|
||||
@ -42,13 +44,15 @@
|
||||
# include "frontend/TokenStream.h"
|
||||
#endif
|
||||
#include "frontend/BytecodeCompilation.h"
|
||||
#include "frontend/CompilationInfo.h" // frontend::CompilationInfo, frontend::CompilationInfoVector
|
||||
#include "frontend/CompilationStencil.h" // frontend::CompilationStencil
|
||||
#include "gc/Allocator.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/Disassemble.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "jit/Invalidation.h"
|
||||
#include "jit/Ion.h"
|
||||
#include "jit/JitOptions.h"
|
||||
#include "jit/JitRuntime.h"
|
||||
#include "jit/TrialInlining.h"
|
||||
#include "js/Array.h" // JS::NewArrayObject
|
||||
@ -86,6 +90,7 @@
|
||||
# include "unicode/utypes.h"
|
||||
# include "unicode/uversion.h"
|
||||
#endif
|
||||
#include "util/DifferentialTesting.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
@ -125,7 +130,6 @@
|
||||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::AssertedCast;
|
||||
using mozilla::AsWritableChars;
|
||||
using mozilla::Maybe;
|
||||
@ -183,6 +187,12 @@ static bool GetRealmConfiguration(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool topLevelAwait = cx->options().topLevelAwait();
|
||||
if (!JS_SetProperty(cx, info, "topLevelAwait",
|
||||
topLevelAwait ? TrueHandleValue : FalseHandleValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool offThreadParseGlobal = js::UseOffThreadParseGlobal();
|
||||
if (!JS_SetProperty(
|
||||
cx, info, "offThreadParseGlobal",
|
||||
@ -415,15 +425,6 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "more-deterministic", value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_PROFILING
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
@ -493,21 +494,10 @@ static bool IsLCovEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsTypeInferenceEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
// TODO(no-TI): remove testing function.
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TrialInline(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setUndefined();
|
||||
|
||||
if (!jit::JitOptions.warpBuilder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameIter iter(cx);
|
||||
if (iter.done() || !iter.isBaseline() || iter.realm() != cx->realm()) {
|
||||
return true;
|
||||
@ -556,7 +546,7 @@ static bool GC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
} else if (arg.isObject()) {
|
||||
PrepareZoneForGC(UncheckedUnwrap(&arg.toObject())->zone());
|
||||
PrepareZoneForGC(cx, UncheckedUnwrap(&arg.toObject())->zone());
|
||||
zone = true;
|
||||
}
|
||||
}
|
||||
@ -585,9 +575,7 @@ static bool GC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
size_t preBytes = cx->runtime()->gc.heapSize.bytes();
|
||||
#endif
|
||||
|
||||
if (zone) {
|
||||
PrepareForDebugGC(cx->runtime());
|
||||
@ -598,10 +586,10 @@ static bool GC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
JS::NonIncrementalGC(cx, gckind, reason);
|
||||
|
||||
char buf[256] = {'\0'};
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
SprintfLiteral(buf, "before %zu, after %zu\n", preBytes,
|
||||
cx->runtime()->gc.heapSize.bytes());
|
||||
#endif
|
||||
if (!js::SupportDifferentialTesting()) {
|
||||
SprintfLiteral(buf, "before %zu, after %zu\n", preBytes,
|
||||
cx->runtime()->gc.heapSize.bytes());
|
||||
}
|
||||
return ReturnStringCopy(cx, args, buf);
|
||||
}
|
||||
|
||||
@ -624,7 +612,10 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
_("gcBytes", JSGC_BYTES, false) \
|
||||
_("nurseryBytes", JSGC_NURSERY_BYTES, false) \
|
||||
_("gcNumber", JSGC_NUMBER, false) \
|
||||
_("mode", JSGC_MODE, true) \
|
||||
_("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \
|
||||
_("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \
|
||||
_("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \
|
||||
_("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \
|
||||
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
|
||||
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
|
||||
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
|
||||
@ -684,18 +675,17 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t paramIndex = 0;
|
||||
for (;; paramIndex++) {
|
||||
if (paramIndex == ArrayLength(paramMap)) {
|
||||
JS_ReportErrorASCII(
|
||||
cx, "the first argument must be one of:" GC_PARAMETER_ARGS_LIST);
|
||||
return false;
|
||||
}
|
||||
if (JS_LinearStringEqualsAscii(linearStr, paramMap[paramIndex].name)) {
|
||||
break;
|
||||
}
|
||||
const auto* ptr = std::find_if(
|
||||
std::begin(paramMap), std::end(paramMap), [&](const auto& param) {
|
||||
return JS_LinearStringEqualsAscii(linearStr, param.name);
|
||||
});
|
||||
if (ptr == std::end(paramMap)) {
|
||||
JS_ReportErrorASCII(
|
||||
cx, "the first argument must be one of:" GC_PARAMETER_ARGS_LIST);
|
||||
return false;
|
||||
}
|
||||
const ParamInfo& info = paramMap[paramIndex];
|
||||
|
||||
const ParamInfo& info = *ptr;
|
||||
JSGCParamKey param = info.param;
|
||||
|
||||
// Request mode.
|
||||
@ -853,12 +843,26 @@ static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool WasmExceptionsEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(wasm::ExceptionsAvailable(cx));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool WasmMultiValueEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(wasm::MultiValuesAvailable(cx));
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
static bool WasmSimdSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(wasm::SimdAvailable(cx));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool WasmCompilersPresent(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -1559,6 +1563,81 @@ static bool VerifyPostBarriers(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CurrentGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() != 0) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee, "Too many arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject result(cx, JS_NewPlainObject(cx));
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::gc::GCRuntime& gc = cx->runtime()->gc;
|
||||
const char* state = StateName(gc.state());
|
||||
|
||||
RootedString str(cx, JS_NewStringCopyZ(cx, state));
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
RootedValue val(cx, StringValue(str));
|
||||
if (!JS_DefineProperty(cx, result, "incrementalState", val,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gc.state() == js::gc::State::Sweep) {
|
||||
val = Int32Value(gc.getCurrentSweepGroupIndex());
|
||||
if (!JS_DefineProperty(cx, result, "sweepGroup", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
val = BooleanValue(gc.isShrinkingGC());
|
||||
if (!JS_DefineProperty(cx, result, "isShrinking", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = Int32Value(gc.gcNumber());
|
||||
if (!JS_DefineProperty(cx, result, "number", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = Int32Value(gc.minorGCCount());
|
||||
if (!JS_DefineProperty(cx, result, "minorCount", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = Int32Value(gc.majorGCCount());
|
||||
if (!JS_DefineProperty(cx, result, "majorCount", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = BooleanValue(gc.isFullGc());
|
||||
if (!JS_DefineProperty(cx, result, "isFull", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = BooleanValue(gc.isCompactingGc());
|
||||
if (!JS_DefineProperty(cx, result, "isCompacting", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
val = Int32Value(gc.marker.queuePos);
|
||||
if (!JS_DefineProperty(cx, result, "queuePos", val, JSPROP_ENUMERATE)) {
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DeterministicGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -1621,7 +1700,7 @@ static bool ScheduleZoneForGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (args[0].isObject()) {
|
||||
// Ensure that |zone| is collected during the next GC.
|
||||
Zone* zone = UncheckedUnwrap(&args[0].toObject())->zone();
|
||||
PrepareZoneForGC(zone);
|
||||
PrepareZoneForGC(cx, zone);
|
||||
} else if (args[0].isString()) {
|
||||
// This allows us to schedule the atoms zone for GC.
|
||||
Zone* zone = args[0].toString()->zoneFromAnyThread();
|
||||
@ -1630,7 +1709,7 @@ static bool ScheduleZoneForGC(JSContext* cx, unsigned argc, Value* vp) {
|
||||
ReportUsageErrorASCII(cx, callee, "Specified zone not accessible for GC");
|
||||
return false;
|
||||
}
|
||||
PrepareZoneForGC(zone);
|
||||
PrepareZoneForGC(cx, zone);
|
||||
} else {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
@ -1716,6 +1795,9 @@ static bool GCSlice(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (args.length() >= 1) {
|
||||
uint32_t work = 0;
|
||||
if (!ToUint32(cx, args[0], &work)) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
"The work budget parameter |n| must be an integer");
|
||||
return false;
|
||||
}
|
||||
budget = SliceBudget(WorkBudget(work));
|
||||
@ -2926,11 +3008,11 @@ static bool DumpHeap(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
static bool Terminate(JSContext* cx, unsigned arg, Value* vp) {
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
// Print a message to stderr in more-deterministic builds to help jsfunfuzz
|
||||
// Print a message to stderr in differential testing to help jsfunfuzz
|
||||
// find uncatchable-exception bugs.
|
||||
fprintf(stderr, "terminate called\n");
|
||||
#endif
|
||||
if (js::SupportDifferentialTesting()) {
|
||||
fprintf(stderr, "terminate called\n");
|
||||
}
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
return false;
|
||||
@ -3208,6 +3290,24 @@ static bool testingFunc_bailAfter(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool testingFunc_invalidate(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// If the topmost frame is Ion/Warp, find the IonScript and invalidate it.
|
||||
FrameIter iter(cx);
|
||||
if (!iter.done() && iter.isIon()) {
|
||||
while (!iter.isPhysicalJitFrame()) {
|
||||
++iter;
|
||||
}
|
||||
if (iter.script()->hasIonScript()) {
|
||||
js::jit::Invalidate(cx, iter.script());
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr unsigned JitWarmupResetLimit = 20;
|
||||
static_assert(JitWarmupResetLimit <=
|
||||
unsigned(JSScript::MutableFlags::WarmupResets_MASK),
|
||||
@ -3419,7 +3519,7 @@ class CloneBufferObject : public NativeObject {
|
||||
|
||||
const char* data = nullptr;
|
||||
UniqueChars dataOwner;
|
||||
uint32_t nbytes;
|
||||
size_t nbytes;
|
||||
|
||||
if (args.get(0).isObject() && args[0].toObject().is<ArrayBufferObject>()) {
|
||||
ArrayBufferObject* buffer = &args[0].toObject().as<ArrayBufferObject>();
|
||||
@ -3788,16 +3888,18 @@ static bool DetachArrayBuffer(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
static bool HelperThreadCount(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
// Always return 0 to get consistent output with and without --no-threads.
|
||||
args.rval().setInt32(0);
|
||||
#else
|
||||
|
||||
if (js::SupportDifferentialTesting()) {
|
||||
// Always return 0 to get consistent output with and without --no-threads.
|
||||
args.rval().setInt32(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CanUseExtraThreads()) {
|
||||
args.rval().setInt32(HelperThreadState().threadCount);
|
||||
} else {
|
||||
args.rval().setInt32(0);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3880,6 +3982,14 @@ static bool SharedArrayRawBufferRefcount(JSContext* cx, unsigned argc,
|
||||
#ifdef NIGHTLY_BUILD
|
||||
static bool ObjectAddress(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (js::SupportDifferentialTesting()) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
"Function unavailable in differential testing mode.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length() != 1) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
|
||||
@ -3891,20 +4001,23 @@ static bool ObjectAddress(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef JS_MORE_DETERMINISTIC
|
||||
args.rval().setInt32(0);
|
||||
return true;
|
||||
# else
|
||||
void* ptr = js::UncheckedUnwrap(&args[0].toObject(), true);
|
||||
char buffer[64];
|
||||
SprintfLiteral(buffer, "%p", ptr);
|
||||
|
||||
return ReturnStringCopy(cx, args, buffer);
|
||||
# endif
|
||||
}
|
||||
|
||||
static bool SharedAddress(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (js::SupportDifferentialTesting()) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
"Function unavailable in differential testing mode.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length() != 1) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
|
||||
@ -3916,9 +4029,6 @@ static bool SharedAddress(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef JS_MORE_DETERMINISTIC
|
||||
args.rval().setString(cx->staticStrings().getUint(0));
|
||||
# else
|
||||
RootedObject obj(cx, CheckedUnwrapStatic(&args[0].toObject()));
|
||||
if (!obj) {
|
||||
ReportAccessDenied(cx);
|
||||
@ -3940,7 +4050,6 @@ static bool SharedAddress(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
args.rval().setString(str);
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4021,8 +4130,21 @@ static bool ThrowOutOfMemory(JSContext* cx, unsigned argc, Value* vp) {
|
||||
static bool ReportLargeAllocationFailure(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
void* buf = cx->runtime()->onOutOfMemoryCanGC(
|
||||
AllocFunction::Malloc, js::MallocArena, JSRuntime::LARGE_ALLOCATION);
|
||||
|
||||
size_t bytes = JSRuntime::LARGE_ALLOCATION;
|
||||
if (args.length() >= 1) {
|
||||
if (!args[0].isInt32()) {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
"First argument must be an integer if specified.");
|
||||
return false;
|
||||
}
|
||||
bytes = args[0].toInt32();
|
||||
}
|
||||
|
||||
void* buf = cx->runtime()->onOutOfMemoryCanGC(AllocFunction::Malloc,
|
||||
js::MallocArena, bytes);
|
||||
|
||||
js_free(buf);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
@ -4227,7 +4349,7 @@ static bool FindPath(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
result->ensureDenseInitializedLength(cx, 0, length);
|
||||
result->ensureDenseInitializedLength(0, length);
|
||||
|
||||
// Walk |nodes| and |edges| in the stored order, and construct the result
|
||||
// array in start-to-target order.
|
||||
@ -4420,7 +4542,7 @@ static bool ShortestPaths(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!results) {
|
||||
return false;
|
||||
}
|
||||
results->ensureDenseInitializedLength(cx, 0, length);
|
||||
results->ensureDenseInitializedLength(0, length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
size_t numPaths = values[i].length();
|
||||
@ -4430,7 +4552,7 @@ static bool ShortestPaths(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!pathsArray) {
|
||||
return false;
|
||||
}
|
||||
pathsArray->ensureDenseInitializedLength(cx, 0, numPaths);
|
||||
pathsArray->ensureDenseInitializedLength(0, numPaths);
|
||||
|
||||
for (size_t j = 0; j < numPaths; j++) {
|
||||
size_t pathLength = values[i][j].length();
|
||||
@ -4440,7 +4562,7 @@ static bool ShortestPaths(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
path->ensureDenseInitializedLength(cx, 0, pathLength);
|
||||
path->ensureDenseInitializedLength(0, pathLength);
|
||||
|
||||
for (size_t k = 0; k < pathLength; k++) {
|
||||
RootedPlainObject part(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
@ -4540,7 +4662,6 @@ static bool EvalReturningScope(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
RootedObject varObj(cx);
|
||||
RootedObject lexicalScope(cx);
|
||||
|
||||
{
|
||||
// If we're switching globals here, ExecuteInFrameScriptEnvironment will
|
||||
@ -4552,35 +4673,21 @@ static bool EvalReturningScope(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject lexicalScope(cx);
|
||||
if (!js::ExecuteInFrameScriptEnvironment(cx, obj, script, &lexicalScope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
varObj = lexicalScope->enclosingEnvironment()->enclosingEnvironment();
|
||||
}
|
||||
|
||||
RootedObject rv(cx, JS_NewPlainObject(cx));
|
||||
if (!rv) {
|
||||
return false;
|
||||
MOZ_ASSERT(varObj->is<NonSyntacticVariablesObject>());
|
||||
}
|
||||
|
||||
RootedValue varObjVal(cx, ObjectValue(*varObj));
|
||||
if (!cx->compartment()->wrap(cx, &varObjVal)) {
|
||||
return false;
|
||||
}
|
||||
if (!JS_SetProperty(cx, rv, "vars", varObjVal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue lexicalScopeVal(cx, ObjectValue(*lexicalScope));
|
||||
if (!cx->compartment()->wrap(cx, &lexicalScopeVal)) {
|
||||
return false;
|
||||
}
|
||||
if (!JS_SetProperty(cx, rv, "lexicals", lexicalScopeVal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*rv);
|
||||
args.rval().set(varObjVal);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4680,7 +4787,7 @@ static bool ByteSizeOfScript(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
|
||||
if (fun->isNative()) {
|
||||
if (fun->isNativeFun()) {
|
||||
JS_ReportErrorASCII(cx, "Argument must be a scripted function");
|
||||
return false;
|
||||
}
|
||||
@ -4770,16 +4877,6 @@ static bool GetStringRepresentation(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
#endif
|
||||
|
||||
static bool SetLazyParsingDisabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
bool disable = !args.hasDefined(0) || ToBoolean(args[0]);
|
||||
cx->realm()->behaviors().setDisableLazyParsing(disable);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CompileStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -4814,20 +4911,21 @@ static bool CompileStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
/* TODO: StencilXDR - Add option to select between full and syntax parse. */
|
||||
options.setForceFullParse();
|
||||
|
||||
Rooted<frontend::CompilationInfo> compilationInfo(
|
||||
cx, frontend::CompilationInfo(cx, options));
|
||||
if (!compilationInfo.get().input.initForGlobal(cx)) {
|
||||
return false;
|
||||
}
|
||||
if (!frontend::CompileGlobalScriptToStencil(cx, compilationInfo.get(), srcBuf,
|
||||
ScopeKind::Global)) {
|
||||
Rooted<frontend::CompilationInput> input(cx,
|
||||
frontend::CompilationInput(options));
|
||||
auto stencil = frontend::CompileGlobalScriptToExtensibleStencil(
|
||||
cx, input.get(), srcBuf, ScopeKind::Global);
|
||||
if (!stencil) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Serialize the stencil to XDR. */
|
||||
JS::TranscodeBuffer xdrBytes;
|
||||
if (!compilationInfo.get().serializeStencils(cx, xdrBytes)) {
|
||||
return false;
|
||||
{
|
||||
frontend::BorrowingCompilationStencil borrowingStencil(*stencil);
|
||||
if (!borrowingStencil.serializeStencils(cx, input.get(), xdrBytes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump the bytes into a javascript ArrayBuffer and return a UInt8Array. */
|
||||
@ -4864,21 +4962,22 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
const char* filename = "compileStencilXDR-DATA.js";
|
||||
uint32_t lineno = 1;
|
||||
|
||||
/* Prepare the CompilationInfoVector for decoding. */
|
||||
/* Prepare the CompilationStencil for decoding. */
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(filename, lineno);
|
||||
options.setForceFullParse();
|
||||
|
||||
Rooted<frontend::CompilationInfoVector> compilationInfos(
|
||||
cx, frontend::CompilationInfoVector(cx, options));
|
||||
if (!compilationInfos.get().initial.input.initForGlobal(cx)) {
|
||||
Rooted<frontend::CompilationInput> input(cx,
|
||||
frontend::CompilationInput(options));
|
||||
if (!input.get().initForGlobal(cx)) {
|
||||
return false;
|
||||
}
|
||||
frontend::CompilationStencil stencil(nullptr);
|
||||
|
||||
/* Deserialize the stencil from XDR. */
|
||||
JS::TranscodeRange xdrRange(src->dataPointer(), src->byteLength().get());
|
||||
bool succeeded = false;
|
||||
if (!compilationInfos.get().deserializeStencils(cx, xdrRange, &succeeded)) {
|
||||
if (!stencil.deserializeStencils(cx, input.get(), xdrRange, &succeeded)) {
|
||||
return false;
|
||||
}
|
||||
if (!succeeded) {
|
||||
@ -4888,7 +4987,10 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
|
||||
/* Instantiate the stencil. */
|
||||
Rooted<frontend::CompilationGCOutput> output(cx);
|
||||
if (!compilationInfos.get().instantiateStencils(cx, output.get())) {
|
||||
Rooted<frontend::CompilationGCOutput> outputForDelazification(cx);
|
||||
if (!frontend::CompilationStencil::instantiateStencils(
|
||||
cx, input.get(), stencil, output.get(),
|
||||
outputForDelazification.address())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4903,16 +5005,6 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SetDiscardSource(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
bool discard = !args.hasDefined(0) || ToBoolean(args[0]);
|
||||
cx->realm()->behaviors().setDiscardSource(discard);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
class AllocationMarkerObject : public NativeObject {
|
||||
public:
|
||||
static const JSClass class_;
|
||||
@ -5157,6 +5249,24 @@ static bool ClearMarkQueue(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
static bool NurseryStringsEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(cx->zone()->allocNurseryStrings);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsNurseryAllocated(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args.get(0).isGCThing()) {
|
||||
JS_ReportErrorASCII(
|
||||
cx, "The function takes one argument, which must be a GC thing");
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setBoolean(IsInsideNursery(args[0].toGCThing()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetLcovInfo(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -5813,9 +5923,9 @@ static bool EncodeAsUtf8InBuffer(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!array) {
|
||||
return false;
|
||||
}
|
||||
array->ensureDenseInitializedLength(cx, 0, 2);
|
||||
array->ensureDenseInitializedLength(0, 2);
|
||||
|
||||
uint32_t length;
|
||||
size_t length;
|
||||
bool isSharedMemory;
|
||||
uint8_t* data;
|
||||
if (!args[1].isObject() ||
|
||||
@ -5938,14 +6048,12 @@ static bool BaselineCompile(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
const char* returnedStr = nullptr;
|
||||
do {
|
||||
#ifdef JS_MORE_DETERMINISTIC
|
||||
// In order to check for differential behaviour, baselineCompile should have
|
||||
// the same output whether --no-baseline is used or not.
|
||||
if (fuzzingSafe) {
|
||||
returnedStr = "skipped (fuzzing-safe)";
|
||||
if (js::SupportDifferentialTesting()) {
|
||||
returnedStr = "skipped (differential testing)";
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
AutoRealm ar(cx, script);
|
||||
if (script->hasBaselineScript()) {
|
||||
@ -6075,6 +6183,36 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsSmallFunction(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedObject callee(cx, &args.callee());
|
||||
|
||||
if (!args.requireAtLeast(cx, "IsSmallFunction", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HandleValue arg = args[0];
|
||||
if (!arg.isObject() || !arg.toObject().is<JSFunction>()) {
|
||||
ReportUsageErrorASCII(cx, callee, "First argument must be a function");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
|
||||
if (!fun->isInterpreted()) {
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
"First argument must be an interpreted function");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSScript* script = JSFunction::getOrCreateScript(cx, fun);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setBoolean(jit::JitOptions.isSmallFunction(script));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool PCCountProfiling_Start(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -6201,10 +6339,6 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
"isLcovEnabled()",
|
||||
" Return true if JS LCov support is enabled."),
|
||||
|
||||
JS_FN_HELP("isTypeInferenceEnabled", ::IsTypeInferenceEnabled, 0, 0,
|
||||
"isTypeInferenceEnabled()",
|
||||
" Return true if Type Inference is enabled."),
|
||||
|
||||
JS_FN_HELP("trialInline", TrialInline, 0, 0,
|
||||
"trialInline()",
|
||||
" Perform trial-inlining for the caller's frame if it's a BaselineFrame."),
|
||||
@ -6433,6 +6567,11 @@ gc::ZealModeHelpText),
|
||||
"verifypostbarriers()",
|
||||
" Does nothing (the post-write barrier verifier has been remove)."),
|
||||
|
||||
JS_FN_HELP("currentgc", CurrentGC, 0, 0,
|
||||
"currentgc()",
|
||||
" Report various information about the currently running incremental GC,\n"
|
||||
" if one is running."),
|
||||
|
||||
JS_FN_HELP("deterministicgc", DeterministicGC, 1, 0,
|
||||
"deterministicgc(true|false)",
|
||||
" If true, only allow determinstic GCs to run."),
|
||||
@ -6568,6 +6707,13 @@ gc::ZealModeHelpText),
|
||||
" Returns a boolean indicating whether the WebAssembly threads proposal is\n"
|
||||
" supported on the current device."),
|
||||
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
JS_FN_HELP("wasmSimdSupported", WasmSimdSupported, 0, 0,
|
||||
"wasmSimdSupported()",
|
||||
" Returns a boolean indicating whether WebAssembly SIMD is supported by the\n"
|
||||
" compilers and runtime."),
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("wasmReftypesEnabled", WasmReftypesEnabled, 1, 0,
|
||||
"wasmReftypesEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly reftypes proposal is enabled."),
|
||||
@ -6584,6 +6730,10 @@ gc::ZealModeHelpText),
|
||||
"wasmMultiValueEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly multi-value proposal is enabled."),
|
||||
|
||||
JS_FN_HELP("wasmExceptionsEnabled", WasmExceptionsEnabled, 1, 0,
|
||||
"wasmExceptionsEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly exceptions proposal is enabled."),
|
||||
|
||||
#if defined(ENABLE_WASM_SIMD) && defined(DEBUG)
|
||||
JS_FN_HELP("wasmSimdAnalysis", WasmSimdAnalysis, 1, 0,
|
||||
"wasmSimdAnalysis(...)",
|
||||
@ -6670,6 +6820,9 @@ gc::ZealModeHelpText),
|
||||
" Start a counter to bail once after passing the given amount of possible bailout positions in\n"
|
||||
" ionmonkey.\n"),
|
||||
|
||||
JS_FN_HELP("invalidate", testingFunc_invalidate, 0, 0,
|
||||
"invalidate()",
|
||||
" Force an immediate invalidation (if running in Warp)."),
|
||||
|
||||
JS_FN_HELP("inJit", testingFunc_inJit, 0, 0,
|
||||
"inJit()",
|
||||
@ -6750,7 +6903,7 @@ gc::ZealModeHelpText),
|
||||
" Throw out of memory exception, for OOM handling testing."),
|
||||
|
||||
JS_FN_HELP("reportLargeAllocationFailure", ReportLargeAllocationFailure, 0, 0,
|
||||
"reportLargeAllocationFailure()",
|
||||
"reportLargeAllocationFailure([bytes])",
|
||||
" Call the large allocation failure callback, as though a large malloc call failed,\n"
|
||||
" then return undefined. In Gecko, this sends a memory pressure notification, which\n"
|
||||
" can free up some memory."),
|
||||
@ -6858,16 +7011,6 @@ gc::ZealModeHelpText),
|
||||
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("setLazyParsingDisabled", SetLazyParsingDisabled, 1, 0,
|
||||
"setLazyParsingDisabled(bool)",
|
||||
" Explicitly disable lazy parsing in the current compartment. The default is that lazy "
|
||||
" parsing is not explicitly disabled."),
|
||||
|
||||
JS_FN_HELP("setDiscardSource", SetDiscardSource, 1, 0,
|
||||
"setDiscardSource(bool)",
|
||||
" Explicitly enable source discarding in the current compartment. The default is that "
|
||||
" source discarding is not explicitly enabled."),
|
||||
|
||||
JS_FN_HELP("allocationMarker", AllocationMarker, 0, 0,
|
||||
"allocationMarker([options])",
|
||||
" Return a freshly allocated object whose [[Class]] name is\n"
|
||||
@ -6915,6 +7058,15 @@ gc::ZealModeHelpText),
|
||||
" some fidelity."),
|
||||
#endif // DEBUG
|
||||
|
||||
JS_FN_HELP("nurseryStringsEnabled", NurseryStringsEnabled, 0, 0,
|
||||
"nurseryStringsEnabled()",
|
||||
" Return whether strings are currently allocated in the nursery for current\n"
|
||||
" global\n"),
|
||||
|
||||
JS_FN_HELP("isNurseryAllocated", IsNurseryAllocated, 1, 0,
|
||||
"isNurseryAllocated(thing)",
|
||||
" Return whether a GC thing is nursery allocated.\n"),
|
||||
|
||||
JS_FN_HELP("getLcovInfo", GetLcovInfo, 1, 0,
|
||||
"getLcovInfo(global)",
|
||||
" Generate LCOV tracefile for the given compartment. If no global are provided then\n"
|
||||
@ -7038,6 +7190,10 @@ JS_FN_HELP("getICUOptions", GetICUOptions, 0, 0,
|
||||
" timezone: the ICU default time zone, e.g. 'America/Los_Angeles'\n"
|
||||
" host-timezone: the host time zone, e.g. 'America/Los_Angeles'"),
|
||||
|
||||
JS_FN_HELP("isSmallFunction", IsSmallFunction, 1, 0,
|
||||
"isSmallFunction(fun)",
|
||||
" Returns true if a scripted function is small enough to be inlinable."),
|
||||
|
||||
JS_FS_HELP_END
|
||||
};
|
||||
// clang-format on
|
||||
|
@ -9,21 +9,21 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
MOZ_MUST_USE bool InitTestingFunctions();
|
||||
[[nodiscard]] bool InitTestingFunctions();
|
||||
|
||||
MOZ_MUST_USE bool DefineTestingFunctions(JSContext* cx, HandleObject obj,
|
||||
bool fuzzingSafe,
|
||||
bool disableOOMFunctions);
|
||||
[[nodiscard]] bool DefineTestingFunctions(JSContext* cx, HandleObject obj,
|
||||
bool fuzzingSafe,
|
||||
bool disableOOMFunctions);
|
||||
|
||||
MOZ_MUST_USE bool testingFunc_assertFloat32(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] bool testingFunc_assertFloat32(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool testingFunc_assertRecoveredOnBailout(JSContext* cx,
|
||||
unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] bool testingFunc_assertRecoveredOnBailout(JSContext* cx,
|
||||
unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool testingFunc_serialize(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
[[nodiscard]] bool testingFunc_serialize(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
|
||||
extern JSScript* TestingFunctionArgumentToScript(JSContext* cx, HandleValue v,
|
||||
JSFunction** funp = nullptr);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user