summaryrefslogtreecommitdiffstats
path: root/js/src/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin')
-rw-r--r--js/src/builtin/Array.js108
-rw-r--r--js/src/builtin/AtomicsObject.cpp27
-rw-r--r--js/src/builtin/AtomicsObject.h26
-rw-r--r--js/src/builtin/Intl.cpp31
-rw-r--r--js/src/builtin/IntlTimeZoneData.h2
-rw-r--r--js/src/builtin/MapObject.cpp4
-rw-r--r--js/src/builtin/ModuleObject.cpp10
-rw-r--r--js/src/builtin/ModuleObject.h2
-rw-r--r--js/src/builtin/Object.cpp393
-rw-r--r--js/src/builtin/Object.h3
-rw-r--r--js/src/builtin/Object.js6
-rw-r--r--js/src/builtin/Promise.cpp129
-rw-r--r--js/src/builtin/Promise.h8
-rw-r--r--js/src/builtin/Reflect.cpp3
-rw-r--r--js/src/builtin/ReflectParse.cpp31
-rw-r--r--js/src/builtin/RegExp.cpp18
-rw-r--r--js/src/builtin/RegExp.h2
-rw-r--r--js/src/builtin/SIMD.cpp22
-rw-r--r--js/src/builtin/String.js12
-rw-r--r--js/src/builtin/SymbolObject.cpp37
-rw-r--r--js/src/builtin/SymbolObject.h4
-rw-r--r--js/src/builtin/TestingFunctions.cpp44
-rw-r--r--js/src/builtin/TypedObject.cpp30
-rw-r--r--js/src/builtin/Utilities.js63
-rw-r--r--js/src/builtin/WeakMapObject.cpp6
-rw-r--r--js/src/builtin/WeakSetObject.cpp7
-rw-r--r--js/src/builtin/WeakSetObject.h2
27 files changed, 634 insertions, 396 deletions
diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js
index 30e6fb35f..05fc41bc1 100644
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -1073,6 +1073,114 @@ function ArrayConcat(arg1) {
return A;
}
+// https://tc39.github.io/proposal-flatMap/
+// January 4, 2019
+function ArrayFlatMap(mapperFunction/*, thisArg*/) {
+ // Step 1.
+ var O = ToObject(this);
+
+ // Step 2.
+ var sourceLen = ToLength(O.length);
+
+ // Step 3.
+ if (!IsCallable(mapperFunction))
+ ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction));
+
+ // Step 4.
+ var T = arguments.length > 1 ? arguments[1] : undefined;
+
+ // Step 5.
+ var A = ArraySpeciesCreate(O, 0);
+
+ // Step 6.
+ FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T);
+
+ // Step 7.
+ return A;
+}
+
+// https://tc39.github.io/proposal-flatMap/
+// January 4, 2019
+function ArrayFlat(/* depth */) {
+ // Step 1.
+ var O = ToObject(this);
+
+ // Step 2.
+ var sourceLen = ToLength(O.length);
+
+ // Step 3.
+ var depthNum = 1;
+
+ // Step 4.
+ if (arguments.length > 0 && arguments[0] !== undefined)
+ depthNum = ToInteger(arguments[0]);
+
+ // Step 5.
+ var A = ArraySpeciesCreate(O, 0);
+
+ // Step 6.
+ FlattenIntoArray(A, O, sourceLen, 0, depthNum);
+
+ // Step 7.
+ return A;
+}
+
+// https://tc39.github.io/proposal-flatMap/
+// January 4, 2019
+function FlattenIntoArray(target, source, sourceLen, start, depth, mapperFunction, thisArg) {
+ // Step 1.
+ var targetIndex = start;
+
+ // Steps 2-3.
+ for (var sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
+ // Steps 3.a-c.
+ if (sourceIndex in source) {
+ // Step 3.c.i.
+ var element = source[sourceIndex];
+
+ if (mapperFunction) {
+ // Step 3.c.ii.1.
+ assert(arguments.length === 7, "thisArg is present");
+
+ // Step 3.c.ii.2.
+ element = callContentFunction(mapperFunction, thisArg, element, sourceIndex, source);
+ }
+
+ // Step 3.c.iii.
+ var shouldFlatten = false;
+
+ // Step 3.c.iv.
+ if (depth > 0) {
+ // Step 3.c.iv.1.
+ shouldFlatten = IsArray(element);
+ }
+
+ // Step 3.c.v.
+ if (shouldFlatten) {
+ // Step 3.c.v.1.
+ var elementLen = ToLength(element.length);
+
+ // Step 3.c.v.2.
+ // Recursive call to walk the depth.
+ targetIndex = FlattenIntoArray(target, element, elementLen, targetIndex, depth - 1);
+ } else {
+ // Step 3.c.vi.1.
+ if (targetIndex >= MAX_NUMERIC_INDEX)
+ ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
+
+ // Step 3.c.vi.2.
+ _DefineDataProperty(target, targetIndex, element);
+
+ // Step 3.c.vi.3.
+ targetIndex++;
+ }
+ }
+ }
+
+ // Step 4.
+ return targetIndex;
+}
+
function ArrayStaticConcat(arr, arg1) {
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');
diff --git a/js/src/builtin/AtomicsObject.cpp b/js/src/builtin/AtomicsObject.cpp
index 08777fd51..ceee83349 100644
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -789,7 +789,7 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
// and it provides the necessary memory fence.
AutoLockFutexAPI lock;
- SharedMem<int32_t*>(addr) = view->viewDataShared().cast<int32_t*>() + offset;
+ SharedMem<int32_t*> addr = view->viewDataShared().cast<int32_t*>() + offset;
if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) {
r.setString(cx->names().futexNotEqual);
return true;
@@ -834,7 +834,7 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
}
bool
-js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
+js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
HandleValue objv = args.get(0);
@@ -874,7 +874,7 @@ js::atomics_wake(JSContext* cx, unsigned argc, Value* vp)
iter = iter->lower_pri;
if (c->offset != offset || !c->rt->fx.isWaiting())
continue;
- c->rt->fx.wake(FutexRuntime::WakeExplicit);
+ c->rt->fx.notify(FutexRuntime::NotifyExplicit);
++woken;
--count;
} while (count > 0 && iter != waiters);
@@ -950,7 +950,7 @@ js::FutexRuntime::isWaiting()
// When a worker is awoken for an interrupt it goes into state
// WaitingNotifiedForInterrupt for a short time before it actually
// wakes up and goes into WaitingInterrupted. In those states the
- // worker is still waiting, and if an explicit wake arrives the
+ // worker is still waiting, and if an explicit notify arrives the
// worker transitions to Woken. See further comments in
// FutexRuntime::wait().
return state_ == Waiting || state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt;
@@ -1029,14 +1029,14 @@ js::FutexRuntime::wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
// should be woken when the interrupt handler returns.
// To that end, we flag the thread as interrupted around
// the interrupt and check state_ when the interrupt
- // handler returns. A wake() call that reaches the
+ // handler returns. A notify() call that reaches the
// runtime during the interrupt sets state_ to Woken.
//
// - It is in principle possible for wait() to be
// reentered on the same thread/runtime and waiting on the
// same location and to yet again be interrupted and enter
// the interrupt handler. In this case, it is important
- // that when another agent wakes waiters, all waiters using
+ // that when another agent notifies waiters, all waiters using
// the same runtime on the same location are woken in LIFO
// order; FIFO may be the required order, but FIFO would
// fail to wake up the innermost call. Interrupts are
@@ -1073,25 +1073,25 @@ finished:
}
void
-js::FutexRuntime::wake(WakeReason reason)
+js::FutexRuntime::notify(NotifyReason reason)
{
MOZ_ASSERT(isWaiting());
- if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == WakeExplicit) {
+ if ((state_ == WaitingInterrupted || state_ == WaitingNotifiedForInterrupt) && reason == NotifyExplicit) {
state_ = Woken;
return;
}
switch (reason) {
- case WakeExplicit:
+ case NotifyExplicit:
state_ = Woken;
break;
- case WakeForJSInterrupt:
+ case NotifyForJSInterrupt:
if (state_ == WaitingNotifiedForInterrupt)
return;
state_ = WaitingNotifiedForInterrupt;
break;
default:
- MOZ_CRASH("bad WakeReason in FutexRuntime::wake()");
+ MOZ_CRASH("bad NotifyReason in FutexRuntime::notify()");
}
cond_->notify_all();
}
@@ -1108,7 +1108,8 @@ const JSFunctionSpec AtomicsMethods[] = {
JS_INLINABLE_FN("xor", atomics_xor, 3,0, AtomicsXor),
JS_INLINABLE_FN("isLockFree", atomics_isLockFree, 1,0, AtomicsIsLockFree),
JS_FN("wait", atomics_wait, 4,0),
- JS_FN("wake", atomics_wake, 3,0),
+ JS_FN("notify", atomics_notify, 3,0),
+ JS_FN("wake", atomics_notify, 3,0), //Legacy name
JS_FS_END
};
@@ -1116,7 +1117,7 @@ JSObject*
AtomicsObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
{
// Create Atomics Object.
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return nullptr;
RootedObject Atomics(cx, NewObjectWithGivenProto(cx, &AtomicsObject::class_, objProto,
diff --git a/js/src/builtin/AtomicsObject.h b/js/src/builtin/AtomicsObject.h
index adb6fb986..6511dc8bf 100644
--- a/js/src/builtin/AtomicsObject.h
+++ b/js/src/builtin/AtomicsObject.h
@@ -36,7 +36,7 @@ MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
-MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_notify(JSContext* cx, unsigned argc, Value* vp);
/* asm.js callouts */
namespace wasm { class Instance; }
@@ -63,10 +63,10 @@ public:
MOZ_MUST_USE bool initInstance();
void destroyInstance();
- // Parameters to wake().
- enum WakeReason {
- WakeExplicit, // Being asked to wake up by another thread
- WakeForJSInterrupt // Interrupt requested
+ // Parameters to notify().
+ enum NotifyReason {
+ NotifyExplicit, // Being asked to wake up by another thread
+ NotifyForJSInterrupt // Interrupt requested
};
// Result code from wait().
@@ -83,29 +83,27 @@ public:
// times allowed; specify mozilla::Nothing() for an indefinite
// wait.
//
- // wait() will not wake up spuriously. It will return true and
- // set *result to a return code appropriate for
- // Atomics.wait() on success, and return false on error.
+ // wait() will not wake up spuriously.
MOZ_MUST_USE bool wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
mozilla::Maybe<mozilla::TimeDuration>& timeout, WaitResult* result);
- // Wake the thread represented by this Runtime.
+ // Notify the thread represented by this Runtime.
//
// The futex lock must be held around this call. (The sleeping
- // thread will not wake up until the caller of Atomics.wake()
+ // thread will not wake up until the caller of Atomics.notify()
// releases the lock.)
//
// If the thread is not waiting then this method does nothing.
//
// If the thread is waiting in a call to wait() and the
- // reason is WakeExplicit then the wait() call will return
+ // reason is NotifyExplicit then the wait() call will return
// with Woken.
//
// If the thread is waiting in a call to wait() and the
- // reason is WakeForJSInterrupt then the wait() will return
+ // reason is NotifyForJSInterrupt then the wait() will return
// with WaitingNotifiedForInterrupt; in the latter case the caller
// of wait() must handle the interrupt.
- void wake(WakeReason reason);
+ void notify(NotifyReason reason);
bool isWaiting();
@@ -128,7 +126,7 @@ public:
// interrupt handler
WaitingInterrupted, // We are waiting, but have been interrupted
// and are running the interrupt handler
- Woken // Woken by a script call to Atomics.wake
+ Woken // Woken by a script call to Atomics.notify
};
// Condition variable that this runtime will wait on.
diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp
index 71f7b58d4..0cd0c62dd 100644
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -270,7 +270,7 @@ Collator(JSContext* cx, const CallArgs& args, bool construct)
// See https://github.com/tc39/ecma402/issues/57
if (!construct) {
// ES Intl 1st ed., 10.1.2.1 step 3
- JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
+ JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
if (!intl)
return false;
RootedValue self(cx, args.thisv());
@@ -298,7 +298,7 @@ Collator(JSContext* cx, const CallArgs& args, bool construct)
return false;
if (!proto) {
- proto = cx->global()->getOrCreateCollatorPrototype(cx);
+ proto = GlobalObject::getOrCreateCollatorPrototype(cx, cx->global());
if (!proto)
return false;
}
@@ -358,11 +358,12 @@ collator_finalize(FreeOp* fop, JSObject* obj)
static JSObject*
CreateCollatorPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
{
- RootedFunction ctor(cx, global->createConstructor(cx, &Collator, cx->names().Collator, 0));
+ RootedFunction ctor(cx, GlobalObject::createConstructor(cx, &Collator, cx->names().Collator,
+ 0));
if (!ctor)
return nullptr;
- RootedNativeObject proto(cx, global->createBlankPrototype(cx, &CollatorClass));
+ RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global, &CollatorClass));
if (!proto)
return nullptr;
proto->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr));
@@ -772,7 +773,7 @@ NumberFormat(JSContext* cx, const CallArgs& args, bool construct)
// See https://github.com/tc39/ecma402/issues/57
if (!construct) {
// ES Intl 1st ed., 11.1.2.1 step 3
- JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
+ JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
if (!intl)
return false;
RootedValue self(cx, args.thisv());
@@ -800,7 +801,7 @@ NumberFormat(JSContext* cx, const CallArgs& args, bool construct)
return false;
if (!proto) {
- proto = cx->global()->getOrCreateNumberFormatPrototype(cx);
+ proto = GlobalObject::getOrCreateNumberFormatPrototype(cx, cx->global());
if (!proto)
return false;
}
@@ -862,11 +863,12 @@ static JSObject*
CreateNumberFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
{
RootedFunction ctor(cx);
- ctor = global->createConstructor(cx, &NumberFormat, cx->names().NumberFormat, 0);
+ ctor = GlobalObject::createConstructor(cx, &NumberFormat, cx->names().NumberFormat, 0);
if (!ctor)
return nullptr;
- RootedNativeObject proto(cx, global->createBlankPrototype(cx, &NumberFormatClass));
+ RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
+ &NumberFormatClass));
if (!proto)
return nullptr;
proto->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr));
@@ -1250,7 +1252,7 @@ DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct)
// See https://github.com/tc39/ecma402/issues/57
if (!construct) {
// ES Intl 1st ed., 12.1.2.1 step 3
- JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
+ JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
if (!intl)
return false;
RootedValue self(cx, args.thisv());
@@ -1278,7 +1280,7 @@ DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct)
return false;
if (!proto) {
- proto = cx->global()->getOrCreateDateTimeFormatPrototype(cx);
+ proto = GlobalObject::getOrCreateDateTimeFormatPrototype(cx, cx->global());
if (!proto)
return false;
}
@@ -1340,11 +1342,12 @@ static JSObject*
CreateDateTimeFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
{
RootedFunction ctor(cx);
- ctor = global->createConstructor(cx, &DateTimeFormat, cx->names().DateTimeFormat, 0);
+ ctor = GlobalObject::createConstructor(cx, &DateTimeFormat, cx->names().DateTimeFormat, 0);
if (!ctor)
return nullptr;
- RootedNativeObject proto(cx, global->createBlankPrototype(cx, &DateTimeFormatClass));
+ RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
+ &DateTimeFormatClass));
if (!proto)
return nullptr;
proto->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr));
@@ -2731,10 +2734,10 @@ static const JSFunctionSpec intl_static_methods[] = {
* Initializes the Intl Object and its standard built-in properties.
* Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
*/
-bool
+/* static */ bool
GlobalObject::initIntlObject(JSContext* cx, Handle<GlobalObject*> global)
{
- RootedObject proto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!proto)
return false;
diff --git a/js/src/builtin/IntlTimeZoneData.h b/js/src/builtin/IntlTimeZoneData.h
index fa808c0b9..1612f0f6b 100644
--- a/js/src/builtin/IntlTimeZoneData.h
+++ b/js/src/builtin/IntlTimeZoneData.h
@@ -1,5 +1,5 @@
// Generated by make_intl_data.py. DO NOT EDIT.
-// tzdata version = 2018e
+// tzdata version = 2019c
#ifndef builtin_IntlTimeZoneData_h
#define builtin_IntlTimeZoneData_h
diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp
index c496cfb77..34e2e566d 100644
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -164,7 +164,7 @@ MapIteratorObject::kind() const
return MapObject::IteratorKind(i);
}
-bool
+/* static */ bool
GlobalObject::initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
{
Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
@@ -924,7 +924,7 @@ SetIteratorObject::kind() const
return SetObject::IteratorKind(i);
}
-bool
+/* static */ bool
GlobalObject::initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
{
Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 333cb3e11..575bab0b0 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -103,7 +103,7 @@ GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
JS_PS_END
};
- RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
+ RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!proto)
return false;
@@ -169,7 +169,7 @@ GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
JS_PS_END
};
- RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
+ RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!proto)
return false;
@@ -768,7 +768,7 @@ AssertModuleScopesMatch(ModuleObject* module)
}
void
-ModuleObject::fixEnvironmentsAfterCompartmentMerge(JSContext* cx)
+ModuleObject::fixEnvironmentsAfterCompartmentMerge()
{
AssertModuleScopesMatch(this);
initialEnvironment().fixEnclosingEnvironmentAfterCompartmentMerge(script()->global());
@@ -927,7 +927,7 @@ ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValu
ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
{
MOZ_ASSERT(!self->namespace_());
- MOZ_ASSERT(exports->is<ArrayObject>() || exports->is<UnboxedArrayObject>());
+ MOZ_ASSERT(exports->is<ArrayObject>());
RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
if (!ns)
@@ -1000,7 +1000,7 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
JS_FS_END
};
- RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
+ RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!proto)
return false;
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 51a428271..22db762ac 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -237,7 +237,7 @@ class ModuleObject : public NativeObject
#ifdef DEBUG
static bool IsFrozen(JSContext* cx, HandleModuleObject self);
#endif
- void fixEnvironmentsAfterCompartmentMerge(JSContext* cx);
+ void fixEnvironmentsAfterCompartmentMerge();
JSScript* script() const;
Scope* enclosingScope() const;
diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp
index cd4ac122c..bfcc8d20e 100644
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -9,11 +9,13 @@
#include "mozilla/ArrayUtils.h"
#include "jscntxt.h"
+#include "jsstr.h"
#include "builtin/Eval.h"
#include "frontend/BytecodeCompiler.h"
#include "jit/InlinableNatives.h"
#include "js/UniquePtr.h"
+#include "vm/AsyncFunction.h"
#include "vm/StringBuffer.h"
#include "jsobjinlines.h"
@@ -124,6 +126,27 @@ obj_toSource(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+template <typename CharT>
+static bool
+Consume(const CharT*& s, const CharT* e, const char *chars)
+{
+ size_t len = strlen(chars);
+ if (s + len >= e)
+ return false;
+ if (!EqualChars(s, chars, len))
+ return false;
+ s += len;
+ return true;
+}
+
+template <typename CharT>
+static void
+ConsumeSpaces(const CharT*& s, const CharT* e)
+{
+ while (*s == ' ' && s < e)
+ s++;
+}
+
/*
* Given a function source string, return the offset and length of the part
* between '(function $name' and ')'.
@@ -133,37 +156,53 @@ static bool
ArgsAndBodySubstring(mozilla::Range<const CharT> chars, size_t* outOffset, size_t* outLen)
{
const CharT* const start = chars.begin().get();
- const CharT* const end = chars.end().get();
const CharT* s = start;
+ const CharT* e = chars.end().get();
- uint8_t parenChomp = 0;
- if (s[0] == '(') {
- s++;
- parenChomp = 1;
- }
-
- /* Try to jump "function" keyword. */
- s = js_strchr_limit(s, ' ', end);
- if (!s)
+ if (s == e)
return false;
- /*
- * Jump over the function's name: it can't be encoded as part
- * of an ECMA getter or setter.
- */
- s = js_strchr_limit(s, '(', end);
- if (!s)
- return false;
+ // Remove enclosing parentheses.
+ if (*s == '(' && *(e - 1) == ')') {
+ s++;
+ e--;
+ }
- if (*s == ' ')
+ (void) Consume(s, e, "async");
+ ConsumeSpaces(s, e);
+ (void) (Consume(s, e, "function") || Consume(s, e, "get") || Consume(s, e, "set"));
+ ConsumeSpaces(s, e);
+ (void) Consume(s, e, "*");
+ ConsumeSpaces(s, e);
+
+ // Jump over the function's name.
+ if (Consume(s, e, "[")) {
+ s = js_strchr_limit(s, ']', e);
+ if (!s)
+ return false;
s++;
+ ConsumeSpaces(s, e);
+ if (*s != '(')
+ return false;
+ } else {
+ s = js_strchr_limit(s, '(', e);
+ if (!s)
+ return false;
+ }
*outOffset = s - start;
- *outLen = end - s - parenChomp;
+ *outLen = e - s;
MOZ_ASSERT(*outOffset + *outLen <= chars.length());
return true;
}
+enum class PropertyKind {
+ Getter,
+ Setter,
+ Method,
+ Normal
+};
+
JSString*
js::ObjectToSource(JSContext* cx, HandleObject obj)
{
@@ -182,59 +221,28 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
if (!buf.append('{'))
return nullptr;
- RootedValue v0(cx), v1(cx);
- MutableHandleValue val[2] = {&v0, &v1};
-
- RootedString str0(cx), str1(cx);
- MutableHandleString gsop[2] = {&str0, &str1};
-
AutoIdVector idv(cx);
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_SYMBOLS, &idv))
return nullptr;
bool comma = false;
- for (size_t i = 0; i < idv.length(); ++i) {
- RootedId id(cx, idv[i]);
- Rooted<PropertyDescriptor> desc(cx);
- if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
- return nullptr;
-
- int valcnt = 0;
- if (desc.object()) {
- if (desc.isAccessorDescriptor()) {
- if (desc.hasGetterObject() && desc.getterObject()) {
- val[valcnt].setObject(*desc.getterObject());
- gsop[valcnt].set(cx->names().get);
- valcnt++;
- }
- if (desc.hasSetterObject() && desc.setterObject()) {
- val[valcnt].setObject(*desc.setterObject());
- gsop[valcnt].set(cx->names().set);
- valcnt++;
- }
- } else {
- valcnt = 1;
- val[0].set(desc.value());
- gsop[0].set(nullptr);
- }
- }
-
+ auto AddProperty = [cx, &comma, &buf](HandleId id, HandleValue val, PropertyKind kind) -> bool {
/* Convert id to a string. */
RootedString idstr(cx);
if (JSID_IS_SYMBOL(id)) {
RootedValue v(cx, SymbolValue(JSID_TO_SYMBOL(id)));
idstr = ValueToSource(cx, v);
if (!idstr)
- return nullptr;
+ return false;
} else {
RootedValue idv(cx, IdToValue(id));
idstr = ToString<CanGC>(cx, idv);
if (!idstr)
- return nullptr;
+ return false;
/*
- * If id is a string that's not an identifier, or if it's a negative
- * integer, then it must be quoted.
+ * If id is a string that's not an identifier, or if it's a
+ * negative integer, then it must be quoted.
*/
if (JSID_IS_ATOM(id)
? !IsIdentifier(JSID_TO_ATOM(id))
@@ -242,28 +250,65 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
{
idstr = QuoteString(cx, idstr, char16_t('\''));
if (!idstr)
- return nullptr;
+ return false;
}
}
- for (int j = 0; j < valcnt; j++) {
- /* Convert val[j] to its canonical source form. */
- JSString* valsource = ValueToSource(cx, val[j]);
- if (!valsource)
- return nullptr;
+ RootedString valsource(cx, ValueToSource(cx, val));
+ if (!valsource)
+ return false;
- RootedLinearString valstr(cx, valsource->ensureLinear(cx));
- if (!valstr)
- return nullptr;
+ RootedLinearString valstr(cx, valsource->ensureLinear(cx));
+ if (!valstr)
+ return false;
- size_t voffset = 0;
- size_t vlength = valstr->length();
+ if (comma && !buf.append(", "))
+ return false;
+ comma = true;
+
+ size_t voffset, vlength;
+
+ // Methods and accessors can return exact syntax of source, that fits
+ // into property without adding property name or "get"/"set" prefix.
+ // Use the exact syntax when the following conditions are met:
+ //
+ // * It's a function object
+ // (exclude proxies)
+ // * Function's kind and property's kind are same
+ // (this can be false for dynamically defined properties)
+ // * Function has explicit name
+ // (this can be false for computed property and dynamically defined
+ // properties)
+ // * Function's name and property's name are same
+ // (this can be false for dynamically defined properties)
+ if (kind == PropertyKind::Getter || kind == PropertyKind::Setter ||
+ kind == PropertyKind::Method)
+ {
+ RootedFunction fun(cx);
+ if (val.toObject().is<JSFunction>()) {
+ fun = &val.toObject().as<JSFunction>();
+ // Method's case should be checked on caller.
+ if (((fun->isGetter() && kind == PropertyKind::Getter) ||
+ (fun->isSetter() && kind == PropertyKind::Setter) ||
+ kind == PropertyKind::Method) &&
+ fun->explicitName())
+ {
+ bool result;
+ if (!EqualStrings(cx, fun->explicitName(), idstr, &result))
+ return false;
- /*
- * Remove '(function ' from the beginning of valstr and ')' from the
- * end so that we can put "get" in front of the function definition.
- */
- if (gsop[j] && IsFunctionObject(val[j])) {
+ if (result) {
+ if (!buf.append(valstr))
+ return false;
+ return true;
+ }
+ }
+ }
+
+ {
+ // When falling back try to generate a better string
+ // representation by skipping the prelude, and also removing
+ // the enclosing parentheses.
bool success;
JS::AutoCheckCannotGC nogc;
if (valstr->hasLatin1Chars())
@@ -271,29 +316,90 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
else
success = ArgsAndBodySubstring(valstr->twoByteRange(nogc), &voffset, &vlength);
if (!success)
- gsop[j].set(nullptr);
+ kind = PropertyKind::Normal;
}
- if (comma && !buf.append(", "))
- return nullptr;
- comma = true;
+ if (kind == PropertyKind::Getter) {
+ if (!buf.append("get "))
+ return false;
+ } else if (kind == PropertyKind::Setter) {
+ if (!buf.append("set "))
+ return false;
+ } else if (kind == PropertyKind::Method && fun) {
+ if (IsWrappedAsyncFunction(fun)) {
+ if (!buf.append("async "))
+ return false;
+ }
- if (gsop[j]) {
- if (!buf.append(gsop[j]) || !buf.append(' '))
- return nullptr;
+ if (fun->isStarGenerator()) {
+ if (!buf.append('*'))
+ return false;
+ }
}
- if (JSID_IS_SYMBOL(id) && !buf.append('['))
- return nullptr;
- if (!buf.append(idstr))
- return nullptr;
- if (JSID_IS_SYMBOL(id) && !buf.append(']'))
- return nullptr;
- if (!buf.append(gsop[j] ? ' ' : ':'))
- return nullptr;
+ }
+ bool needsBracket = JSID_IS_SYMBOL(id);
+ if (needsBracket && !buf.append('['))
+ return false;
+ if (!buf.append(idstr))
+ return false;
+ if (needsBracket && !buf.append(']'))
+ return false;
+
+ if (kind == PropertyKind::Getter || kind == PropertyKind::Setter ||
+ kind == PropertyKind::Method)
+ {
if (!buf.appendSubstring(valstr, voffset, vlength))
- return nullptr;
+ return false;
+ } else {
+ if (!buf.append(':'))
+ return false;
+ if (!buf.append(valstr))
+ return false;
+ }
+ return true;
+ };
+
+ RootedId id(cx);
+ Rooted<PropertyDescriptor> desc(cx);
+ RootedValue val(cx);
+ RootedFunction fun(cx);
+ for (size_t i = 0; i < idv.length(); ++i) {
+ id = idv[i];
+ if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
+ return nullptr;
+
+ if (!desc.object())
+ continue;
+
+ if (desc.isAccessorDescriptor()) {
+ if (desc.hasGetterObject() && desc.getterObject()) {
+ val.setObject(*desc.getterObject());
+ if (!AddProperty(id, val, PropertyKind::Getter))
+ return nullptr;
+ }
+ if (desc.hasSetterObject() && desc.setterObject()) {
+ val.setObject(*desc.setterObject());
+ if (!AddProperty(id, val, PropertyKind::Setter))
+ return nullptr;
+ }
+ continue;
+ }
+
+ val.set(desc.value());
+ if (IsFunctionObject(val, fun.address())) {
+ if (IsWrappedAsyncFunction(fun))
+ fun = GetUnwrappedAsyncFunction(fun);
+
+ if (fun->isMethod()) {
+ if (!AddProperty(id, val, PropertyKind::Method))
+ return nullptr;
+ continue;
+ }
}
+
+ if (!AddProperty(id, val, PropertyKind::Normal))
+ return nullptr;
}
if (!buf.append('}'))
@@ -419,18 +525,6 @@ js::obj_toString(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-
-bool
-js::obj_valueOf(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
- RootedObject obj(cx, ToObject(cx, args.thisv()));
- if (!obj)
- return false;
- args.rval().setObject(*obj);
- return true;
-}
-
static bool
obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
{
@@ -474,97 +568,6 @@ obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-#if JS_HAS_OBJ_WATCHPOINT
-
-bool
-js::WatchHandler(JSContext* cx, JSObject* obj_, jsid id_, const JS::Value& old,
- JS::Value* nvp, void* closure)
-{
- RootedObject obj(cx, obj_);
- RootedId id(cx, id_);
-
- /* Avoid recursion on (obj, id) already being watched on cx. */
- AutoResolving resolving(cx, obj, id, AutoResolving::WATCH);
- if (resolving.alreadyStarted())
- return true;
-
- FixedInvokeArgs<3> args(cx);
-
- args[0].set(IdToValue(id));
- args[1].set(old);
- args[2].set(*nvp);
-
- RootedValue callable(cx, ObjectValue(*static_cast<JSObject*>(closure)));
- RootedValue thisv(cx, ObjectValue(*obj));
- RootedValue rv(cx);
- if (!Call(cx, callable, thisv, args, &rv))
- return false;
-
- *nvp = rv;
- return true;
-}
-
-static bool
-obj_watch(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- RootedObject obj(cx, ToObject(cx, args.thisv()));
- if (!obj)
- return false;
-
- if (!GlobalObject::warnOnceAboutWatch(cx, obj))
- return false;
-
- if (args.length() <= 1) {
- ReportMissingArg(cx, args.calleev(), 1);
- return false;
- }
-
- RootedObject callable(cx, ValueToCallable(cx, args[1], args.length() - 2));
- if (!callable)
- return false;
-
- RootedId propid(cx);
- if (!ValueToId<CanGC>(cx, args[0], &propid))
- return false;
-
- if (!WatchProperty(cx, obj, propid, callable))
- return false;
-
- args.rval().setUndefined();
- return true;
-}
-
-static bool
-obj_unwatch(JSContext* cx, unsigned argc, Value* vp)
-{
- CallArgs args = CallArgsFromVp(argc, vp);
-
- RootedObject obj(cx, ToObject(cx, args.thisv()));
- if (!obj)
- return false;
-
- if (!GlobalObject::warnOnceAboutWatch(cx, obj))
- return false;
-
- RootedId id(cx);
- if (args.length() != 0) {
- if (!ValueToId<CanGC>(cx, args[0], &id))
- return false;
- } else {
- id = JSID_VOID;
- }
-
- if (!UnwatchProperty(cx, obj, id))
- return false;
-
- args.rval().setUndefined();
- return true;
-}
-
-#endif /* JS_HAS_OBJ_WATCHPOINT */
-
/* ECMA 15.2.4.5. */
bool
js::obj_hasOwnProperty(JSContext* cx, unsigned argc, Value* vp)
@@ -1195,11 +1198,7 @@ static const JSFunctionSpec object_methods[] = {
#endif
JS_FN(js_toString_str, obj_toString, 0,0),
JS_SELF_HOSTED_FN(js_toLocaleString_str, "Object_toLocaleString", 0, 0),
- JS_FN(js_valueOf_str, obj_valueOf, 0,0),
-#if JS_HAS_OBJ_WATCHPOINT
- JS_FN(js_watch_str, obj_watch, 2,0),
- JS_FN(js_unwatch_str, obj_unwatch, 1,0),
-#endif
+ JS_SELF_HOSTED_FN(js_valueOf_str, "Object_valueOf", 0,0),
JS_FN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0),
JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0),
@@ -1314,8 +1313,8 @@ FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject pro
* only set the [[Prototype]] if it hasn't already been set.
*/
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
- if (global->shouldSplicePrototype(cx)) {
- if (!global->splicePrototype(cx, global->getClass(), tagged))
+ if (global->shouldSplicePrototype()) {
+ if (!JSObject::splicePrototype(cx, global, global->getClass(), tagged))
return false;
}
return true;
diff --git a/js/src/builtin/Object.h b/js/src/builtin/Object.h
index 09512be36..8231888b1 100644
--- a/js/src/builtin/Object.h
+++ b/js/src/builtin/Object.h
@@ -25,9 +25,6 @@ obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
-MOZ_MUST_USE bool
-obj_valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
-
PlainObject*
ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind = GenericObject,
HandleObjectGroup group = nullptr);
diff --git a/js/src/builtin/Object.js b/js/src/builtin/Object.js
index a7440aec7..9ed1be0e1 100644
--- a/js/src/builtin/Object.js
+++ b/js/src/builtin/Object.js
@@ -87,6 +87,12 @@ function Object_toLocaleString() {
return callContentFunction(O.toString, O);
}
+// ES 2017 draft bb96899bb0d9ef9be08164a26efae2ee5f25e875 19.1.3.7
+function Object_valueOf() {
+ // Step 1.
+ return ToObject(this);
+}
+
// ES7 draft (2016 March 8) B.2.2.3
function ObjectDefineSetter(name, setter) {
// Step 1.
diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp
index c781a336d..ec7845e89 100644
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -603,7 +603,7 @@ ResolvePromise(JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueO
// Now that everything else is done, do the things the debugger needs.
// Step 7 of RejectPromise implemented in onSettled.
- promise->onSettled(cx);
+ PromiseObject::onSettled(cx, promise);
// Step 7 of FulfillPromise.
// Step 8 of RejectPromise.
@@ -1947,26 +1947,23 @@ PerformPromiseRace(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
}
// ES2016, Sub-steps of 25.4.4.4 and 25.4.4.5.
-static MOZ_MUST_USE bool
-CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, ResolutionMode mode)
+static MOZ_MUST_USE JSObject*
+CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue argVal,
+ ResolutionMode mode)
{
- CallArgs args = CallArgsFromVp(argc, vp);
- RootedValue x(cx, args.get(0));
-
// Steps 1-2.
- if (!args.thisv().isObject()) {
+ if (!thisVal.isObject()) {
const char* msg = mode == ResolveMode
? "Receiver of Promise.resolve call"
: "Receiver of Promise.reject call";
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, msg);
- return false;
+ return nullptr;
}
- RootedValue cVal(cx, args.thisv());
- RootedObject C(cx, &cVal.toObject());
+ RootedObject C(cx, &thisVal.toObject());
// Step 3 of Resolve.
- if (mode == ResolveMode && x.isObject()) {
- RootedObject xObj(cx, &x.toObject());
+ if (mode == ResolveMode && argVal.isObject()) {
+ RootedObject xObj(cx, &argVal.toObject());
bool isPromise = false;
if (xObj->is<PromiseObject>()) {
isPromise = true;
@@ -1985,11 +1982,9 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
if (isPromise) {
RootedValue ctorVal(cx);
if (!GetProperty(cx, xObj, xObj, cx->names().constructor, &ctorVal))
- return false;
- if (ctorVal == cVal) {
- args.rval().set(x);
- return true;
- }
+ return nullptr;
+ if (ctorVal == thisVal)
+ return xObj;
}
}
@@ -1998,15 +1993,17 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
RootedObject resolveFun(cx);
RootedObject rejectFun(cx);
if (!NewPromiseCapability(cx, C, &promise, &resolveFun, &rejectFun, true))
- return false;
+ return nullptr;
// Step 5 of Resolve, 4 of Reject.
- if (!RunResolutionFunction(cx, mode == ResolveMode ? resolveFun : rejectFun, x, mode, promise))
- return false;
+ if (!RunResolutionFunction(cx, mode == ResolveMode ? resolveFun : rejectFun, argVal, mode,
+ promise))
+ {
+ return nullptr;
+ }
// Step 6 of Resolve, 4 of Reject.
- args.rval().setObject(*promise);
- return true;
+ return promise;
}
/**
@@ -2015,7 +2012,14 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
bool
js::Promise_reject(JSContext* cx, unsigned argc, Value* vp)
{
- return CommonStaticResolveRejectImpl(cx, argc, vp, RejectMode);
+ CallArgs args = CallArgsFromVp(argc, vp);
+ RootedValue thisVal(cx, args.thisv());
+ RootedValue argVal(cx, args.get(0));
+ JSObject* result = CommonStaticResolveRejectImpl(cx, thisVal, argVal, RejectMode);
+ if (!result)
+ return false;
+ args.rval().setObject(*result);
+ return true;
}
/**
@@ -2024,19 +2028,11 @@ js::Promise_reject(JSContext* cx, unsigned argc, Value* vp)
/* static */ JSObject*
PromiseObject::unforgeableReject(JSContext* cx, HandleValue value)
{
- // Steps 1-2 (omitted).
-
- // Roughly step 3.
- Rooted<PromiseObject*> promise(cx, CreatePromiseObjectInternal(cx));
- if (!promise)
+ RootedObject promiseCtor(cx, JS::GetPromiseConstructor(cx));
+ if (!promiseCtor)
return nullptr;
-
- // Roughly step 4.
- if (!ResolvePromise(cx, promise, value, JS::PromiseState::Rejected))
- return nullptr;
-
- // Step 5.
- return promise;
+ RootedValue cVal(cx, ObjectValue(*promiseCtor));
+ return CommonStaticResolveRejectImpl(cx, cVal, value, RejectMode);
}
/**
@@ -2045,7 +2041,14 @@ PromiseObject::unforgeableReject(JSContext* cx, HandleValue value)
bool
js::Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
{
- return CommonStaticResolveRejectImpl(cx, argc, vp, ResolveMode);
+ CallArgs args = CallArgsFromVp(argc, vp);
+ RootedValue thisVal(cx, args.thisv());
+ RootedValue argVal(cx, args.get(0));
+ JSObject* result = CommonStaticResolveRejectImpl(cx, thisVal, argVal, ResolveMode);
+ if (!result)
+ return false;
+ args.rval().setObject(*result);
+ return true;
}
/**
@@ -2054,30 +2057,11 @@ js::Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
/* static */ JSObject*
PromiseObject::unforgeableResolve(JSContext* cx, HandleValue value)
{
- // Steps 1-2 (omitted).
-
- // Step 3.
- if (value.isObject()) {
- JSObject* obj = &value.toObject();
- if (IsWrapper(obj))
- obj = CheckedUnwrap(obj);
- // Instead of getting the `constructor` property, do an unforgeable
- // check.
- if (obj && obj->is<PromiseObject>())
- return obj;
- }
-
- // Step 4.
- Rooted<PromiseObject*> promise(cx, CreatePromiseObjectInternal(cx));
- if (!promise)
+ RootedObject promiseCtor(cx, JS::GetPromiseConstructor(cx));
+ if (!promiseCtor)
return nullptr;
-
- // Steps 5.
- if (!ResolvePromiseInternal(cx, promise, value))
- return nullptr;
-
- // Step 6.
- return promise;
+ RootedValue cVal(cx, ObjectValue(*promiseCtor));
+ return CommonStaticResolveRejectImpl(cx, cVal, value, ResolveMode);
}
// ES2016, 25.4.4.6, implemented in Promise.js.
@@ -2647,14 +2631,14 @@ PromiseObject::dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> v
return true;
}
-bool
-PromiseObject::resolve(JSContext* cx, HandleValue resolutionValue)
+/* static */ bool
+PromiseObject::resolve(JSContext* cx, Handle<PromiseObject*> promise, HandleValue resolutionValue)
{
- MOZ_ASSERT(!PromiseHasAnyFlag(*this, PROMISE_FLAG_ASYNC));
- if (state() != JS::PromiseState::Pending)
+ MOZ_ASSERT(!PromiseHasAnyFlag(*promise, PROMISE_FLAG_ASYNC));
+ if (promise->state() != JS::PromiseState::Pending)
return true;
- RootedObject resolveFun(cx, GetResolveFunctionFromPromise(this));
+ RootedObject resolveFun(cx, GetResolveFunctionFromPromise(promise));
RootedValue funVal(cx, ObjectValue(*resolveFun));
// For xray'd Promises, the resolve fun may have been created in another
@@ -2670,14 +2654,14 @@ PromiseObject::resolve(JSContext* cx, HandleValue resolutionValue)
return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
}
-bool
-PromiseObject::reject(JSContext* cx, HandleValue rejectionValue)
+/* static */ bool
+PromiseObject::reject(JSContext* cx, Handle<PromiseObject*> promise, HandleValue rejectionValue)
{
- MOZ_ASSERT(!PromiseHasAnyFlag(*this, PROMISE_FLAG_ASYNC));
- if (state() != JS::PromiseState::Pending)
+ MOZ_ASSERT(!PromiseHasAnyFlag(*promise, PROMISE_FLAG_ASYNC));
+ if (promise->state() != JS::PromiseState::Pending)
return true;
- RootedValue funVal(cx, this->getFixedSlot(PromiseSlot_RejectFunction));
+ RootedValue funVal(cx, promise->getFixedSlot(PromiseSlot_RejectFunction));
MOZ_ASSERT(IsCallable(funVal));
FixedInvokeArgs<1> args(cx);
@@ -2687,10 +2671,9 @@ PromiseObject::reject(JSContext* cx, HandleValue rejectionValue)
return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
}
-void
-PromiseObject::onSettled(JSContext* cx)
+/* static */ void
+PromiseObject::onSettled(JSContext* cx, Handle<PromiseObject*> promise)
{
- Rooted<PromiseObject*> promise(cx, this);
RootedObject stack(cx);
if (cx->options().asyncStack() || cx->compartment()->isDebuggee()) {
if (!JS::CaptureCurrentStack(cx, &stack, JS::StackCapture(JS::AllFrames()))) {
@@ -2750,7 +2733,7 @@ PromiseTask::executeAndFinish(JSContext* cx)
static JSObject*
CreatePromisePrototype(JSContext* cx, JSProtoKey key)
{
- return cx->global()->createBlankPrototype(cx, &PromiseObject::protoClass_);
+ return GlobalObject::createBlankPrototype(cx, cx->global(), &PromiseObject::protoClass_);
}
static const JSFunctionSpec promise_methods[] = {
diff --git a/js/src/builtin/Promise.h b/js/src/builtin/Promise.h
index bb4778631..c76dc358c 100644
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -66,10 +66,12 @@ class PromiseObject : public NativeObject
return getFixedSlot(PromiseSlot_ReactionsOrResult);
}
- MOZ_MUST_USE bool resolve(JSContext* cx, HandleValue resolutionValue);
- MOZ_MUST_USE bool reject(JSContext* cx, HandleValue rejectionValue);
+ static MOZ_MUST_USE bool resolve(JSContext* cx, Handle<PromiseObject*> promise,
+ HandleValue resolutionValue);
+ static MOZ_MUST_USE bool reject(JSContext* cx, Handle<PromiseObject*> promise,
+ HandleValue rejectionValue);
- void onSettled(JSContext* cx);
+ static void onSettled(JSContext* cx, Handle<PromiseObject*> promise);
double allocationTime() { return getFixedSlot(PromiseSlot_AllocationTime).toNumber(); }
double resolutionTime() { return getFixedSlot(PromiseSlot_ResolutionTime).toNumber(); }
diff --git a/js/src/builtin/Reflect.cpp b/js/src/builtin/Reflect.cpp
index 2f509a226..4e7fae78c 100644
--- a/js/src/builtin/Reflect.cpp
+++ b/js/src/builtin/Reflect.cpp
@@ -268,7 +268,8 @@ static const JSFunctionSpec methods[] = {
JSObject*
js::InitReflect(JSContext* cx, HandleObject obj)
{
- RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
+ RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!proto)
return nullptr;
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index beff58e13..8e8bb2417 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3044,7 +3044,12 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
RootedValue expr(cx);
- expr.setString(next->pn_atom);
+ if (next->isKind(PNK_RAW_UNDEFINED)) {
+ expr.setUndefined();
+ } else {
+ MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
+ expr.setString(next->pn_atom);
+ }
cooked.infallibleAppend(expr);
}
@@ -3136,6 +3141,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_TRUE:
case PNK_FALSE:
case PNK_NULL:
+ case PNK_RAW_UNDEFINED:
return literal(pn, dst);
case PNK_YIELD_STAR:
@@ -3216,6 +3222,8 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst)
return expression(pn->pn_kid, &val) &&
builder.prototypeMutation(val, &pn->pn_pos, dst);
}
+ if (pn->isKind(PNK_SPREAD))
+ return expression(pn, dst);
PropKind kind;
switch (pn->getOp()) {
@@ -3276,6 +3284,10 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
val.setNull();
break;
+ case PNK_RAW_UNDEFINED:
+ val.setUndefined();
+ break;
+
case PNK_TRUE:
val.setBoolean(true);
break;
@@ -3332,6 +3344,16 @@ ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
return false;
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
+ if (propdef->isKind(PNK_SPREAD)) {
+ RootedValue target(cx);
+ RootedValue spread(cx);
+ if (!pattern(propdef->pn_kid, &target))
+ return false;
+ if(!builder.spreadExpression(target, &propdef->pn_pos, &spread))
+ return false;
+ elts.infallibleAppend(spread);
+ continue;
+ }
LOCAL_ASSERT(propdef->isKind(PNK_MUTATEPROTO) != propdef->isOp(JSOP_INITPROP));
RootedValue key(cx);
@@ -3407,12 +3429,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
: GeneratorStyle::None;
bool isAsync = pn->pn_funbox->isAsync();
- bool isExpression =
-#if JS_HAS_EXPR_CLOSURES
- func->isExprBody();
-#else
- false;
-#endif
+ bool isExpression = pn->pn_funbox->isExprBody();
RootedValue id(cx);
RootedAtom funcAtom(cx, func->explicitName());
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
index b20f41c53..7cf20d23c 100644
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -140,12 +140,12 @@ ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, RegExpShared& re, HandleLin
/* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
bool
-js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
+js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
HandleLinearString input, size_t* lastIndex, bool test,
MutableHandleValue rval)
{
RegExpGuard shared(cx);
- if (!reobj.getShared(cx, &shared))
+ if (!RegExpObject::getShared(cx, reobj, &shared))
return false;
ScopedMatchPairs matches(&cx->tempLifoAlloc());
@@ -801,7 +801,7 @@ const JSFunctionSpec js::regexp_methods[] = {
name(JSContext* cx, unsigned argc, Value* vp) \
{ \
CallArgs args = CallArgsFromVp(argc, vp); \
- RegExpStatics* res = cx->global()->getRegExpStatics(cx); \
+ RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \
if (!res) \
return false; \
code; \
@@ -827,7 +827,7 @@ DEFINE_STATIC_GETTER(static_paren9_getter, STATIC_PAREN_GETTER_CODE(9))
static bool \
name(JSContext* cx, unsigned argc, Value* vp) \
{ \
- RegExpStatics* res = cx->global()->getRegExpStatics(cx); \
+ RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \
if (!res) \
return false; \
code; \
@@ -838,7 +838,7 @@ static bool
static_input_setter(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
- RegExpStatics* res = cx->global()->getRegExpStatics(cx);
+ RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
if (!res)
return false;
@@ -918,12 +918,12 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard re(cx);
- if (!reobj->getShared(cx, &re))
+ if (!RegExpObject::getShared(cx, reobj, &re))
return RegExpRunStatus_Error;
RegExpStatics* res;
if (staticsUpdate == UpdateRegExpStatics) {
- res = cx->global()->getRegExpStatics(cx);
+ res = GlobalObject::getRegExpStatics(cx, cx->global());
if (!res)
return RegExpRunStatus_Error;
} else {
@@ -1725,7 +1725,7 @@ js::intrinsic_GetElemBaseForLambda(JSContext* cx, unsigned argc, Value* vp)
if (!fun->isInterpreted() || fun->isClassConstructor())
return true;
- JSScript* script = fun->getOrCreateScript(cx);
+ JSScript* script = JSFunction::getOrCreateScript(cx, fun);
if (!script)
return false;
@@ -1800,7 +1800,7 @@ js::intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp)
return false;
RootedValue v(cx);
- if (HasDataProperty(cx, nobj, AtomToId(atom), v.address()) && v.isString())
+ if (GetPropertyPure(cx, nobj, AtomToId(atom), v.address()) && v.isString())
args.rval().set(v);
else
args.rval().setUndefined();
diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h
index 715656f40..4e0ff6948 100644
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -31,7 +31,7 @@ enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics };
* |chars| and |length|.
*/
MOZ_MUST_USE bool
-ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
+ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
HandleLinearString input, size_t* lastIndex, bool test,
MutableHandleValue rval);
diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp
index 2383922db..5fe691152 100644
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -475,7 +475,7 @@ const Class SimdObject::class_ = {
&SimdObjectClassOps
};
-bool
+/* static */ bool
GlobalObject::initSimdObject(JSContext* cx, Handle<GlobalObject*> global)
{
// SIMD relies on the TypedObject module being initialized.
@@ -483,11 +483,11 @@ GlobalObject::initSimdObject(JSContext* cx, Handle<GlobalObject*> global)
// to be able to call GetTypedObjectModule(). It is NOT necessary
// to install the TypedObjectModule global, but at the moment
// those two things are not separable.
- if (!global->getOrCreateTypedObjectModule(cx))
+ if (!GlobalObject::getOrCreateTypedObjectModule(cx, global))
return false;
RootedObject globalSimdObject(cx);
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return false;
@@ -510,7 +510,7 @@ static bool
CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName stringRepr,
SimdType simdType, const JSFunctionSpec* methods)
{
- RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+ RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
if (!funcProto)
return false;
@@ -531,7 +531,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
return false;
// Create prototype property, which inherits from Object.prototype.
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return false;
Rooted<TypedProto*> proto(cx);
@@ -551,7 +551,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
}
// Bind type descriptor to the global SIMD object
- RootedObject globalSimdObject(cx, global->getOrCreateSimdGlobalObject(cx));
+ RootedObject globalSimdObject(cx, GlobalObject::getOrCreateSimdGlobalObject(cx, global));
MOZ_ASSERT(globalSimdObject);
RootedValue typeValue(cx, ObjectValue(*typeDescr));
@@ -568,7 +568,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
return !!typeDescr;
}
-bool
+/* static */ bool
GlobalObject::initSimdType(JSContext* cx, Handle<GlobalObject*> global, SimdType simdType)
{
#define CREATE_(Type) \
@@ -584,13 +584,13 @@ GlobalObject::initSimdType(JSContext* cx, Handle<GlobalObject*> global, SimdType
#undef CREATE_
}
-SimdTypeDescr*
+/* static */ SimdTypeDescr*
GlobalObject::getOrCreateSimdTypeDescr(JSContext* cx, Handle<GlobalObject*> global,
SimdType simdType)
{
MOZ_ASSERT(unsigned(simdType) < unsigned(SimdType::Count), "Invalid SIMD type");
- RootedObject globalSimdObject(cx, global->getOrCreateSimdGlobalObject(cx));
+ RootedObject globalSimdObject(cx, GlobalObject::getOrCreateSimdGlobalObject(cx, global));
if (!globalSimdObject)
return nullptr;
@@ -628,8 +628,8 @@ SimdObject::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool*
JSObject*
js::InitSimdClass(JSContext* cx, HandleObject obj)
{
- Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
- return global->getOrCreateSimdGlobalObject(cx);
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
+ return GlobalObject::getOrCreateSimdGlobalObject(cx, global);
}
template<typename V>
diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js
index e5b2ad552..f830b1aa2 100644
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -828,16 +828,16 @@ function String_static_trim(string) {
return callFunction(std_String_trim, string);
}
-function String_static_trimLeft(string) {
+function String_static_trimStart(string) {
if (arguments.length < 1)
- ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimLeft');
- return callFunction(std_String_trimLeft, string);
+ ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimStart');
+ return callFunction(std_String_trimStart, string);
}
-function String_static_trimRight(string) {
+function String_static_trimEnd(string) {
if (arguments.length < 1)
- ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimRight');
- return callFunction(std_String_trimRight, string);
+ ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimEnd');
+ return callFunction(std_String_trimEnd, string);
}
function String_static_toLocaleLowerCase(string) {
diff --git a/js/src/builtin/SymbolObject.cpp b/js/src/builtin/SymbolObject.cpp
index cf48402d6..8fa860ef3 100644
--- a/js/src/builtin/SymbolObject.cpp
+++ b/js/src/builtin/SymbolObject.cpp
@@ -33,6 +33,7 @@ SymbolObject::create(JSContext* cx, JS::HandleSymbol symbol)
}
const JSPropertySpec SymbolObject::properties[] = {
+ JS_PSG("description", descriptionGetter, 0),
JS_PS_END
};
@@ -52,17 +53,17 @@ const JSFunctionSpec SymbolObject::staticMethods[] = {
JSObject*
SymbolObject::initClass(JSContext* cx, HandleObject obj)
{
- Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
// This uses &JSObject::class_ because: "The Symbol prototype object is an
// ordinary object. It is not a Symbol instance and does not have a
// [[SymbolData]] internal slot." (ES6 rev 24, 19.4.3)
- RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
+ RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!proto)
return nullptr;
- RootedFunction ctor(cx, global->createConstructor(cx, construct,
- ClassName(JSProto_Symbol, cx), 0));
+ RootedFunction ctor(cx, GlobalObject::createConstructor(cx, construct,
+ ClassName(JSProto_Symbol, cx), 0));
if (!ctor)
return nullptr;
@@ -227,6 +228,34 @@ SymbolObject::toPrimitive(JSContext* cx, unsigned argc, Value* vp)
return CallNonGenericMethod<IsSymbol, valueOf_impl>(cx, args);
}
+// ES2019 Stage 4 Draft / November 28, 2018
+// Symbol description accessor
+// See: https://tc39.github.io/proposal-Symbol-description/
+bool
+SymbolObject::descriptionGetter_impl(JSContext* cx, const CallArgs& args)
+{
+ // Get symbol object pointer.
+ HandleValue thisv = args.thisv();
+ MOZ_ASSERT(IsSymbol(thisv));
+ Rooted<Symbol*> sym(cx, thisv.isSymbol()
+ ? thisv.toSymbol()
+ : thisv.toObject().as<SymbolObject>().unbox());
+
+ // Return the symbol's description if present, otherwise return undefined.
+ if (JSString* str = sym->description())
+ args.rval().setString(str);
+ else
+ args.rval().setUndefined();
+ return true;
+}
+
+bool
+SymbolObject::descriptionGetter(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return CallNonGenericMethod<IsSymbol, descriptionGetter_impl>(cx, args);
+}
+
JSObject*
js::InitSymbolClass(JSContext* cx, HandleObject obj)
{
diff --git a/js/src/builtin/SymbolObject.h b/js/src/builtin/SymbolObject.h
index 0f204b494..e10b42d53 100644
--- a/js/src/builtin/SymbolObject.h
+++ b/js/src/builtin/SymbolObject.h
@@ -52,6 +52,10 @@ class SymbolObject : public NativeObject
static MOZ_MUST_USE bool valueOf(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE 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);
+
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];
static const JSFunctionSpec staticMethods[];
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index 373b6c9ed..4363c7aed 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -239,12 +239,11 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
value = BooleanValue(true);
if (!JS_SetProperty(cx, info, "intl-api", value))
return false;
-
-#if defined(SOLARIS)
+#ifdef XP_SOLARIS
value = BooleanValue(false);
#else
value = BooleanValue(true);
-#endif
+#endif
if (!JS_SetProperty(cx, info, "mapped-array-buffer", value))
return false;
@@ -3222,13 +3221,13 @@ ByteSizeOfScript(JSContext*cx, unsigned argc, Value* vp)
return false;
}
- JSFunction* fun = &args[0].toObject().as<JSFunction>();
+ RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
if (fun->isNative()) {
JS_ReportErrorASCII(cx, "Argument must be a scripted function");
return false;
}
- RootedScript script(cx, fun->getOrCreateScript(cx));
+ RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
if (!script)
return false;
@@ -3323,7 +3322,8 @@ GetConstructorName(JSContext* cx, unsigned argc, Value* vp)
}
RootedAtom name(cx);
- if (!args[0].toObject().constructorDisplayAtom(cx, &name))
+ RootedObject obj(cx, &args[0].toObject());
+ if (!JSObject::constructorDisplayAtom(cx, obj, &name))
return false;
if (name) {
@@ -4027,7 +4027,7 @@ DisRegExp(JSContext* cx, unsigned argc, Value* vp)
return false;
}
- if (!reobj->dumpBytecode(cx, match_only, input))
+ if (!RegExpObject::dumpBytecode(cx, reobj, match_only, input))
return false;
args.rval().setUndefined();
@@ -4046,6 +4046,32 @@ IsConstructor(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+static bool
+GetErrorNotes(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ if (!args.requireAtLeast(cx, "getErrorNotes", 1))
+ return false;
+
+ if (!args[0].isObject() || !args[0].toObject().is<ErrorObject>()) {
+ args.rval().setNull();
+ return true;
+ }
+
+ JSErrorReport* report = args[0].toObject().as<ErrorObject>().getErrorReport();
+ if (!report) {
+ args.rval().setNull();
+ return true;
+ }
+
+ RootedObject notesArray(cx, CreateErrorNotesArray(cx, report));
+ if (!notesArray)
+ return false;
+
+ args.rval().setObject(*notesArray);
+ return true;
+}
+
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'zone' [, 'shrinking'])",
@@ -4580,6 +4606,10 @@ static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
" Dumps RegExp bytecode."),
#endif
+ JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0,
+"getErrorNotes(error)",
+" Returns an array of error notes."),
+
JS_FS_HELP_END
};
diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
index ae74f01bf..50bf0b836 100644
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -652,7 +652,7 @@ ArrayMetaTypeDescr::create(JSContext* cx,
if (!CreateTraceList(cx, obj))
return nullptr;
- if (!cx->zone()->typeDescrObjects.put(obj)) {
+ if (!cx->zone()->addTypeDescrObject(cx, obj)) {
ReportOutOfMemory(cx);
return nullptr;
}
@@ -993,8 +993,8 @@ StructMetaTypeDescr::create(JSContext* cx,
if (!CreateTraceList(cx, descr))
return nullptr;
- if (!cx->zone()->typeDescrObjects.put(descr) ||
- !cx->zone()->typeDescrObjects.put(fieldTypeVec))
+ if (!cx->zone()->addTypeDescrObject(cx, descr) ||
+ !cx->zone()->addTypeDescrObject(cx, fieldTypeVec))
{
ReportOutOfMemory(cx);
return nullptr;
@@ -1124,11 +1124,11 @@ DefineSimpleTypeDescr(JSContext* cx,
typename T::Type type,
HandlePropertyName className)
{
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return false;
- RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+ RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
if (!funcProto)
return false;
@@ -1165,10 +1165,8 @@ DefineSimpleTypeDescr(JSContext* cx,
if (!CreateTraceList(cx, descr))
return false;
- if (!cx->zone()->typeDescrObjects.put(descr)) {
- ReportOutOfMemory(cx);
+ if (!cx->zone()->addTypeDescrObject(cx, descr))
return false;
- }
return true;
}
@@ -1187,7 +1185,7 @@ DefineMetaTypeDescr(JSContext* cx,
if (!className)
return nullptr;
- RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+ RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
if (!funcProto)
return nullptr;
@@ -1199,7 +1197,7 @@ DefineMetaTypeDescr(JSContext* cx,
// Create ctor.prototype.prototype, which inherits from Object.__proto__
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return nullptr;
RootedObject protoProto(cx);
@@ -1218,7 +1216,7 @@ DefineMetaTypeDescr(JSContext* cx,
const int constructorLength = 2;
RootedFunction ctor(cx);
- ctor = global->createConstructor(cx, T::construct, className, constructorLength);
+ ctor = GlobalObject::createConstructor(cx, T::construct, className, constructorLength);
if (!ctor ||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndFunctions(cx, proto,
@@ -1242,10 +1240,10 @@ DefineMetaTypeDescr(JSContext* cx,
* initializer for the `TypedObject` class populate the
* `TypedObject` global (which is referred to as "module" herein).
*/
-bool
+/* static */ bool
GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
{
- RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+ RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto)
return false;
@@ -1319,9 +1317,8 @@ GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
JSObject*
js::InitTypedObjectModuleObject(JSContext* cx, HandleObject obj)
{
- MOZ_ASSERT(obj->is<GlobalObject>());
- Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
- return global->getOrCreateTypedObjectModule(cx);
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
+ return GlobalObject::getOrCreateTypedObjectModule(cx, global);
}
/******************************************************************************
@@ -2218,7 +2215,6 @@ const ObjectOps TypedObject::objectOps_ = {
TypedObject::obj_setProperty,
TypedObject::obj_getOwnPropertyDescriptor,
TypedObject::obj_deleteProperty,
- nullptr, nullptr, /* watch/unwatch */
nullptr, /* getElements */
TypedObject::obj_enumerate,
nullptr, /* thisValue */
diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js
index c73bc5e7f..d5f233d05 100644
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -229,6 +229,69 @@ function GetInternalError(msg) {
// To be used when a function is required but calling it shouldn't do anything.
function NullFunction() {}
+// Object Rest/Spread Properties proposal
+// Abstract operation: CopyDataProperties (target, source, excluded)
+function CopyDataProperties(target, source, excluded) {
+ // Step 1.
+ assert(IsObject(target), "target is an object");
+
+ // Step 2.
+ assert(IsObject(excluded), "excluded is an object");
+
+ // Steps 3, 6.
+ if (source === undefined || source === null)
+ return;
+
+ // Step 4.a.
+ source = ToObject(source);
+
+ // Step 4.b.
+ var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
+
+ // Step 5.
+ for (var index = 0; index < keys.length; index++) {
+ var key = keys[index];
+
+ // We abbreviate this by calling propertyIsEnumerable which is faster
+ // and returns false for not defined properties.
+ if (!callFunction(std_Object_hasOwnProperty, excluded, key) && callFunction(std_Object_propertyIsEnumerable, source, key))
+ _DefineDataProperty(target, key, source[key]);
+ }
+
+ // Step 6 (Return).
+}
+
+// Object Rest/Spread Properties proposal
+// Abstract operation: CopyDataProperties (target, source, excluded)
+function CopyDataPropertiesUnfiltered(target, source) {
+ // Step 1.
+ assert(IsObject(target), "target is an object");
+
+ // Step 2 (Not applicable).
+
+ // Steps 3, 6.
+ if (source === undefined || source === null)
+ return;
+
+ // Step 4.a.
+ source = ToObject(source);
+
+ // Step 4.b.
+ var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
+
+ // Step 5.
+ for (var index = 0; index < keys.length; index++) {
+ var key = keys[index];
+
+ // We abbreviate this by calling propertyIsEnumerable which is faster
+ // and returns false for not defined properties.
+ if (callFunction(std_Object_propertyIsEnumerable, source, key))
+ _DefineDataProperty(target, key, source[key]);
+ }
+
+ // Step 6 (Return).
+}
+
/*************************************** Testing functions ***************************************/
function outer() {
return function inner() {
diff --git a/js/src/builtin/WeakMapObject.cpp b/js/src/builtin/WeakMapObject.cpp
index 555b9e03a..dcfa19776 100644
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -350,14 +350,14 @@ InitWeakMapClass(JSContext* cx, HandleObject obj, bool defineMembers)
{
MOZ_ASSERT(obj->isNative());
- Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!proto)
return nullptr;
- RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
- cx->names().WeakMap, 0));
+ RootedFunction ctor(cx, GlobalObject::createConstructor(cx, WeakMap_construct,
+ cx->names().WeakMap, 0));
if (!ctor)
return nullptr;
diff --git a/js/src/builtin/WeakSetObject.cpp b/js/src/builtin/WeakSetObject.cpp
index 7ea3f2fef..fbe5e418c 100644
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -41,14 +41,15 @@ const JSFunctionSpec WeakSetObject::methods[] = {
};
JSObject*
-WeakSetObject::initClass(JSContext* cx, JSObject* obj)
+WeakSetObject::initClass(JSContext* cx, HandleObject obj)
{
- Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
+ Handle<GlobalObject*> global = obj.as<GlobalObject>();
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!proto)
return nullptr;
- Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(JSProto_WeakSet, cx), 0));
+ Rooted<JSFunction*> ctor(cx, GlobalObject::createConstructor(cx, construct,
+ ClassName(JSProto_WeakSet, cx), 0));
if (!ctor ||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
diff --git a/js/src/builtin/WeakSetObject.h b/js/src/builtin/WeakSetObject.h
index 0a6ff33f3..50e54c182 100644
--- a/js/src/builtin/WeakSetObject.h
+++ b/js/src/builtin/WeakSetObject.h
@@ -16,7 +16,7 @@ class WeakSetObject : public NativeObject
public:
static const unsigned RESERVED_SLOTS = 1;
- static JSObject* initClass(JSContext* cx, JSObject* obj);
+ static JSObject* initClass(JSContext* cx, HandleObject obj);
static const Class class_;
private: