Bug 1474739 - Part 2: Remove all code for XPT shims, r=bzbarsky
authorNika Layzell <nika@thelayzells.com>
Wed, 01 Aug 2018 15:14:58 -0400
changeset 429739 da7308cd7b0f1f50bde54e908ef86e2fdba2b792
parent 429738 1a5c1ee48c9102ef8939bca79fa02686cea56b8e
child 429740 62a0e59c7e1a23a0774c4cca4ea2cd98c0838ff0
push id34372
push usernerli@mozilla.com
push dateThu, 02 Aug 2018 08:55:28 +0000
treeherdermozilla-central@bd79b07f57a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1474739
milestone63.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 1474739 - Part 2: Remove all code for XPT shims, r=bzbarsky Summary: Depends On D2624 Reviewers: bzbarsky! Tags: #secure-revision Bug #: 1474739 Differential Revision: https://phabricator.services.mozilla.com/D2625
xpcom/idl-parser/xpidl/jsonxpt.py
xpcom/idl-parser/xpidl/xpidl.py
xpcom/reflect/xptinfo/xptcodegen.py
xpcom/reflect/xptinfo/xptinfo.cpp
xpcom/reflect/xptinfo/xptinfo.h
--- a/xpcom/idl-parser/xpidl/jsonxpt.py
+++ b/xpcom/idl-parser/xpidl/jsonxpt.py
@@ -207,55 +207,42 @@ def build_interface(iface):
             build_attr(member)
         elif isinstance(member, xpidl.Method):
             build_method(member)
         elif isinstance(member, xpidl.CDATA):
             pass
         else:
             raise Exception("Unexpected interface member: %s" % member)
 
-    assert iface.attributes.shim is not None or iface.attributes.shimfile is None
-
     return {
         'name': iface.name,
         'uuid': iface.attributes.uuid,
         'methods': methods,
         'consts': consts,
         'parent': iface.base,
-        'shim': iface.attributes.shim,
-        'shimfile': iface.attributes.shimfile,
         'flags': flags(
             ('scriptable', iface.attributes.scriptable),
             ('function', iface.attributes.function),
             ('builtinclass', iface.attributes.builtinclass or iface.implicit_builtinclass),
             ('main_process_only', iface.attributes.main_process_scriptable_only),
         )
     }
 
 
 # These functions are the public interface of this module. They are very simple
 # functions, but are exported so that if we need to do something more
 # complex in them in the future we can.
 
-# Given a parsed IDL file, generate and return the typelib for that file.
 def build_typelib(idl):
-    def exported(p):
-        if p.kind != 'interface':
-            return False
-        # Only export scriptable or shim interfaces
-        return p.attributes.scriptable or p.attributes.shim
-
-    return [build_interface(p) for p in idl.productions if exported(p)]
-
-# Link a list of typelibs together into a single typelib
-
+    """Given a parsed IDL file, generate and return the typelib"""
+    return [build_interface(p) for p in idl.productions
+            if p.kind == 'interface' and p.attributes.scriptable]
 
 def link(typelibs):
+    """Link a list of typelibs together into a single typelib"""
     linked = list(itertools.chain.from_iterable(typelibs))
     assert len(set(iface['name'] for iface in linked)) == len(linked), \
         "Multiple typelibs containing the same interface were linked together"
     return linked
 
-# Write the typelib into the fd file
-
-
 def write(typelib, fd):
+    """Write typelib into fd"""
     json.dump(typelib, fd, indent=2)
--- a/xpcom/idl-parser/xpidl/xpidl.py
+++ b/xpcom/idl-parser/xpidl/xpidl.py
@@ -805,18 +805,16 @@ class Interface(object):
 
 class InterfaceAttributes(object):
     uuid = None
     scriptable = False
     builtinclass = False
     function = False
     noscript = False
     main_process_scriptable_only = False
-    shim = None
-    shimfile = None
 
     def setuuid(self, value):
         self.uuid = value.lower()
 
     def setscriptable(self):
         self.scriptable = True
 
     def setfunction(self):
@@ -826,32 +824,24 @@ class InterfaceAttributes(object):
         self.noscript = True
 
     def setbuiltinclass(self):
         self.builtinclass = True
 
     def setmain_process_scriptable_only(self):
         self.main_process_scriptable_only = True
 
-    def setshim(self, value):
-        self.shim = value
-
-    def setshimfile(self, value):
-        self.shimfile = value
-
     actions = {
         'uuid':       (True, setuuid),
         'scriptable': (False, setscriptable),
         'builtinclass': (False, setbuiltinclass),
         'function':   (False, setfunction),
         'noscript':   (False, setnoscript),
         'object':     (False, lambda self: True),
         'main_process_scriptable_only': (False, setmain_process_scriptable_only),
-        'shim':    (True, setshim),
-        'shimfile': (True, setshimfile),
     }
 
     def __init__(self, attlist, location):
         def badattribute(self):
             raise IDLError("Unexpected interface attribute '%s'" % name, location)
 
         for name, val, aloc in attlist:
             hasval, action = self.actions.get(name, (False, badattribute))
@@ -878,20 +868,16 @@ class InterfaceAttributes(object):
         if self.scriptable:
             l.append("\tscriptable\n")
         if self.builtinclass:
             l.append("\tbuiltinclass\n")
         if self.function:
             l.append("\tfunction\n")
         if self.main_process_scriptable_only:
             l.append("\tmain_process_scriptable_only\n")
-        if self.shim:
-            l.append("\tshim: %s\n" % self.shim)
-        if self.shimfile:
-            l.append("\tshimfile: %s\n" % self.shimfile)
         return "".join(l)
 
 
 class ConstMember(object):
     kind = 'const'
 
     def __init__(self, type, name, value, location, doccomments):
         self.type = type
--- a/xpcom/reflect/xptinfo/xptcodegen.py
+++ b/xpcom/reflect/xptinfo/xptcodegen.py
@@ -1,18 +1,15 @@
 #!/usr/bin/env python
 # jsonlink.py - Merge JSON typelib files into a .cpp file
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# NOTE: Once shims are removed, this code can be cleaned up, removing all
-# reference to them.
-
 import json
 from perfecthash import PerfectHash
 from collections import OrderedDict
 import buildconfig
 
 # Pick a nice power-of-two size for our intermediate PHF tables.
 PHFSIZE = 512
 
@@ -44,17 +41,16 @@ def mkstruct(*fields):
 nsXPTInterfaceInfo = mkstruct(
     "mIID",
     "mName",
     "mParent",
     "mBuiltinClass",
     "mMainProcessScriptableOnly",
     "mMethods",
     "mConsts",
-    "mIsShim",
     "mFunction",
     "mNumMethods",
     "mNumConsts",
 )
 
 ##########################################################
 # Ensure these fields are in the same order as xptinfo.h #
 ##########################################################
@@ -97,17 +93,17 @@ nsXPTDOMObjectInfo = mkstruct(
     "mUnwrap",
     "mWrap",
     "mCleanup",
 )
 
 ##########################################################
 # Ensure these fields are in the same order as xptinfo.h #
 ##########################################################
-ConstInfo = mkstruct(
+nsXPTConstantInfo = mkstruct(
     "mName",
     "mSigned",
     "mValue",
 )
 
 
 # Helper functions for dealing with IIDs.
 #
@@ -357,58 +353,33 @@ def link_to_cpp(interfaces, fd):
         assert const['type']['tag'] in \
             ['TD_INT16', 'TD_INT32', 'TD_UINT16', 'TD_UINT32']
         is_signed = const['type']['tag'] in ['TD_INT16', 'TD_INT32']
 
         # Constants are always either signed or unsigned 16 or 32 bit integers,
         # which we will only need to convert to JS values. To save on space,
         # don't bother storing the type, and instead just store a 32-bit
         # unsigned integer, and stash whether to interpret it as signed.
-        consts.append(ConstInfo(
+        consts.append(nsXPTConstantInfo(
             "%d = %s::%s" % (len(consts), ifacename, const['name']),
 
             mName=lower_string(const['name']),
             mSigned=is_signed,
             mValue="(uint32_t)%d" % const['value'],
         ))
 
-    def lower_prop_hooks(iface):  # XXX: Used by xpt shims
-        assert iface['shim'] is not None
-
-        # Add an include for the Binding file for the shim.
-        includes.add("mozilla/dom/%sBinding.h" %
-                     (iface['shimfile'] or iface['shim']))
-
-        # Add the property hook reference to the sPropHooks table.
-        prophooks.append(
-            "mozilla::dom::%s_Binding::sNativePropertyHooks, // %d = %s(%s)" %
-            (iface['shim'], len(prophooks), iface['name'], iface['shim']))
-
     def ancestors(iface):
         yield iface
         while iface['parent']:
             iface = name_phf.get_entry(iface['parent'].encode('ascii'))
             yield iface
 
     def lower_iface(iface):
-        isshim = iface['shim'] is not None
-        assert isshim or 'scriptable' in iface['flags']
-
-        method_off = len(methods)
-        consts_off = len(consts)
-        method_cnt = const_cnt = 0
-        if isshim:
-            # If we are looking at a shim, don't lower any methods or constants,
-            # as they will be pulled from the WebIDL binding instead. Instead,
-            # we use the constants offset field to store the index into the prop
-            # hooks table.
-            consts_off = len(prophooks)
-        else:
-            method_cnt = sum(len(i['methods']) for i in ancestors(iface))
-            const_cnt = sum(len(i['consts']) for i in ancestors(iface))
+        method_cnt = sum(len(i['methods']) for i in ancestors(iface))
+        const_cnt = sum(len(i['consts']) for i in ancestors(iface))
 
         # The number of maximum methods is not arbitrary. It is the same value
         # as in xpcom/reflect/xptcall/genstubs.pl; do not change this value
         # without changing that one or you WILL see problems.
         #
         # In addition, mNumMethods and mNumConsts are stored as a 8-bit ints,
         # meaning we cannot exceed 255 methods/consts on any interface.
         assert method_cnt < 250, "%s has too many methods" % iface['name']
@@ -417,33 +388,28 @@ def link_to_cpp(interfaces, fd):
         # Store the lowered interface as 'cxx' on the iface object.
         iface['cxx'] = nsXPTInterfaceInfo(
             "%d = %s" % (iface['idx'], iface['name']),
 
             mIID=lower_uuid(iface['uuid']),
             mName=lower_string(iface['name']),
             mParent=interface_idx(iface['parent']),
 
-            mMethods=method_off,
+            mMethods=len(methods),
             mNumMethods=method_cnt,
-            mConsts=consts_off,
+            mConsts=len(consts),
             mNumConsts=const_cnt,
 
             # Flags
-            mIsShim=isshim,
             mBuiltinClass='builtinclass' in iface['flags'],
             mMainProcessScriptableOnly='main_process_only' in iface['flags'],
             mFunction='function' in iface['flags'],
         )
 
-        if isshim:
-            lower_prop_hooks(iface)
-            return
-
-        # Lower the methods and constants used by this interface
+        # Lower methods and constants used by this interface
         for method in iface['methods']:
             lower_method(method, iface['name'])
         for const in iface['consts']:
             lower_const(const, iface['name'])
 
     # Lower the types which have fixed indexes first, and check that the indexes
     # seem correct.
     for expected, ty in enumerate(utility_types):
@@ -452,18 +418,18 @@ def link_to_cpp(interfaces, fd):
 
     # Lower interfaces in the order of the IID phf's entries lookup.
     for iface in iid_phf.entries:
         lower_iface(iface)
 
     # Write out the final output file
     fd.write("/* THIS FILE WAS GENERATED BY xptcodegen.py - DO NOT EDIT */\n\n")
 
-    # Include any bindings files which we need to include due to XPT shims.
-    for include in includes:
+    # Include any bindings files which we need to include for webidl types
+    for include in sorted(includes):
         fd.write('#include "%s"\n' % include)
 
     # Write out our header
     fd.write("""
 #include "xptinfo.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/dom/BindingUtils.h"
 
@@ -497,18 +463,17 @@ namespace detail {
     # Static data arrays
     def array(ty, name, els):
         fd.write("const %s %s[] = {%s\n};\n\n" %
                  (ty, name, ','.join(indented('\n' + str(e)) for e in els)))
     array("nsXPTType", "sTypes", types)
     array("nsXPTParamInfo", "sParams", params)
     array("nsXPTMethodInfo", "sMethods", methods)
     array("nsXPTDOMObjectInfo", "sDOMObjects", domobjects)
-    array("ConstInfo", "sConsts", consts)
-    array("mozilla::dom::NativePropertyHooks*", "sPropHooks", prophooks)
+    array("nsXPTConstantInfo", "sConsts", consts)
 
     # The strings array. We write out individual characters to avoid MSVC restrictions.
     fd.write("const char sStrings[] = {\n")
     for s, off in strings.iteritems():
         fd.write("  // %d = %s\n  '%s','\\0',\n" % (off, s, "','".join(s)))
     fd.write("};\n\n")
 
     # Build the perfect hash table for InterfaceByIID
--- a/xpcom/reflect/xptinfo/xptinfo.cpp
+++ b/xpcom/reflect/xptinfo/xptinfo.cpp
@@ -13,111 +13,41 @@ using namespace mozilla;
 using namespace mozilla::dom;
 using namespace xpt::detail;
 
 
 ////////////////////////////////////
 // Constant Lookup Helper Methods //
 ////////////////////////////////////
 
-// XXX: Remove when shims are gone.
-// This method either looks for the ConstantSpec at aIndex, or counts the
-// number of constants for a given shim.
-// NOTE: Only one of the aSpec and aCount outparameters should be provided.
-// NOTE: If aSpec is not passed, aIndex is ignored.
-// NOTE: aIndex must be in range if aSpec is passed.
-static void
-GetWebIDLConst(uint16_t aHookIdx, uint16_t aIndex,
-               const ConstantSpec** aSpec, uint16_t* aCount)
-{
-  MOZ_ASSERT((aSpec && !aCount) || (aCount && !aSpec),
-             "Only one of aSpec and aCount should be provided");
-
-  const NativePropertyHooks* propHooks = sPropHooks[aHookIdx];
-
-  uint16_t idx = 0;
-  do {
-    const NativeProperties* props[] = {
-      propHooks->mNativeProperties.regular,
-      propHooks->mNativeProperties.chromeOnly
-    };
-    for (size_t i = 0; i < ArrayLength(props); ++i) {
-      auto prop = props[i];
-      if (prop && prop->HasConstants()) {
-        for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
-          // We have found one constant here.  We explicitly do not bother
-          // calling isEnabled() here because it's OK to define potentially
-          // extra constants on these shim interfaces.
-          if (aSpec && idx == aIndex) {
-            *aSpec = cs;
-            return;
-          }
-          ++idx;
-        }
-      }
-    }
-  } while ((propHooks = propHooks->mProtoHooks));
-
-  MOZ_ASSERT(aCount, "aIndex is out of bounds!");
-  *aCount = idx;
-}
 
 bool
 nsXPTInterfaceInfo::HasAncestor(const nsIID& aIID) const
 {
   for (const auto* info = this; info; info = info->GetParent()) {
     if (info->IID() == aIID) {
       return true;
     }
   }
   return false;
 }
 
-uint16_t
-nsXPTInterfaceInfo::ConstantCount() const
+const nsXPTConstantInfo&
+nsXPTInterfaceInfo::Constant(uint16_t aIndex) const
 {
-  if (!mIsShim) {
-    return mNumConsts;
+  MOZ_ASSERT(aIndex < ConstantCount());
+
+  if (const nsXPTInterfaceInfo* pi = GetParent()) {
+    if (aIndex < pi->ConstantCount()) {
+      return pi->Constant(aIndex);
+    }
+    aIndex -= pi->ConstantCount();
   }
 
-  // Get the number of WebIDL constants.
-  uint16_t num = 0;
-  GetWebIDLConst(mConsts, 0, nullptr, &num);
-  return num;
-}
-
-const char*
-nsXPTInterfaceInfo::Constant(uint16_t aIndex, JS::MutableHandleValue aValue) const
-{
-  if (!mIsShim) {
-    MOZ_ASSERT(aIndex < mNumConsts);
-
-    if (const nsXPTInterfaceInfo* pi = GetParent()) {
-      MOZ_ASSERT(!pi->mIsShim);
-      if (aIndex < pi->mNumConsts) {
-        return pi->Constant(aIndex, aValue);
-      }
-      aIndex -= pi->mNumConsts;
-    }
-
-    // Extract the value and name from the Constant Info.
-    const ConstInfo& info = sConsts[mConsts + aIndex];
-    if (info.mSigned || info.mValue <= (uint32_t)INT32_MAX) {
-      aValue.set(JS::Int32Value((int32_t)info.mValue));
-    } else {
-      aValue.set(JS::DoubleValue(info.mValue));
-    }
-    return GetString(info.mName);
-  }
-
-  // Get a single WebIDL constant.
-  const ConstantSpec* spec;
-  GetWebIDLConst(mConsts, aIndex, &spec, nullptr);
-  aValue.set(spec->value);
-  return spec->name;
+  return xpt::detail::GetConstant(mConsts + aIndex);
 }
 
 const nsXPTMethodInfo&
 nsXPTInterfaceInfo::Method(uint16_t aIndex) const
 {
   MOZ_ASSERT(aIndex < MethodCount());
 
   if (const nsXPTInterfaceInfo* pi = GetParent()) {
@@ -184,20 +114,22 @@ nsXPTInterfaceInfo::GetMethodInfo(uint16
   return *aInfo ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsXPTInterfaceInfo::GetConstant(uint16_t aIndex,
                                 JS::MutableHandleValue aConstant,
                                 char** aName) const
 {
-  *aName = aIndex < ConstantCount()
-    ? moz_xstrdup(Constant(aIndex, aConstant))
-    : nullptr;
-  return *aName ? NS_OK : NS_ERROR_FAILURE;
+  if (aIndex < ConstantCount()) {
+    aConstant.set(Constant(aIndex).JSValue());
+    *aName = moz_xstrdup(Constant(aIndex).Name());
+    return NS_OK;
+  }
+  return NS_ERROR_FAILURE;
 }
 
 nsresult
 nsXPTInterfaceInfo::IsIID(const nsIID* aIID, bool* aIs) const
 {
   *aIs = mIID == *aIID;
   return NS_OK;
 }
--- a/xpcom/reflect/xptinfo/xptinfo.h
+++ b/xpcom/reflect/xptinfo/xptinfo.h
@@ -26,26 +26,28 @@ namespace dom {
 struct NativePropertyHooks;
 } // namespace dom
 } // namespace mozilla
 
 struct nsXPTInterfaceInfo;
 struct nsXPTType;
 struct nsXPTParamInfo;
 struct nsXPTMethodInfo;
+struct nsXPTConstantInfo;
 struct nsXPTDOMObjectInfo;
 
 // Internal helper methods.
 namespace xpt {
 namespace detail {
 
 inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex);
 inline const nsXPTType& GetType(uint16_t aIndex);
 inline const nsXPTParamInfo& GetParam(uint16_t aIndex);
 inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex);
+inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex);
 inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex);
 inline const char* GetString(uint32_t aIndex);
 
 const nsXPTInterfaceInfo* InterfaceByIID(const nsIID& aIID);
 const nsXPTInterfaceInfo* InterfaceByName(const char* aName);
 
 extern const uint16_t sInterfacesSize;
 
@@ -71,44 +73,42 @@ struct nsXPTInterfaceInfo
   static const nsXPTInterfaceInfo* ByIndex(uint16_t aIndex) {
     // NOTE: We add 1 here, as the internal index 0 is reserved for null.
     return xpt::detail::GetInterface(aIndex + 1);
   }
   static uint16_t InterfaceCount() { return xpt::detail::sInterfacesSize; }
 
 
   // Interface flag getters
-  bool IsScriptable() const { return true; } // XXX remove (backcompat)
+  bool IsScriptable() const { return true; } // XXX remove (bug 1480245)
   bool IsFunction() const { return mFunction; }
   bool IsBuiltinClass() const { return mBuiltinClass; }
   bool IsMainProcessScriptableOnly() const { return mMainProcessScriptableOnly; }
 
   const char* Name() const { return xpt::detail::GetString(mName); }
   const nsIID& IID() const { return mIID; }
 
   // Get the parent interface, or null if this interface doesn't have a parent.
   const nsXPTInterfaceInfo* GetParent() const {
     return xpt::detail::GetInterface(mParent);
   }
 
   // Do we have an ancestor interface with the given IID?
   bool HasAncestor(const nsIID& aIID) const;
 
-  // Constant Getters and Setters.
-  uint16_t ConstantCount() const;
-  const char* Constant(uint16_t aIndex, JS::MutableHandleValue aConst) const;
-
-  // Method Getters and Setters.
+  // Get methods & constants
+  uint16_t ConstantCount() const { return mNumConsts; }
+  const nsXPTConstantInfo& Constant(uint16_t aIndex) const;
   uint16_t MethodCount() const { return mNumMethods; }
   const nsXPTMethodInfo& Method(uint16_t aIndex) const;
 
 
-  //////////////////////////////////////////////
-  // nsIInterfaceInfo backwards compatibility //
-  //////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////
+  // nsIInterfaceInfo backwards compatibility (bug 1480245) //
+  ////////////////////////////////////////////////////////////
 
   nsresult GetName(char** aName) const;
   nsresult IsScriptable(bool* aRes) const;
   nsresult IsBuiltinClass(bool* aRes) const;
   nsresult GetParent(const nsXPTInterfaceInfo** aParent) const;
   nsresult GetMethodCount(uint16_t* aMethodCount) const;
   nsresult GetConstantCount(uint16_t* aConstantCount) const;
   nsresult GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo) const;
@@ -117,37 +117,35 @@ struct nsXPTInterfaceInfo
                        char** aName) const;
   nsresult IsIID(const nsIID* aIID, bool* aIs) const;
   nsresult GetNameShared(const char** aName) const;
   nsresult GetIIDShared(const nsIID** aIID) const;
   nsresult IsFunction(bool* aRetval) const;
   nsresult HasAncestor(const nsIID* aIID, bool* aRetval) const;
   nsresult IsMainProcessScriptableOnly(bool* aRetval) const;
 
-  // XXX: We can probably get away with removing this method. A shim interface
-  // _should_ never show up in code which calls EnsureResolved().
-  bool EnsureResolved() const { return !mIsShim; }
+  bool EnsureResolved() const { return true; } // XXX: Remove (bug 1480245)
 
   ////////////////////////////////////////////////////////////////
   // Ensure these fields are in the same order as xptcodegen.py //
   ////////////////////////////////////////////////////////////////
 
   nsID mIID;
   uint32_t mName; // Index into xpt::detail::sStrings
 
   uint16_t mParent : 14;
   uint16_t mBuiltinClass : 1;
   // XXX(nika): Do we need this if we don't have addons anymore?
   uint16_t mMainProcessScriptableOnly : 1;
 
   uint16_t mMethods; // Index into xpt::detail::sMethods
 
   uint16_t mConsts : 14; // Index into xpt::detail::sConsts
-  uint16_t mIsShim : 1; // Is this interface a WebIDL shim?
   uint16_t mFunction : 1;
+  // uint16_t unused : 1;
 
   uint8_t mNumMethods; // NOTE(24/04/18): largest=nsIDocShell (193)
   uint8_t mNumConsts; // NOTE(24/04/18): largest=nsIAccessibleRole (175)
 };
 
 // The fields in nsXPTInterfaceInfo were carefully ordered to minimize size.
 static_assert(sizeof(nsXPTInterfaceInfo) == 28, "wrong size?");
 
@@ -502,16 +500,46 @@ struct nsXPTMethodInfo
   uint8_t mHasRetval : 1;
   // uint8_t unused : 1;
 };
 
 // The fields in nsXPTMethodInfo were carefully ordered to minimize size.
 static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size");
 
 /**
+ * A nsXPTConstantInfo is used to describe a single interface constant.
+ */
+struct nsXPTConstantInfo
+{
+  const char* Name() const {
+    return xpt::detail::GetString(mName);
+  }
+
+  JS::Value JSValue() const {
+    if (mSigned || mValue <= uint32_t(INT32_MAX)) {
+      return JS::Int32Value(int32_t(mValue));
+    }
+    return JS::DoubleValue(mValue);
+  }
+
+  ////////////////////////////////////////////////////////////////
+  // Ensure these fields are in the same order as xptcodegen.py //
+  ////////////////////////////////////////////////////////////////
+
+  uint32_t mName : 31; // Index into xpt::detail::mStrings.
+
+  // Whether the value should be interpreted as a int32_t or uint32_t.
+  uint32_t mSigned: 1;
+  uint32_t mValue; // The value stored as a u32
+};
+
+// The fields in nsXPTConstantInfo were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTConstantInfo) == 8, "wrong size");
+
+/**
  * Object representing the information required to wrap and unwrap DOMObjects.
  *
  * This object will not live in rodata as it contains relocations.
  */
 struct nsXPTDOMObjectInfo
 {
   nsresult Unwrap(JS::HandleValue aHandle, void** aObj) const {
     return mUnwrap(aHandle, aObj);
@@ -561,53 +589,30 @@ public:
   void Clear() {
     if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) {
       nsTArrayFallibleAllocator::Free(mHdr);
     }
     mHdr = EmptyHdr();
   }
 };
 
-/**
- * The compressed representation of constants from XPT. Not part of the public
- * interface, as we also need to support Shim interfaces.
- */
-struct ConstInfo
-{
-  ////////////////////////////////////////////////////////////////
-  // Ensure these fields are in the same order as xptcodegen.py //
-  ////////////////////////////////////////////////////////////////
-
-  uint32_t mName : 31; // Index into xpt::detail::mStrings.
-
-  // Whether the value should be interpreted as a int32_t or uint32_t.
-  uint32_t mSigned: 1;
-  uint32_t mValue; // The value stored as a u32
-};
-
-// The fields in ConstInfo were carefully ordered to minimize size.
-static_assert(sizeof(ConstInfo) == 8, "wrong size");
-
 
 //////////////////////////////////////////////
 // Raw typelib data stored in const statics //
 //////////////////////////////////////////////
 
 // XPIDL information
 extern const nsXPTInterfaceInfo sInterfaces[];
 extern const nsXPTType sTypes[];
 extern const nsXPTParamInfo sParams[];
 extern const nsXPTMethodInfo sMethods[];
+extern const nsXPTConstantInfo sConsts[];
 extern const nsXPTDOMObjectInfo sDOMObjects[];
 
 extern const char sStrings[];
-extern const ConstInfo sConsts[];
-
-// shim constant information
-extern const mozilla::dom::NativePropertyHooks* sPropHooks[];
 
 
 //////////////////////////////////////
 // Helper Methods for fetching data //
 //////////////////////////////////////
 
 inline const nsXPTInterfaceInfo*
 GetInterface(uint16_t aIndex)
@@ -631,16 +636,22 @@ GetParam(uint16_t aIndex)
 }
 
 inline const nsXPTMethodInfo&
 GetMethod(uint16_t aIndex)
 {
   return sMethods[aIndex];
 }
 
+inline const nsXPTConstantInfo&
+GetConstant(uint16_t aIndex)
+{
+  return sConsts[aIndex];
+}
+
 inline const nsXPTDOMObjectInfo&
 GetDOMObjectInfo(uint16_t aIndex)
 {
   return sDOMObjects[aIndex];
 }
 
 inline const char*
 GetString(uint32_t aIndex)