--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1932,20 +1932,80 @@ MaybeReportUndeclaredVarAssignment(JSCon
return !!bytes &&
JS_ReportErrorFlagsAndNumber(cx,
(JSREPORT_WARNING | JSREPORT_STRICT
| JSREPORT_STRICT_MODE_ERROR),
js_GetErrorMessage, nullptr,
JSMSG_UNDECLARED_VAR, bytes.ptr());
}
+/*
+ * When a [[Set]] operation finds no existing property with the given id
+ * or finds a writable data property on the prototype chain, we end up here.
+ * Finish the [[Set]] by defining a new property on receiver.
+ *
+ * This should follow ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
+ * is really old code and we're not there yet.
+ */
template <ExecutionMode mode>
static bool
SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
- HandleObject receiver, HandleId id, HandleValue v, bool strict);
+ HandleObject receiver, HandleId id, HandleValue v, bool strict)
+{
+ // If receiver is inextensible, stop. (According to the specification, this
+ // is supposed to be enforced by [[DefineOwnProperty]], but we haven't
+ // implemented that yet.)
+ bool extensible;
+ if (mode == ParallelExecution) {
+ if (receiver->is<ProxyObject>())
+ return false;
+ extensible = receiver->nonProxyIsExtensible();
+ } else {
+ if (!JSObject::isExtensible(cxArg->asJSContext(), receiver, &extensible))
+ return false;
+ }
+ if (!extensible) {
+ // Error in strict mode code, warn with extra warnings option,
+ // otherwise do nothing.
+ if (strict)
+ return receiver->reportNotExtensible(cxArg);
+ if (mode == SequentialExecution &&
+ cxArg->asJSContext()->compartment()->options().extraWarnings(cxArg->asJSContext()))
+ {
+ return receiver->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
+ }
+ return true;
+ }
+
+ // Invalidate SpiderMonkey-specific caches or bail.
+ const Class *clasp = receiver->getClass();
+ if (mode == ParallelExecution) {
+ if (receiver->isDelegate())
+ return false;
+
+ if (clasp->getProperty != JS_PropertyStub || !types::HasTypePropertyId(receiver, id, v))
+ return false;
+ } else {
+ // Purge the property cache of now-shadowed id in receiver's scope chain.
+ if (!PurgeScopeChain(cxArg->asJSContext(), receiver, id))
+ return false;
+ }
+
+ // Define the new data property.
+ if (!receiver->is<NativeObject>()) {
+ if (mode == ParallelExecution)
+ return false;
+ return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v,
+ clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
+ }
+ Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
+ return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id,
+ clasp->getProperty, clasp->setProperty,
+ JSPROP_ENUMERATE, v, true, strict);
+}
template <ExecutionMode mode>
bool
baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, bool strict)
{
MOZ_ASSERT(cxArg->isThreadLocal(obj));
@@ -2131,81 +2191,16 @@ baseops::SetPropertyHelper(typename Exec
if (shape)
return NativeSet<mode>(cxArg, obj, receiver, shape, strict, vp);
MOZ_ASSERT(attrs == JSPROP_ENUMERATE);
return SetPropertyByDefining<mode>(cxArg, receiver, id, vp, strict);
}
-/*
- * When a [[Set]] operation finds no existing property with the given id
- * or finds a writable data property on the prototype chain, we end up here.
- * Finish the [[Set]] by defining a new property on receiver.
- *
- * This should follow ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
- * is really old code and we're not there yet.
- */
-template <ExecutionMode mode>
-static bool
-SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
- HandleObject receiver, HandleId id, HandleValue v, bool strict)
-{
- // If receiver is inextensible, stop. (According to the specification, this
- // is supposed to be enforced by [[DefineOwnProperty]], but we haven't
- // implemented that yet.)
- bool extensible;
- if (mode == ParallelExecution) {
- if (receiver->is<ProxyObject>())
- return false;
- extensible = receiver->nonProxyIsExtensible();
- } else {
- if (!JSObject::isExtensible(cxArg->asJSContext(), receiver, &extensible))
- return false;
- }
- if (!extensible) {
- // Error in strict mode code, warn with extra warnings option,
- // otherwise do nothing.
- if (strict)
- return receiver->reportNotExtensible(cxArg);
- if (mode == SequentialExecution &&
- cxArg->asJSContext()->compartment()->options().extraWarnings(cxArg->asJSContext()))
- {
- return receiver->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
- }
- return true;
- }
-
- // Invalidate SpiderMonkey-specific caches or bail.
- const Class *clasp = receiver->getClass();
- if (mode == ParallelExecution) {
- if (receiver->isDelegate())
- return false;
-
- if (clasp->getProperty != JS_PropertyStub || !types::HasTypePropertyId(receiver, id, v))
- return false;
- } else {
- // Purge the property cache of now-shadowed id in receiver's scope chain.
- if (!PurgeScopeChain(cxArg->asJSContext(), receiver, id))
- return false;
- }
-
- // Define the new data property.
- if (!receiver->is<NativeObject>()) {
- if (mode == ParallelExecution)
- return false;
- return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v,
- clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
- }
- Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
- return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id,
- clasp->getProperty, clasp->setProperty,
- JSPROP_ENUMERATE, v, true, strict);
-}
-
template bool
baseops::SetPropertyHelper<SequentialExecution>(JSContext *cx, HandleNativeObject obj,
HandleObject receiver, HandleId id,
QualifiedBool qualified,
MutableHandleValue vp, bool strict);
template bool
baseops::SetPropertyHelper<ParallelExecution>(ForkJoinContext *cx, HandleNativeObject obj,
HandleObject receiver, HandleId id,