Bug 1090537, part 6 - Factor out a big chunk of SetPropertyHelper into a separate function template, SetPropertyByDefining. No change in behavior. r=efaust.
authorJason Orendorff <jorendorff@mozilla.com>
Sat, 18 Oct 2014 16:30:32 -0500
changeset 226124 1791020afc6f362725b8008869c85cb9a97ce01a
parent 226123 9317cf955dc77e6dbd914b0afd47303087d31dc5
child 226125 724e3e6efb7bbda09b1b3d3a646549f8a88d8882
push id36
push userdburns@mozilla.com
push dateMon, 10 Nov 2014 15:14:02 +0000
reviewersefaust
bugs1090537
milestone36.0a1
Bug 1090537, part 6 - Factor out a big chunk of SetPropertyHelper into a separate function template, SetPropertyByDefining. No change in behavior. r=efaust.
js/src/vm/NativeObject.cpp
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1933,16 +1933,22 @@ MaybeReportUndeclaredVarAssignment(JSCon
            JS_ReportErrorFlagsAndNumber(cx,
                                         (JSREPORT_WARNING | JSREPORT_STRICT
                                          | JSREPORT_STRICT_MODE_ERROR),
                                         js_GetErrorMessage, nullptr,
                                         JSMSG_UNDECLARED_VAR, bytes.ptr());
 }
 
 template <ExecutionMode mode>
+static bool
+SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
+                      Handle<NativeObject*> obj, HandleId id, unsigned attrs, HandleValue v,
+                      bool 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));
 
     if (MOZ_UNLIKELY(obj->watched())) {
@@ -2119,60 +2125,77 @@ baseops::SetPropertyHelper(typename Exec
         return true;
     }
 
     if (obj->is<ArrayObject>() && id == NameToId(cxArg->names().length)) {
         Rooted<ArrayObject*> arr(cxArg, &obj->as<ArrayObject>());
         return ArraySetLength<mode>(cxArg, arr, id, attrs, vp, strict);
     }
 
-    if (!shape) {
-        bool extensible;
-        if (mode == ParallelExecution) {
-            if (obj->is<ProxyObject>())
-                return false;
-            extensible = obj->nonProxyIsExtensible();
-        } else {
-            if (!JSObject::isExtensible(cxArg->asJSContext(), obj, &extensible))
-                return false;
-        }
+    if (shape)
+        return NativeSet<mode>(cxArg, obj, receiver, shape, strict, vp);
+    return SetPropertyByDefining<mode>(cxArg, obj, id, attrs, vp, strict);
+}
 
-        if (!extensible) {
-            /* Error in strict mode code, warn with extra warnings option, otherwise do nothing. */
-            if (strict)
-                return obj->reportNotExtensible(cxArg);
-            if (mode == SequentialExecution &&
-                cxArg->asJSContext()->compartment()->options().extraWarnings(cxArg->asJSContext()))
-            {
-                return obj->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
-            }
-            return true;
-        }
-
-        const Class *clasp = obj->getClass();
-        if (mode == ParallelExecution) {
-            if (obj->isDelegate())
-                return false;
-
-            if (clasp->getProperty != JS_PropertyStub || !types::HasTypePropertyId(obj, id, vp))
-                return false;
-        } else {
-            JSContext *cx = cxArg->asJSContext();
-
-            /* Purge the property cache of now-shadowed id in obj's scope chain. */
-            if (!PurgeScopeChain(cx, obj, id))
-                return false;
-        }
-
-        return DefinePropertyOrElement<mode>(cxArg, obj, id,
-                                             clasp->getProperty, clasp->setProperty,
-                                             attrs, vp, true, 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 obj.
+ *
+ * (FIXME: Should really define it on receiver, not obj.)
+ *
+ * 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,
+                      Handle<NativeObject*> obj, HandleId id, unsigned attrs, HandleValue v,
+                      bool strict)
+{
+    bool extensible;
+    if (mode == ParallelExecution) {
+        if (obj->is<ProxyObject>())
+            return false;
+        extensible = obj->nonProxyIsExtensible();
+    } else {
+        if (!JSObject::isExtensible(cxArg->asJSContext(), obj, &extensible))
+            return false;
     }
 
-    return NativeSet<mode>(cxArg, obj, receiver, shape, strict, vp);
+    if (!extensible) {
+        /* Error in strict mode code, warn with extra warnings option, otherwise do nothing. */
+        if (strict)
+            return obj->reportNotExtensible(cxArg);
+        if (mode == SequentialExecution &&
+            cxArg->asJSContext()->compartment()->options().extraWarnings(cxArg->asJSContext()))
+        {
+            return obj->reportNotExtensible(cxArg, JSREPORT_STRICT | JSREPORT_WARNING);
+        }
+        return true;
+    }
+
+    const Class *clasp = obj->getClass();
+    if (mode == ParallelExecution) {
+        if (obj->isDelegate())
+            return false;
+
+        if (clasp->getProperty != JS_PropertyStub || !types::HasTypePropertyId(obj, id, v))
+            return false;
+    } else {
+        JSContext *cx = cxArg->asJSContext();
+
+        /* Purge the property cache of now-shadowed id in obj's scope chain. */
+        if (!PurgeScopeChain(cx, obj, id))
+            return false;
+    }
+
+    return DefinePropertyOrElement<mode>(cxArg, obj, id,
+                                         clasp->getProperty, clasp->setProperty,
+                                         attrs, v, true, strict);
 }
 
 template bool
 baseops::SetPropertyHelper<SequentialExecution>(JSContext *cx, HandleNativeObject obj,
                                                 HandleObject receiver, HandleId id,
                                                 QualifiedBool qualified,
                                                 MutableHandleValue vp, bool strict);
 template bool