Bug 1052139 - Make the [[Prototype]] of various (but not all) objects on the window object's [[Prototype]] chain immutable. BUT, also disable the code that actually respects immutable-prototype handling -- it'll be a one-liner to revert this when we're ready to do so. Making the rest of the chain immutable will happen in separate patches. r=bz
authorJeff Walden <jwalden@mit.edu>
Fri, 28 Nov 2014 02:58:23 -0500
changeset 266942 692c2ac8d341d25c2afb269b0afd5076b142e9c1
parent 266941 a2788bc9ed7ea00773d977cd71ba52764fef3980
child 266943 de953677a1819ad7e64e647d4c5d6093b2cc76c2
push id66337
push userjwalden@mit.edu
push dateThu, 08 Oct 2015 22:22:44 +0000
treeherdermozilla-inbound@de953677a181 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1052139
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1052139 - Make the [[Prototype]] of various (but not all) objects on the window object's [[Prototype]] chain immutable. BUT, also disable the code that actually respects immutable-prototype handling -- it'll be a one-liner to revert this when we're ready to do so. Making the rest of the chain immutable will happen in separate patches. r=bz
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsobj.cpp
js/src/shell/js.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6385,16 +6385,22 @@ JS_DecodeInterpretedFunction(JSContext* 
 {
     XDRDecoder decoder(cx, data, length);
     RootedFunction funobj(cx);
     if (!decoder.codeFunction(&funobj))
         return nullptr;
     return funobj;
 }
 
+JS_PUBLIC_API(bool)
+JS_SetImmutablePrototype(JSContext *cx, JS::HandleObject obj, bool *succeeded)
+{
+    return SetImmutablePrototype(cx, obj, succeeded);
+}
+
 JS_PUBLIC_API(void)
 JS::SetAsmJSCacheOps(JSRuntime* rt, const JS::AsmJSCacheOps* ops)
 {
     rt->asmJSCacheOps = *ops;
 }
 
 char*
 JSAutoByteString::encodeLatin1(ExclusiveContext* cx, JSString* str)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2457,16 +2457,26 @@ JS_FreezeObject(JSContext* cx, JS::Handl
  * attempt, return false (with a pending exception set, depending upon the
  * nature of the error).  If no error occurs, return true with |result| set
  * to indicate whether the attempt successfully set the [[Extensible]] property
  * to false.
  */
 extern JS_PUBLIC_API(bool)
 JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
 
+/*
+ * Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt
+ * to modify it will fail.  If an error occurs during the attempt, return false
+ * (with a pending exception set, depending upon the nature of the error).  If
+ * no error occurs, return true with |*succeeded| set to indicate whether the
+ * attempt successfully made the [[Prototype]] immutable.
+ */
+extern JS_PUBLIC_API(bool)
+JS_SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded);
+
 extern JS_PUBLIC_API(JSObject*)
 JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
 
 
 /*** Property descriptors ************************************************************************/
 
 struct JSPropertyDescriptor : public JS::Traceable {
     JSObject* obj;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2389,17 +2389,17 @@ JSObject::reportNotExtensible(JSContext*
 }
 
 // Our immutable-prototype behavior is non-standard, and it's unclear whether
 // it's shippable.  (Or at least it's unclear whether it's shippable with any
 // provided-by-default uses exposed to script.)  If this bool is true,
 // immutable-prototype behavior is enforced; if it's false, behavior is not
 // enforced, and immutable-prototype bits stored on objects are completely
 // ignored.
-static const bool ImmutablePrototypesEnabled = true;
+static const bool ImmutablePrototypesEnabled = false;
 
 JS_FRIEND_API(bool)
 JS_ImmutablePrototypesEnabled()
 {
     return ImmutablePrototypesEnabled;
 }
 
 /*** ES6 standard internal methods ***************************************************************/
@@ -3335,16 +3335,17 @@ JSObject::dump()
     if (obj->isQualifiedVarObj()) fprintf(stderr, " varobj");
     if (obj->isUnqualifiedVarObj()) fprintf(stderr, " unqualified_varobj");
     if (obj->watched()) fprintf(stderr, " watched");
     if (obj->isIteratedSingleton()) fprintf(stderr, " iterated_singleton");
     if (obj->isNewGroupUnknown()) fprintf(stderr, " new_type_unknown");
     if (obj->hasUncacheableProto()) fprintf(stderr, " has_uncacheable_proto");
     if (obj->hadElementsAccess()) fprintf(stderr, " had_elements_access");
     if (obj->wasNewScriptCleared()) fprintf(stderr, " new_script_cleared");
+    if (!obj->hasLazyPrototype() && obj->nonLazyPrototypeIsImmutable()) fprintf(stderr, " immutable_prototype");
 
     if (obj->isNative()) {
         NativeObject* nobj = &obj->as<NativeObject>();
         if (nobj->inDictionaryMode())
             fprintf(stderr, " inDictionaryMode");
         if (nobj->hasShapeTable())
             fprintf(stderr, " hasShapeTable");
     }
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5839,16 +5839,23 @@ NewGlobalObject(JSContext* cx, JS::Compa
     {
         JSAutoCompartment ac(cx, glob);
 
 #ifndef LAZY_STANDARD_CLASSES
         if (!JS_InitStandardClasses(cx, glob))
             return nullptr;
 #endif
 
+        bool succeeded;
+        if (!JS_SetImmutablePrototype(cx, glob, &succeeded))
+            return nullptr;
+        MOZ_ASSERT(succeeded,
+                   "a fresh, unexposed global object is always capable of "
+                   "having its [[Prototype]] be immutable");
+
 #ifdef JS_HAS_CTYPES
         if (!JS_InitCTypesClass(cx, glob))
             return nullptr;
 #endif
         if (!JS_InitReflectParse(cx, glob))
             return nullptr;
         if (!JS_DefineDebuggerObject(cx, glob))
             return nullptr;