Bug 1415234. Annotate HTMLInputElement::Width() as MOZ_CAN_RUN_SCRIPT and plumb through the binding bits needed to make this pass static analysis. r=mystor
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 13 Nov 2017 10:36:53 -0500
changeset 391507 9ef61399999ef17a696071735db2fbab8c4bf502
parent 391506 d331391aee4d2b41740d0b8615c07ffbb668585b
child 391508 b9aa0fc4f179dbe92419b3b153df170bd1eb697d
push id97288
push userbzbarsky@mozilla.com
push dateMon, 13 Nov 2017 15:49:35 +0000
treeherdermozilla-inbound@01a5361e9460 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1415234
milestone59.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 1415234. Annotate HTMLInputElement::Width() as MOZ_CAN_RUN_SCRIPT and plumb through the binding bits needed to make this pass static analysis. r=mystor This basically marks most of the bindings bits as MOZ_CAN_RUN_SCRIPT. MozReview-Commit-ID: HcQcYhTR9cb
dom/bindings/Codegen.py
dom/html/HTMLInputElement.h
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1544,38 +1544,45 @@ class CGAbstractMethod(CGThing):
     MOZ_ALWAYS_INLINE.
 
     static should be True to generate a static method, which only has
     a definition.
 
     If templateArgs is not None it should be a list of strings containing
     template arguments, and the function will be templatized using those
     arguments.
-    """
-    def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, templateArgs=None):
+
+    canRunScript should be True to generate a MOZ_CAN_RUN_SCRIPT annotation.
+    """
+    def __init__(self, descriptor, name, returnType, args, inline=False,
+                 alwaysInline=False, static=False, templateArgs=None,
+                 canRunScript=False):
         CGThing.__init__(self)
         self.descriptor = descriptor
         self.name = name
         self.returnType = returnType
         self.args = args
         self.inline = inline
         self.alwaysInline = alwaysInline
         self.static = static
         self.templateArgs = templateArgs
+        self.canRunScript = canRunScript
 
     def _argstring(self, declare):
         return ', '.join([a.declare() if declare else a.define() for a in self.args])
 
     def _template(self):
         if self.templateArgs is None:
             return ''
         return 'template <%s>\n' % ', '.join(self.templateArgs)
 
     def _decorators(self):
         decorators = []
+        if self.canRunScript:
+            decorators.append('MOZ_CAN_RUN_SCRIPT');
         if self.alwaysInline:
             decorators.append('MOZ_ALWAYS_INLINE')
         elif self.inline:
             decorators.append('inline')
         if self.static:
             decorators.append('static')
         decorators.append(self.returnType)
         maybeNewline = " " if self.inline else "\n"
@@ -1613,19 +1620,20 @@ class CGAbstractMethod(CGThing):
         assert False  # Override me!
 
 
 class CGAbstractStaticMethod(CGAbstractMethod):
     """
     Abstract base class for codegen of implementation-only (no
     declaration) static methods.
     """
-    def __init__(self, descriptor, name, returnType, args):
+    def __init__(self, descriptor, name, returnType, args, canRunScript=False):
         CGAbstractMethod.__init__(self, descriptor, name, returnType, args,
-                                  inline=False, static=True)
+                                  inline=False, static=True,
+                                  canRunScript=canRunScript)
 
     def declare(self):
         # We only have implementation
         return ""
 
 
 class CGAbstractClassHook(CGAbstractStaticMethod):
     """
@@ -2983,17 +2991,18 @@ class CGJsonifyAttributesMethod(CGAbstra
     """
     Generate the JsonifyAttributes method for an interface descriptor
     """
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('%s*' % descriptor.nativeType, 'self'),
                 Argument('JS::Rooted<JSObject*>&', 'aResult')]
-        CGAbstractMethod.__init__(self, descriptor, 'JsonifyAttributes', 'bool', args)
+        CGAbstractMethod.__init__(self, descriptor, 'JsonifyAttributes',
+                                  'bool', args, canRunScript=True)
 
     def definition_body(self):
         ret = ''
         interface = self.descriptor.interface
         for m in interface.members:
             if m.isAttr() and not m.isStatic() and m.type.isSerializable():
                 ret += fill(
                     """
@@ -8842,17 +8851,18 @@ class CGSpecializedMethod(CGAbstractStat
     """
     def __init__(self, descriptor, method):
         self.method = method
         name = CppKeywords.checkMethodName(IDLToCIdentifier(method.identifier.name))
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('%s*' % descriptor.nativeType, 'self'),
                 Argument('const JSJitMethodCallArgs&', 'args')]
-        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
+        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args,
+                                        canRunScript=True)
 
     def definition_body(self):
         nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
                                                         self.method)
         return CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
                             self.method).define()
 
     @staticmethod
@@ -8865,17 +8875,18 @@ class CGMethodPromiseWrapper(CGAbstractS
     """
     A class for generating a wrapper around another method that will
     convert exceptions to promises.
     """
     def __init__(self, descriptor, methodToWrap):
         self.method = methodToWrap
         name = self.makeName(methodToWrap.name)
         args = list(methodToWrap.args)
-        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
+        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args,
+                                        canRunScript=True)
 
     def definition_body(self):
         return fill(
             """
             // Make sure to save the callee before someone maybe messes
             // with rval().
             JS::Rooted<JSObject*> callee(cx, &args.callee());
             bool ok = ${methodName}(${args});
@@ -9212,17 +9223,23 @@ class CGSpecializedGetter(CGAbstractStat
         self.attr = attr
         name = 'get_' + IDLToCIdentifier(attr.identifier.name)
         args = [
             Argument('JSContext*', 'cx'),
             Argument('JS::Handle<JSObject*>', 'obj'),
             Argument('%s*' % descriptor.nativeType, 'self'),
             Argument('JSJitGetterCallArgs', 'args')
         ]
-        CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
+        # StoreInSlot attributes have their getters called from Wrap().  We
+        # really hope they can't run script, and don't want to annotate Wrap()
+        # methods as doing that anyway, so let's not annotate them as
+        # MOZ_CAN_RUN_SCRIPT.
+        CGAbstractStaticMethod.__init__(
+            self, descriptor, name, "bool", args,
+            canRunScript=not attr.getExtendedAttribute("StoreInSlot"))
 
     def definition_body(self):
         if self.attr.isMaplikeOrSetlikeAttr():
             # If the interface is maplike/setlike, there will be one getter
             # method for the size property of the backing object. Due to having
             # to unpack the backing object from the slot, this requires its own
             # generator.
             return getMaplikeOrSetlikeSizeGetterBody(self.descriptor, self.attr)
@@ -9322,17 +9339,18 @@ class CGGetterPromiseWrapper(CGAbstractS
     """
     A class for generating a wrapper around another getter that will
     convert exceptions to promises.
     """
     def __init__(self, descriptor, getterToWrap):
         self.getter = getterToWrap
         name = self.makeName(getterToWrap.name)
         args = list(getterToWrap.args)
-        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
+        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args,
+                                        canRunScript=True)
 
     def definition_body(self):
         return fill(
             """
             bool ok = ${getterName}(${args});
             if (ok) {
               return true;
             }
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -751,17 +751,17 @@ public:
   double ValueAsNumber() const
   {
     return DoesValueAsNumberApply() ? GetValueAsDecimal().toDouble()
                                     : UnspecifiedNaN<double>();
   }
 
   void SetValueAsNumber(double aValue, ErrorResult& aRv);
 
-  uint32_t Width();
+  MOZ_CAN_RUN_SCRIPT uint32_t Width();
 
   void SetWidth(uint32_t aValue, ErrorResult& aRv)
   {
     SetUnsignedIntAttr(nsGkAtoms::width, aValue, 0, aRv);
   }
 
   void StepUp(int32_t aN, ErrorResult& aRv)
   {