Bug 1595745 - Part 10: Change Proxy to use ClassSpec. r=mgaudet
☠☠ backed out by ec8cad689121 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 15 Nov 2019 15:55:26 +0000
changeset 502204 a514661afdda948c4fb0917375534f06a82ff5b0
parent 502203 29ec5ccb4adf6d914edf9fb7dfaf9f362a902455
child 502205 e089ebe699d2ef3729774765db5c47a58995435f
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1595745
milestone72.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 1595745 - Part 10: Change Proxy to use ClassSpec. r=mgaudet Proxy JSClasses are defined through a special macro (`PROXY_CLASS_DEF`), which ensures all Proxy related bits are set correctly. The macro doesn't allow to specify a ClassSpec, so we need to add a new macro which supports that functionality. Differential Revision: https://phabricator.services.mozilla.com/D52666
js/public/ProtoKey.h
js/public/Proxy.h
js/src/proxy/Proxy.cpp
js/src/proxy/Proxy.h
--- a/js/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -81,17 +81,17 @@
   REAL(Int32Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Int32))               \
   REAL(Uint32Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint32))             \
   REAL(Float32Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32))           \
   REAL(Float64Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64))           \
   REAL(Uint8ClampedArray, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \
   REAL(BigInt64Array, InitViaClassSpec, TYPED_ARRAY_CLASP(BigInt64))         \
   REAL(BigUint64Array, InitViaClassSpec, TYPED_ARRAY_CLASP(BigUint64))       \
   REAL(BigInt, InitViaClassSpec, OCLASP(BigInt))                             \
-  REAL(Proxy, InitProxyClass, &js::ProxyClass)                               \
+  REAL(Proxy, InitViaClassSpec, CLASP(Proxy))                                \
   REAL(WeakMap, InitViaClassSpec, OCLASP(WeakMap))                           \
   REAL(Map, InitViaClassSpec, OCLASP(Map))                                   \
   REAL(Set, InitViaClassSpec, OCLASP(Set))                                   \
   REAL(DataView, InitViaClassSpec, OCLASP(DataView))                         \
   REAL(Symbol, InitViaClassSpec, OCLASP(Symbol))                             \
   REAL(SharedArrayBuffer, InitViaClassSpec, OCLASP(SharedArrayBuffer))       \
   REAL_IF_INTL(Intl, InitViaClassSpec, CLASP(Intl))                          \
   REAL_IF_INTL(Collator, InitViaClassSpec, OCLASP(Collator))                 \
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -720,25 +720,28 @@ constexpr unsigned CheckProxyFlags() {
   // always have finalizers, and whether they can be nursery allocated is
   // controlled by the canNurseryAllocate() method on the proxy handler.
   static_assert(!(Flags & JSCLASS_SKIP_NURSERY_FINALIZE),
                 "Proxies must not use JSCLASS_SKIP_NURSERY_FINALIZE; use "
                 "the canNurseryAllocate() proxy handler method instead.");
   return Flags;
 }
 
-#define PROXY_CLASS_DEF(name, flags)                                       \
+#define PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, classSpec)            \
   {                                                                        \
     name,                                                                  \
         JSClass::NON_NATIVE | JSCLASS_IS_PROXY |                           \
             JSCLASS_DELAY_METADATA_BUILDER | js::CheckProxyFlags<flags>(), \
-        &js::ProxyClassOps, JS_NULL_CLASS_SPEC, &js::ProxyClassExtension,  \
+        &js::ProxyClassOps, classSpec, &js::ProxyClassExtension,           \
         &js::ProxyObjectOps                                                \
   }
 
+#define PROXY_CLASS_DEF(name, flags) \
+  PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, JS_NULL_CLASS_SPEC)
+
 // Converts a proxy into a DeadObjectProxy that will throw exceptions on all
 // access. This will run the proxy's finalizer to perform clean-up before the
 // conversion happens.
 JS_FRIEND_API void NukeNonCCWProxy(JSContext* cx, HandleObject proxy);
 
 // This is a variant of js::NukeNonCCWProxy() for CCWs. It should only be called
 // on CCWs that have been removed from CCW tables.
 JS_FRIEND_API void NukeRemovedCrossCompartmentWrapper(JSContext* cx,
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -748,19 +748,27 @@ const ClassExtension js::ProxyClassExten
 
 const ObjectOps js::ProxyObjectOps = {
     proxy_LookupProperty, Proxy::defineProperty,
     Proxy::has,           Proxy::get,
     Proxy::set,           Proxy::getOwnPropertyDescriptor,
     proxy_DeleteProperty, Proxy::getElements,
     Proxy::fun_toString};
 
-const JSClass js::ProxyClass =
-    PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) |
-                                 JSCLASS_HAS_RESERVED_SLOTS(2));
+static const JSFunctionSpec proxy_static_methods[] = {
+    JS_FN("revocable", proxy_revocable, 2, 0), JS_FS_END};
+
+static const ClassSpec ProxyClassSpec = {
+    GenericCreateConstructor<js::proxy, 2, gc::AllocKind::FUNCTION>, nullptr,
+    proxy_static_methods, nullptr};
+
+const JSClass js::ProxyClass = PROXY_CLASS_DEF_WITH_CLASS_SPEC(
+    "Proxy",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) | JSCLASS_HAS_RESERVED_SLOTS(2),
+    &ProxyClassSpec);
 
 JS_FRIEND_API JSObject* js::NewProxyObject(JSContext* cx,
                                            const BaseProxyHandler* handler,
                                            HandleValue priv, JSObject* proto_,
                                            const ProxyOptions& options) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
@@ -789,29 +797,8 @@ void ProxyObject::renew(const BaseProxyH
   MOZ_ASSERT(hasDynamicPrototype());
 
   setHandler(handler);
   setCrossCompartmentPrivate(priv);
   for (size_t i = 0; i < numReservedSlots(); i++) {
     setReservedSlot(i, UndefinedValue());
   }
 }
-
-JSObject* js::InitProxyClass(JSContext* cx, Handle<GlobalObject*> global) {
-  static const JSFunctionSpec static_methods[] = {
-      JS_FN("revocable", proxy_revocable, 2, 0), JS_FS_END};
-
-  RootedFunction ctor(cx);
-  ctor = GlobalObject::createConstructor(cx, proxy, cx->names().Proxy, 2);
-  if (!ctor) {
-    return nullptr;
-  }
-
-  if (!JS_DefineFunctions(cx, ctor, static_methods)) {
-    return nullptr;
-  }
-  if (!JS_DefineProperty(cx, global, "Proxy", ctor, JSPROP_RESOLVING)) {
-    return nullptr;
-  }
-
-  global->setConstructor(JSProto_Proxy, ObjectValue(*ctor));
-  return ctor;
-}
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -8,18 +8,16 @@
 #define proxy_Proxy_h
 
 #include "NamespaceImports.h"
 
 #include "js/Class.h"
 
 namespace js {
 
-class GlobalObject;
-
 /*
  * Dispatch point for handlers that executes the appropriate C++ or scripted
  * traps.
  *
  * Important: All proxy methods need either (a) an AutoEnterPolicy in their
  * Proxy::foo entry point below or (b) an override in SecurityWrapper. See bug
  * 945826 comment 0.
  */
@@ -106,13 +104,11 @@ bool ProxyGetPropertyByValue(JSContext* 
                              HandleValue idVal, MutableHandleValue vp);
 
 bool ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id,
                       HandleValue val, bool strict);
 
 bool ProxySetPropertyByValue(JSContext* cx, HandleObject proxy,
                              HandleValue idVal, HandleValue val, bool strict);
 
-extern JSObject* InitProxyClass(JSContext* cx, Handle<GlobalObject*> global);
-
 } /* namespace js */
 
 #endif /* proxy_Proxy_h */