Bug 1017988 part 11. Codegen the definition of interface objects on worker globals. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 04 Aug 2014 22:20:35 -0400
changeset 197786 3d59b6f2a9297ac0b8266981668c2e424993ae2b
parent 197785 cf0848334ad24bfa4a889e3a65da12c5441710da
child 197787 003e3f31ea6b6b553b305a35556e4727d59e157d
push id27250
push useremorley@mozilla.com
push dateTue, 05 Aug 2014 14:25:40 +0000
treeherdermozilla-central@2aaedcdf69f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1017988
milestone34.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 1017988 part 11. Codegen the definition of interface objects on worker globals. r=khuey
dom/bindings/Codegen.py
dom/bindings/Configuration.py
dom/bindings/mozwebidlcodegen/__init__.py
dom/workers/RegisterBindings.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/test/test_worker_interfaces.js
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -10629,19 +10629,17 @@ class CGDescriptor(CGThing):
         if descriptor.interface.hasInterfacePrototypeObject():
             cgThings.append(CGPrototypeJSClass(descriptor, properties))
 
         if descriptor.interface.hasInterfaceObject():
             cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
 
         if ((descriptor.interface.hasInterfaceObject() or descriptor.interface.getNavigatorProperty()) and
             not descriptor.interface.isExternal() and
-            descriptor.isExposedConditionally() and
-            # Workers stuff is never conditional
-            not descriptor.workers):
+            descriptor.isExposedConditionally()):
             cgThings.append(CGConstructorEnabled(descriptor))
 
         if (descriptor.interface.hasMembersInSlots() and
             descriptor.interface.hasChildInterfaces()):
             raise TypeError("We don't support members in slots on "
                             "non-leaf interfaces like %s" %
                             descriptor.interface.identifier.name)
 
@@ -11328,16 +11326,58 @@ class CGDictionary(CGThing):
     @staticmethod
     def isDictionaryCopyConstructible(dictionary):
         if (dictionary.parent and
             not CGDictionary.isDictionaryCopyConstructible(dictionary.parent)):
             return False
         return all(isTypeCopyConstructible(m.type) for m in dictionary.members)
 
 
+class CGRegisterWorkerBindings(CGAbstractMethod):
+    def __init__(self, config):
+        CGAbstractMethod.__init__(self, None, 'RegisterWorkerBindings', 'bool',
+                                  [Argument('JSContext*', 'aCx'),
+                                   Argument('JS::Handle<JSObject*>', 'aObj')])
+        self.config = config
+
+    def definition_body(self):
+        # We have to be a bit careful: Some of the interfaces we want to expose
+        # in workers only have one descriptor, while others have both a worker
+        # and a non-worker descriptor.  When both are present we want the worker
+        # descriptor, but otherwise we want whatever descriptor we've got.
+        descriptors = self.config.getDescriptors(hasInterfaceObject=True,
+                                                 isExposedInAllWorkers=True,
+                                                 register=True,
+                                                 skipGen=False,
+                                                 workers=True)
+        workerDescriptorIfaceNames = set(d.interface.identifier.name for
+                                         d in descriptors)
+        descriptors.extend(
+            filter(
+                lambda d: d.interface.identifier.name not in workerDescriptorIfaceNames,
+                self.config.getDescriptors(hasInterfaceObject=True,
+                                           isExposedInAllWorkers=True,
+                                           register=True,
+                                           skipGen=False,
+                                           workers=False)))
+        conditions = []
+        for desc in descriptors:
+            bindingNS = toBindingNamespace(desc.name)
+            condition = "!%s::GetConstructorObject(aCx, aObj)" % bindingNS
+            if desc.isExposedConditionally():
+                condition = (
+                    "%s::ConstructorEnabled(aCx, aObj) && " % bindingNS
+                    + condition)
+            conditions.append(condition)
+        lines = [CGIfWrapper(CGGeneric("return false;\n"), condition) for
+                 condition in conditions]
+        lines.append(CGGeneric("return true;\n"))
+        return CGList(lines, "\n").define()
+
+
 class CGRegisterProtos(CGAbstractMethod):
     def __init__(self, config):
         CGAbstractMethod.__init__(self, None, 'Register', 'void',
                                   [Argument('nsScriptNameSpaceManager*', 'aNameSpaceManager')])
         self.config = config
 
     def _defineMacro(self):
         return dedent("""
@@ -13720,16 +13760,43 @@ class GlobalGenRoots():
 
         # Add include guards.
         curr = CGIncludeGuard('RegisterBindings', curr)
 
         # Done.
         return curr
 
     @staticmethod
+    def RegisterWorkerBindings(config):
+
+        # TODO - Generate the methods we want
+        curr = CGRegisterWorkerBindings(config)
+
+        # Wrap all of that in our namespaces.
+        curr = CGNamespace.build(['mozilla', 'dom'],
+                                 CGWrapper(curr, post='\n'))
+        curr = CGWrapper(curr, post='\n')
+
+        # Add the includes
+        defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
+                          for desc in config.getDescriptors(hasInterfaceObject=True,
+                                                            register=True,
+                                                            isExposedInAllWorkers=True,
+                                                            skipGen=False)]
+
+        curr = CGHeaders([], [], [], [], [], defineIncludes,
+                         'RegisterWorkerBindings', curr)
+
+        # Add include guards.
+        curr = CGIncludeGuard('RegisterWorkerBindings', curr)
+
+        # Done.
+        return curr
+
+    @staticmethod
     def UnionTypes(config):
 
         (includes, implincludes,
          declarations, unions) = UnionTypes(config.getDescriptors(),
                                             config.getDictionaries(),
                                             config.getCallbacks(),
                                             config)
         includes.add("mozilla/dom/OwningNonNull.h")
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -133,16 +133,18 @@ class Configuration:
             elif key == 'isCallback':
                 getter = lambda x: x.interface.isCallback()
             elif key == 'isExternal':
                 getter = lambda x: x.interface.isExternal()
             elif key == 'isJSImplemented':
                 getter = lambda x: x.interface.isJSImplemented()
             elif key == 'isNavigatorProperty':
                 getter = lambda x: x.interface.getNavigatorProperty() != None
+            elif key == 'isExposedInAllWorkers':
+                getter = lambda x: not x.interface.isExternal() and "Worker" in x.interface._exposureGlobalNames
             else:
                 # Have to watch out: just closing over "key" is not enough,
                 # since we're about to mutate its value
                 getter = (lambda attrName: lambda x: getattr(x, attrName))(key)
             tofilter.append((getter, val))
         for f in tofilter:
             curr = filter(lambda x: f[0](x) == f[1], curr)
         return curr
--- a/dom/bindings/mozwebidlcodegen/__init__.py
+++ b/dom/bindings/mozwebidlcodegen/__init__.py
@@ -126,23 +126,25 @@ class WebIDLCodegenManager(LoggingMixin)
     """
 
     # Global parser derived declaration files.
     GLOBAL_DECLARE_FILES = {
         'FeatureList.h',
         'GeneratedAtomList.h',
         'PrototypeList.h',
         'RegisterBindings.h',
+        'RegisterWorkerBindings.h',
         'UnionConversions.h',
         'UnionTypes.h',
     }
 
     # Global parser derived definition files.
     GLOBAL_DEFINE_FILES = {
         'RegisterBindings.cpp',
+        'RegisterWorkerBindings.cpp',
         'UnionTypes.cpp',
         'PrototypeList.cpp',
     }
 
     def __init__(self, config_path, inputs, exported_header_dir,
         codegen_dir, state_path, cache_dir=None, make_deps_path=None,
         make_deps_target=None):
         """Create an instance that manages WebIDLs in the build system.
--- a/dom/workers/RegisterBindings.cpp
+++ b/dom/workers/RegisterBindings.cpp
@@ -5,86 +5,40 @@
 
 #include "WorkerPrivate.h"
 #include "ChromeWorkerScope.h"
 #include "File.h"
 #include "RuntimeService.h"
 
 #include "jsapi.h"
 #include "js/OldDebugAPI.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/ConsoleBinding.h"
-#include "mozilla/dom/DOMExceptionBinding.h"
-#include "mozilla/dom/EventBinding.h"
-#include "mozilla/dom/EventHandlerBinding.h"
-#include "mozilla/dom/EventTargetBinding.h"
-#include "mozilla/dom/FileReaderSyncBinding.h"
-#include "mozilla/dom/HeadersBinding.h"
-#include "mozilla/dom/ImageData.h"
-#include "mozilla/dom/ImageDataBinding.h"
-#include "mozilla/dom/MessageEventBinding.h"
-#include "mozilla/dom/MessagePortBinding.h"
-#include "mozilla/dom/PromiseBinding.h"
-#include "mozilla/dom/TextDecoderBinding.h"
-#include "mozilla/dom/TextEncoderBinding.h"
-#include "mozilla/dom/XMLHttpRequestBinding.h"
-#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
-#include "mozilla/dom/URLBinding.h"
-#include "mozilla/dom/URLSearchParamsBinding.h"
-#include "mozilla/dom/WorkerBinding.h"
-#include "mozilla/dom/WorkerLocationBinding.h"
-#include "mozilla/dom/WorkerNavigatorBinding.h"
+#include "mozilla/dom/RegisterWorkerBindings.h"
 #include "mozilla/OSFileConstants.h"
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::dom;
 
 bool
 WorkerPrivate::RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
 {
-  JS::Rooted<JSObject*> eventTargetProto(aCx,
-    EventTargetBinding::GetProtoObject(aCx, aGlobal));
-  if (!eventTargetProto) {
+  // Init Web IDL bindings
+  if (!RegisterWorkerBindings(aCx, aGlobal)) {
     return false;
   }
 
   if (IsChromeWorker()) {
-    if (!ChromeWorkerBinding::GetConstructorObject(aCx, aGlobal) ||
-        !DefineChromeWorkerFunctions(aCx, aGlobal) ||
+    if (!DefineChromeWorkerFunctions(aCx, aGlobal) ||
         !DefineOSFileConstants(aCx, aGlobal)) {
       return false;
     }
   }
 
   // Init other classes we care about.
   if (!file::InitClasses(aCx, aGlobal)) {
     return false;
   }
 
-  // Init other paris-bindings.
-  if (!ConsoleBinding::GetConstructorObject(aCx, aGlobal) ||
-      !DOMExceptionBinding::GetConstructorObject(aCx, aGlobal) ||
-      !EventBinding::GetConstructorObject(aCx, aGlobal) ||
-      !FileReaderSyncBinding_workers::GetConstructorObject(aCx, aGlobal) ||
-      (HeadersBinding::ConstructorEnabled(aCx, aGlobal) &&
-       !HeadersBinding::GetConstructorObject(aCx, aGlobal)) ||
-      !ImageDataBinding::GetConstructorObject(aCx, aGlobal) ||
-      !MessageEventBinding::GetConstructorObject(aCx, aGlobal) ||
-      !MessagePortBinding::GetConstructorObject(aCx, aGlobal) ||
-      !PromiseBinding::GetConstructorObject(aCx, aGlobal) ||
-      !TextDecoderBinding::GetConstructorObject(aCx, aGlobal) ||
-      !TextEncoderBinding::GetConstructorObject(aCx, aGlobal) ||
-      !XMLHttpRequestBinding_workers::GetConstructorObject(aCx, aGlobal) ||
-      !XMLHttpRequestUploadBinding_workers::GetConstructorObject(aCx, aGlobal) ||
-      !URLBinding_workers::GetConstructorObject(aCx, aGlobal) ||
-      !URLSearchParamsBinding::GetConstructorObject(aCx, aGlobal) ||
-      !WorkerBinding::GetConstructorObject(aCx, aGlobal) ||
-      !WorkerLocationBinding_workers::GetConstructorObject(aCx, aGlobal) ||
-      !WorkerNavigatorBinding_workers::GetConstructorObject(aCx, aGlobal)) {
-    return false;
-  }
-
   if (!JS_DefineProfilingFunctions(aCx, aGlobal)) {
     return false;
   }
 
   return true;
 }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3575,21 +3575,27 @@ ChromeWorkerPrivate::Constructor(const G
   return WorkerPrivate::Constructor(aGlobal, aScriptURL, true,
                                     WorkerTypeDedicated, EmptyCString(),
                                     nullptr, aRv)
                                     .downcast<ChromeWorkerPrivate>();
 }
 
 // static
 bool
-ChromeWorkerPrivate::WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */)
+ChromeWorkerPrivate::WorkerAvailable(JSContext* aCx, JSObject* /* unused */)
 {
-  // Chrome is always allowed to use workers, and content is never allowed to
-  // use ChromeWorker, so all we have to check is the caller.
-  return nsContentUtils::ThreadsafeIsCallerChrome();
+  // Chrome is always allowed to use workers, and content is never
+  // allowed to use ChromeWorker, so all we have to check is the
+  // caller.  However, chrome workers apparently might not have a
+  // system principal, so we have to check for them manually.
+  if (NS_IsMainThread()) {
+    return nsContentUtils::IsCallerChrome();
+  }
+
+  return GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
 }
 
 // static
 already_AddRefed<WorkerPrivate>
 WorkerPrivate::Constructor(const GlobalObject& aGlobal,
                            const nsAString& aScriptURL,
                            bool aIsChromeWorker, WorkerType aWorkerType,
                            const nsACString& aSharedWorkerName,
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1186,17 +1186,17 @@ private:
 class ChromeWorkerPrivate : public WorkerPrivate
 {
 public:
   static already_AddRefed<ChromeWorkerPrivate>
   Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
               ErrorResult& rv);
 
   static bool
-  WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */);
+  WorkerAvailable(JSContext* aCx, JSObject* /* unused */);
 
 private:
   ChromeWorkerPrivate() MOZ_DELETE;
   ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
   ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
 };
 
 WorkerPrivate*
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -25,30 +25,27 @@ var ecmaGlobals =
     "Boolean",
     "DataView",
     "Date",
     "Error",
     "EvalError",
     "Float32Array",
     "Float64Array",
     "Function",
-    // NB: We haven't bothered to resolve constants like Infinity and NaN on
-    // Xrayed windows (which are seen from the XBL scope). We could support
-    // this if needed with some refactoring.
-    {name: "Infinity"},
+    "Infinity",
     "Int16Array",
     "Int32Array",
     "Int8Array",
     "InternalError",
     {name: "Intl", desktop: true},
     "Iterator",
     "JSON",
     "Map",
     "Math",
-    {name: "NaN"},
+    "NaN",
     "Number",
     "Object",
     "Proxy",
     "RangeError",
     "ReferenceError",
     "RegExp",
     "Set",
     {name: "SharedArrayBuffer", nightly: true},
@@ -70,19 +67,21 @@ var ecmaGlobals =
 //            a JavaScript Engine peer!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Blob",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Console",
+    "DedicatedWorkerGlobalScope",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DedicatedWorkerGlobalScope",
+    { name: "DataStore", b2g: true },
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    { name: "DataStoreCursor", b2g: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMException",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Event",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "EventTarget",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "File",