aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-08-24 12:47:53 -0500
committerGitHub <noreply@github.com>2016-08-24 12:47:53 -0500
commit1370fa5e3b38f3000c0b1439177cc7b7b81d380e (patch)
tree6237566538677cdcf5e07e8a6b0c9a72c298867c /components/script/dom/bindings/codegen
parent77af4e26cee2f9c02c1da9085d243aad32c667c6 (diff)
parent86a0c45f87f28ef44f996e943aaab1e6c0206443 (diff)
downloadservo-1370fa5e3b38f3000c0b1439177cc7b7b81d380e.tar.gz
servo-1370fa5e3b38f3000c0b1439177cc7b7b81d380e.zip
Auto merge of #12819 - jdm:iterable2, r=nox
Support pair and value iterable WebIDL bindings The actual iterator implementation and JSAPI calls related to setting up the interface are ported directly from Gecko's Codegen.py, IterableIterator.h, and IterableIterator.webidl. The changes to support multiple interfaces in one file are required because the internal iterator interface the parser generates gets associated with the original interface's WebIDL file. It seemed like a good time to address #571 in that case. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #12628 and fix #571. - [X] There are tests for these changes <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12819) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/bindings/codegen')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py520
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py40
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py4
-rw-r--r--components/script/dom/bindings/codegen/parser/callback-location.patch22
-rwxr-xr-xcomponents/script/dom/bindings/codegen/parser/update.sh1
5 files changed, 440 insertions, 147 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 7e80e6c9969..f155362415d 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -21,6 +21,7 @@ from WebIDL import (
IDLType,
IDLInterfaceMember,
IDLUndefinedValue,
+ IDLWrapperType,
)
from Configuration import (
@@ -29,6 +30,7 @@ from Configuration import (
getTypesFromCallback,
getTypesFromDescriptor,
getTypesFromDictionary,
+ iteratorNativeType
)
AUTOGENERATED_WARNING_COMMENT = \
@@ -719,7 +721,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
raise TypeError("Can't handle array arguments yet")
if type.isSequence():
- innerInfo = getJSToNativeConversionInfo(innerSequenceType(type), descriptorProvider)
+ innerInfo = getJSToNativeConversionInfo(innerSequenceType(type),
+ descriptorProvider,
+ isMember=isMember)
declType = CGWrapper(innerInfo.declType, pre="Vec<", post=">")
config = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs)
@@ -942,7 +946,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull()
callback = type.unroll().callback
- declType = CGGeneric('%s::%s' % (getModuleFromObject(callback), callback.identifier.name))
+ declType = CGGeneric(callback.identifier.name)
finalDeclType = CGTemplatedType("Rc", declType)
conversion = CGCallbackTempRoot(declType.define())
@@ -1518,6 +1522,46 @@ class MethodDefiner(PropertyDefiner):
"length": 0,
"condition": "Condition::Satisfied"})
+ # Generate the keys/values/entries aliases for value iterables.
+ maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
+ if (not static and not unforgeable and
+ (maplikeOrSetlikeOrIterable and
+ maplikeOrSetlikeOrIterable.isIterable() and
+ maplikeOrSetlikeOrIterable.isValueIterator())):
+ # Add our keys/values/entries/forEach
+ self.regular.append({
+ "name": "keys",
+ "methodInfo": False,
+ "selfHostedName": "ArrayKeys",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "values",
+ "methodInfo": False,
+ "selfHostedName": "ArrayValues",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "entries",
+ "methodInfo": False,
+ "selfHostedName": "ArrayEntries",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+ self.regular.append({
+ "name": "forEach",
+ "methodInfo": False,
+ "selfHostedName": "ArrayForEach",
+ "length": 0,
+ "condition": PropertyDefiner.getControllingCondition(m,
+ descriptor)
+ })
+
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
if not static and unforgeable == isUnforgeableInterface:
stringifier = descriptor.operations['Stringifier']
@@ -1738,7 +1782,7 @@ class CGImports(CGWrapper):
"""
Generates the appropriate import/use statements.
"""
- def __init__(self, child, descriptors, callbacks, imports, config, ignored_warnings=None):
+ def __init__(self, child, descriptors, callbacks, dictionaries, enums, imports, config, ignored_warnings=None):
"""
Adds a set of imports.
"""
@@ -1752,17 +1796,19 @@ class CGImports(CGWrapper):
]
def componentTypes(type):
- if type.nullable():
+ if type.isType() and type.nullable():
type = type.unroll()
if type.isUnion():
return type.flatMemberTypes
+ if type.isDictionary():
+ return [type] + getTypesFromDictionary(type)
return [type]
def isImportable(type):
if not type.isType():
- assert type.isInterface()
- return not type.isCallback()
- return type.isNonCallbackInterface() and not type.builtin
+ assert type.isInterface() or type.isDictionary() or type.isEnum()
+ return True
+ return not (type.builtin or type.isSequence() or type.isUnion())
def relatedTypesForSignatures(method):
types = []
@@ -1774,13 +1820,30 @@ class CGImports(CGWrapper):
def getIdentifier(t):
if t.isType():
- return t.inner.identifier
- assert t.isInterface()
+ if t.nullable():
+ t = t.inner
+ if t.isCallback():
+ return t.callback.identifier
+ return t.identifier
+ assert t.isInterface() or t.isDictionary() or t.isEnum()
return t.identifier
+ def removeWrapperAndNullableTypes(types):
+ normalized = []
+ for t in types:
+ while (t.isType() and t.nullable()) or isinstance(t, IDLWrapperType):
+ t = t.inner
+ if isImportable(t):
+ normalized += [t]
+ return normalized
+
types = []
for d in descriptors:
- types += [d.interface]
+ if not d.interface.isCallback():
+ types += [d.interface]
+
+ if d.interface.isIteratorInterface():
+ types += [d.interface.iterableInterface]
members = d.interface.members + d.interface.namedConstructors
constructor = d.interface.ctor()
@@ -1796,19 +1859,39 @@ class CGImports(CGWrapper):
elif m.isAttr():
types += componentTypes(m.type)
+ # Import the type names used in the callbacks that are being defined.
for c in callbacks:
types += relatedTypesForSignatures(c)
+ # Import the type names used in the dictionaries that are being defined.
+ for d in dictionaries:
+ types += componentTypes(d)
+
+ # Normalize the types we've collected and remove any ones which can't be imported.
+ types = removeWrapperAndNullableTypes(types)
+
descriptorProvider = config.getDescriptorProvider()
+ extras = []
for t in types:
- if isImportable(t):
+ # Importing these types in the same module that defines them is an error.
+ if t in dictionaries or t in enums:
+ continue
+ if t.isInterface():
descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
- imports += ['%s' % descriptor.path]
+ extras += [descriptor.path]
+ if descriptor.interface.parent:
+ parentName = getIdentifier(descriptor.interface.parent).name
+ descriptor = descriptorProvider.getDescriptor(parentName)
+ extras += [descriptor.path, descriptor.bindingPath]
+ else:
+ if t.isEnum():
+ extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values']
+ extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name]
statements = []
if len(ignored_warnings) > 0:
statements.append('#![allow(%s)]' % ','.join(ignored_warnings))
- statements.extend('use %s;' % i for i in sorted(set(imports)))
+ statements.extend('use %s;' % i for i in sorted(set(imports + extras)))
CGWrapper.__init__(self, child,
pre='\n'.join(statements) + '\n\n')
@@ -1868,7 +1951,7 @@ def DOMClass(descriptor):
# padding.
protoList.extend(['PrototypeList::ID::Last'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
- heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.interface.identifier.name
+ heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.concreteType
if descriptor.isGlobal():
globals_ = camel_to_upper_snake(descriptor.name)
else:
@@ -2111,7 +2194,14 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
# Sort unionStructs by key, retrieve value
unionStructs = (i[1] for i in sorted(unionStructs.items(), key=operator.itemgetter(0)))
- return CGImports(CGList(unionStructs, "\n\n"), [], [], imports, config, ignored_warnings=[])
+ return CGImports(CGList(unionStructs, "\n\n"),
+ descriptors=[],
+ callbacks=[],
+ dictionaries=[],
+ enums=[],
+ imports=imports,
+ config=config,
+ ignored_warnings=[])
class Argument():
@@ -2442,7 +2532,7 @@ class CGIDLInterface(CGThing):
def define(self):
interface = self.descriptor.interface
- name = self.descriptor.name
+ name = self.descriptor.concreteType
if (interface.getUserData("hasConcreteDescendant", False) or
interface.getUserData("hasProxyDescendant", False)):
depth = self.descriptor.prototypeDepth
@@ -2549,6 +2639,8 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
if len(self.descriptor.prototypeChain) == 1:
if self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
getPrototypeProto = "prototype_proto.set(JS_GetErrorPrototype(cx))"
+ elif self.descriptor.interface.isIteratorInterface():
+ getPrototypeProto = "prototype_proto.set(JS_GetIteratorPrototype(cx))"
else:
getPrototypeProto = "prototype_proto.set(JS_GetObjectPrototype(cx, global))"
else:
@@ -2628,6 +2720,55 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
interface.get());
""" % properties))
+ aliasedMembers = [m for m in self.descriptor.interface.members if m.isMethod() and m.aliases]
+ if aliasedMembers:
+ def defineAlias(alias):
+ if alias == "@@iterator":
+ symbolJSID = "RUST_SYMBOL_TO_JSID(GetWellKnownSymbol(cx, SymbolCode::iterator))"
+ getSymbolJSID = CGGeneric(fill("rooted!(in(cx) let iteratorId = ${symbolJSID});",
+ symbolJSID=symbolJSID))
+ defineFn = "JS_DefinePropertyById2"
+ prop = "iteratorId.handle()"
+ elif alias.startswith("@@"):
+ raise TypeError("Can't handle any well-known Symbol other than @@iterator")
+ else:
+ getSymbolJSID = None
+ defineFn = "JS_DefineProperty"
+ prop = '"%s"' % alias
+ return CGList([
+ getSymbolJSID,
+ # XXX If we ever create non-enumerable properties that can
+ # be aliased, we should consider making the aliases
+ # match the enumerability of the property being aliased.
+ CGGeneric(fill(
+ """
+ assert!(${defineFn}(cx, prototype.handle(), ${prop}, aliasedVal.handle(),
+ JSPROP_ENUMERATE, None, None));
+ """,
+ defineFn=defineFn,
+ prop=prop))
+ ], "\n")
+
+ def defineAliasesFor(m):
+ return CGList([
+ CGGeneric(fill(
+ """
+ assert!(JS_GetProperty(cx, prototype.handle(),
+ b\"${prop}\0\" as *const u8 as *const _,
+ aliasedVal.handle_mut()));
+ """,
+ prop=m.identifier.name))
+ ] + [defineAlias(alias) for alias in sorted(m.aliases)])
+
+ defineAliases = CGList([
+ CGGeneric(fill("""
+ // Set up aliases on the interface prototype object we just created.
+
+ """)),
+ CGGeneric("rooted!(in(cx) let mut aliasedVal = UndefinedValue());\n\n")
+ ] + [defineAliasesFor(m) for m in sorted(aliasedMembers)])
+ code.append(defineAliases)
+
constructors = self.descriptor.interface.namedConstructors
if constructors:
decl = "let named_constructors: [(NonNullJSNative, &'static [u8], u32); %d]" % len(constructors)
@@ -2709,7 +2850,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
"""
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
- "PrototypeList::ID", pub=descriptor.hasDescendants())
+ "PrototypeList::ID", pub=True)
def definition_body(self):
return CGList([
@@ -2727,7 +2868,7 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject",
"PrototypeList::Constructor",
- pub=descriptor.hasDescendants())
+ pub=True)
def definition_body(self):
return CGList([
@@ -2966,11 +3107,21 @@ class CGPerSignatureCall(CGThing):
if self.isFallible():
errorResult = " false"
- cgThings.append(CGCallGenerator(
- errorResult,
- self.getArguments(), self.argsPre, returnType,
- self.extendedAttributes, descriptor, nativeMethodName,
- static))
+ if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeOrIterableMethod():
+ if idlNode.maplikeOrSetlikeOrIterable.isMaplike() or \
+ idlNode.maplikeOrSetlikeOrIterable.isSetlike():
+ raise TypeError('Maplike/Setlike methods are not supported yet')
+ else:
+ cgThings.append(CGIterableMethodGenerator(descriptor,
+ idlNode.maplikeOrSetlikeOrIterable,
+ idlNode.identifier.name))
+ else:
+ cgThings.append(CGCallGenerator(
+ errorResult,
+ self.getArguments(), self.argsPre, returnType,
+ self.extendedAttributes, descriptor, nativeMethodName,
+ static))
+
self.cgRoot = CGList(cgThings, "\n")
def getArgs(self):
@@ -5008,6 +5159,7 @@ class CGInterfaceTrait(CGThing):
def members():
for m in descriptor.interface.members:
if (m.isMethod() and not m.isStatic() and
+ not m.isMaplikeOrSetlikeOrIterableMethod() and
(not m.isIdentifierLess() or m.isStringifier())):
name = CGSpecializedMethod.makeNativeName(descriptor, m)
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
@@ -5068,6 +5220,7 @@ class CGInterfaceTrait(CGThing):
post="}")
else:
self.cgRoot = CGGeneric("")
+ self.empty = not methods
def define(self):
return self.cgRoot.define()
@@ -5083,18 +5236,136 @@ class CGWeakReferenceableTrait(CGThing):
return self.code
+def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries=None, enums=None):
+ if not callbacks:
+ callbacks = []
+ if not dictionaries:
+ dictionaries = []
+ if not enums:
+ enums = []
+
+ return CGImports(cgthings, descriptors, callbacks, dictionaries, enums, [
+ 'js',
+ 'js::{JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT}',
+ 'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}',
+ 'js::error::throw_type_error',
+ 'js::jsapi::{JSJitInfo_AliasSet, JSJitInfo_ArgType, AutoIdVector, CallArgs, FreeOp}',
+ 'js::jsapi::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_SHARED}',
+ 'js::jsapi::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}',
+ 'js::jsapi::{GetPropertyKeys, Handle, Call, GetWellKnownSymbol}',
+ 'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
+ 'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
+ 'js::jsapi::{JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
+ 'js::jsapi::{JS_GetClass, JS_GetErrorPrototype, JS_GetFunctionPrototype}',
+ 'js::jsapi::{JS_GetGlobalForObject, JS_GetObjectPrototype, JS_GetProperty}',
+ 'js::jsapi::{JS_GetPropertyById, JS_GetPropertyDescriptorById, JS_GetReservedSlot}',
+ 'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
+ 'js::jsapi::{JS_AtomizeAndPinString, JS_NewObject, JS_NewObjectWithGivenProto}',
+ 'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty, JS_DefinePropertyById2}',
+ 'js::jsapi::{JS_SplicePrototype, JS_SetReservedSlot, JSAutoCompartment}',
+ 'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec, JS_GetIteratorPrototype}',
+ 'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
+ 'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertySpec}',
+ 'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
+ 'js::jsapi::{ObjectOpResult, JSJitInfo_OpType, MutableHandle, MutableHandleObject}',
+ 'js::jsapi::{MutableHandleValue, PropertyDescriptor, RootedObject}',
+ 'js::jsapi::{SymbolCode, jsid}',
+ 'js::jsval::JSVal',
+ 'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
+ 'js::jsval::{NullValue, UndefinedValue}',
+ 'js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, CreateProxyHandler}',
+ 'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}',
+ 'js::glue::{RUST_JSID_IS_STRING, int_to_jsid, RUST_SYMBOL_TO_JSID}',
+ 'js::glue::AppendToAutoIdVector',
+ 'js::rust::{GCMethods, define_methods, define_properties}',
+ 'dom',
+ 'dom::bindings',
+ 'dom::bindings::codegen::InterfaceObjectMap',
+ 'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
+ 'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
+ 'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
+ 'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
+ 'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
+ 'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
+ 'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
+ 'dom::bindings::interface::is_exposed_in',
+ 'dom::bindings::iterable::{IteratorType, Iterable}',
+ 'dom::bindings::js::{JS, Root, RootedReference}',
+ 'dom::bindings::js::{OptionalRootedReference}',
+ 'dom::bindings::reflector::{Reflectable}',
+ 'dom::bindings::utils::{DOMClass, DOMJSClass}',
+ 'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
+ 'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
+ 'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
+ 'dom::bindings::utils::{generic_getter, generic_lenient_getter, generic_lenient_setter}',
+ 'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
+ 'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
+ 'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
+ 'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
+ 'dom::bindings::trace::{JSTraceable, RootedTraceable}',
+ 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
+ 'dom::bindings::callback::{CallSetup,ExceptionHandling}',
+ 'dom::bindings::callback::wrap_call_this_object',
+ 'dom::bindings::conversions::{ConversionBehavior, ConversionResult, DOM_OBJECT_SLOT}',
+ 'dom::bindings::conversions::{IDLInterface, is_array_like}',
+ 'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
+ 'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
+ 'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
+ 'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
+ 'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
+ 'dom::bindings::error::{Fallible, Error, ErrorResult}',
+ 'dom::bindings::error::Error::JSFailed',
+ 'dom::bindings::error::throw_dom_exception',
+ 'dom::bindings::guard::{Condition, Guard}',
+ 'dom::bindings::proxyhandler',
+ 'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
+ 'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
+ 'dom::bindings::num::Finite',
+ 'dom::bindings::str::{ByteString, DOMString, USVString}',
+ 'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
+ 'dom::browsingcontext::BrowsingContext',
+ 'mem::heap_size_of_raw_self_and_children',
+ 'libc',
+ 'util::prefs::PREFS',
+ 'script_runtime::{store_panic_result, maybe_take_panic_result}',
+ 'std::borrow::ToOwned',
+ 'std::cmp',
+ 'std::mem',
+ 'std::num',
+ 'std::os',
+ 'std::panic::{self, AssertUnwindSafe}',
+ 'std::ptr',
+ 'std::str',
+ 'std::rc',
+ 'std::rc::Rc',
+ 'std::default::Default',
+ 'std::ffi::CString',
+ ], config)
+
+
class CGDescriptor(CGThing):
- def __init__(self, descriptor):
+ def __init__(self, descriptor, config, soleDescriptor):
CGThing.__init__(self)
assert not descriptor.concrete or not descriptor.interface.isCallback()
+ reexports = []
+
+ def reexportedName(name):
+ if name.startswith(descriptor.name):
+ return name
+ if not soleDescriptor:
+ return '%s as %s%s' % (name, descriptor.name, name)
+ return name
+
cgThings = []
if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor))
+ reexports.append('GetProtoObject')
if (descriptor.interface.hasInterfaceObject() and
descriptor.shouldHaveGetConstructorObjectMethod()):
cgThings.append(CGGetConstructorObjectMethod(descriptor))
+ reexports.append('GetConstructorObject')
unscopableNames = []
for m in descriptor.interface.members:
@@ -5156,9 +5427,11 @@ class CGDescriptor(CGThing):
cgThings.append(CGNamespace.build([descriptor.name + "Constants"],
CGConstant(constMembers),
public=True))
+ reexports.append(descriptor.name + 'Constants')
- if descriptor.interface.hasInterfaceObject():
+ if descriptor.interface.hasInterfaceObject() and descriptor.register:
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
+ reexports.append('DefineDOMInterface')
cgThings.append(CGConstructorEnabled(descriptor))
if descriptor.proxy:
@@ -5194,6 +5467,7 @@ class CGDescriptor(CGThing):
pass
cgThings.append(CGWrapMethod(descriptor))
+ reexports.append('Wrap')
haveUnscopables = False
if not descriptor.interface.isCallback():
@@ -5206,7 +5480,12 @@ class CGDescriptor(CGThing):
CGGeneric("];\n")], "\n"))
if descriptor.concrete or descriptor.hasDescendants():
cgThings.append(CGIDLInterface(descriptor))
- cgThings.append(CGInterfaceTrait(descriptor))
+
+ interfaceTrait = CGInterfaceTrait(descriptor)
+ cgThings.append(interfaceTrait)
+ if not interfaceTrait.empty:
+ reexports.append('%sMethods' % descriptor.name)
+
if descriptor.weakReferenceable:
cgThings.append(CGWeakReferenceableTrait(descriptor))
@@ -5214,11 +5493,13 @@ class CGDescriptor(CGThing):
cgThings.append(CGGeneric(str(properties)))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables))
- cgThings = CGList(cgThings, "\n")
- # self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
- # cgThings),
- # post='\n')
- self.cgRoot = cgThings
+ cgThings = generate_imports(config, CGList(cgThings, '\n'), [descriptor])
+ cgThings = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
+ cgThings, public=True),
+ post='\n')
+ reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
+ self.cgRoot = CGList([CGGeneric('pub use self::%sBinding::{%s};' % (descriptor.name, reexports)),
+ cgThings], '\n')
def define(self):
return self.cgRoot.define()
@@ -5468,8 +5749,8 @@ class CGRegisterProxyHandlersMethod(CGAbstractMethod):
def definition_body(self):
return CGList([
- CGGeneric("proxy_handlers[Proxies::%s as usize] = codegen::Bindings::%sBinding::DefineProxyHandler();"
- % (desc.name, desc.name))
+ CGGeneric("proxy_handlers[Proxies::%s as usize] = Bindings::%s::DefineProxyHandler();"
+ % (desc.name, '::'.join([desc.name + 'Binding'] * 2)))
for desc in self.descriptors
], "\n")
@@ -5542,7 +5823,7 @@ class CGBindingRoot(CGThing):
for c in mainCallbacks)
# Do codegen for all the descriptors
- cgthings.extend([CGDescriptor(x) for x in descriptors])
+ cgthings.extend([CGDescriptor(x, config, len(descriptors) == 1) for x in descriptors])
# Do codegen for all the callback interfaces.
cgthings.extend(CGList([CGCallbackInterface(x),
@@ -5553,102 +5834,8 @@ class CGBindingRoot(CGThing):
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
# Add imports
- curr = CGImports(curr, descriptors + callbackDescriptors, mainCallbacks, [
- 'js',
- 'js::{JS_CALLEE, JSCLASS_GLOBAL_SLOT_COUNT}',
- 'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}',
- 'js::error::throw_type_error',
- 'js::jsapi::{JSJitInfo_AliasSet, JSJitInfo_ArgType, AutoIdVector, CallArgs, FreeOp}',
- 'js::jsapi::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_SHARED}',
- 'js::jsapi::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}',
- 'js::jsapi::{GetPropertyKeys, Handle}',
- 'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}',
- 'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}',
- 'js::jsapi::{JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}',
- 'js::jsapi::{JS_GetClass, JS_GetErrorPrototype, JS_GetFunctionPrototype}',
- 'js::jsapi::{JS_GetGlobalForObject, JS_GetObjectPrototype, JS_GetProperty}',
- 'js::jsapi::{JS_GetPropertyById, JS_GetPropertyDescriptorById, JS_GetReservedSlot}',
- 'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_InitializePropertiesFromCompatibleNativeObject}',
- 'js::jsapi::{JS_AtomizeAndPinString, JS_NewObject, JS_NewObjectWithGivenProto}',
- 'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty}',
- 'js::jsapi::{JS_SplicePrototype, JS_SetReservedSlot, JSAutoCompartment}',
- 'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec}',
- 'js::jsapi::{JSJitGetterCallArgs, JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs}',
- 'js::jsapi::{JSNative, JSObject, JSNativeWrapper, JSPropertySpec}',
- 'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}',
- 'js::jsapi::{ObjectOpResult, JSJitInfo_OpType, MutableHandle, MutableHandleObject}',
- 'js::jsapi::{MutableHandleValue, PropertyDescriptor, RootedObject}',
- 'js::jsapi::{SymbolCode, jsid}',
- 'js::jsval::JSVal',
- 'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
- 'js::jsval::{NullValue, UndefinedValue}',
- 'js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, CreateProxyHandler}',
- 'js::glue::{GetProxyPrivate, NewProxyObject, ProxyTraps}',
- 'js::glue::{RUST_JSID_IS_STRING, int_to_jsid}',
- 'js::glue::AppendToAutoIdVector',
- 'js::rust::{GCMethods, define_methods, define_properties}',
- 'dom::bindings',
- 'dom::bindings::codegen::InterfaceObjectMap',
- 'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
- 'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
- 'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
- 'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
- 'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
- 'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
- 'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
- 'dom::bindings::interface::is_exposed_in',
- 'dom::bindings::js::{JS, Root, RootedReference}',
- 'dom::bindings::js::{OptionalRootedReference}',
- 'dom::bindings::reflector::{Reflectable}',
- 'dom::bindings::utils::{DOMClass, DOMJSClass}',
- 'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
- 'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
- 'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
- 'dom::bindings::utils::{generic_getter, generic_lenient_getter, generic_lenient_setter}',
- 'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
- 'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
- 'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
- 'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
- 'dom::bindings::trace::{JSTraceable, RootedTraceable}',
- 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
- 'dom::bindings::callback::{CallSetup,ExceptionHandling}',
- 'dom::bindings::callback::wrap_call_this_object',
- 'dom::bindings::conversions::{ConversionBehavior, ConversionResult, DOM_OBJECT_SLOT}',
- 'dom::bindings::conversions::{IDLInterface, is_array_like}',
- 'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
- 'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
- 'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
- 'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
- 'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
- 'dom::bindings::codegen::Bindings::*',
- 'dom::bindings::error::{Fallible, Error, ErrorResult}',
- 'dom::bindings::error::Error::JSFailed',
- 'dom::bindings::error::throw_dom_exception',
- 'dom::bindings::guard::{Condition, Guard}',
- 'dom::bindings::proxyhandler',
- 'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
- 'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
- 'dom::bindings::num::Finite',
- 'dom::bindings::str::{ByteString, DOMString, USVString}',
- 'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
- 'dom::browsingcontext::BrowsingContext',
- 'mem::heap_size_of_raw_self_and_children',
- 'libc',
- 'util::prefs::PREFS',
- 'script_runtime::{store_panic_result, maybe_take_panic_result}',
- 'std::borrow::ToOwned',
- 'std::cmp',
- 'std::mem',
- 'std::num',
- 'std::os',
- 'std::panic::{self, AssertUnwindSafe}',
- 'std::ptr',
- 'std::str',
- 'std::rc',
- 'std::rc::Rc',
- 'std::default::Default',
- 'std::ffi::CString',
- ], config)
+ curr = generate_imports(config, curr, callbackDescriptors, mainCallbacks,
+ dictionaries, enums)
# Add the auto-generated comment.
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
@@ -6250,6 +6437,53 @@ class CallbackSetter(CallbackMember):
return None
+class CGIterableMethodGenerator(CGGeneric):
+ """
+ Creates methods for iterable interfaces. Unwrapping/wrapping
+ will be taken care of by the usual method generation machinery in
+ CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of
+ using CGCallGenerator.
+ """
+ def __init__(self, descriptor, iterable, methodName):
+ if methodName == "forEach":
+ CGGeneric.__init__(self, fill(
+ """
+ if !IsCallable(arg0) {
+ throw_type_error(cx, "Argument 1 of ${ifaceName}.forEach is not callable.");
+ return false;
+ }
+ rooted!(in(cx) let arg0 = ObjectValue(&*arg0));
+ rooted!(in(cx) let mut call_arg1 = UndefinedValue());
+ rooted!(in(cx) let mut call_arg2 = UndefinedValue());
+ let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(&**_obj)];
+ rooted!(in(cx) let mut ignoredReturnVal = UndefinedValue());
+ for i in 0..(*this).get_iterable_length() {
+ (*this).get_value_at_index(i).to_jsval(cx, call_arg1.handle_mut());
+ (*this).get_key_at_index(i).to_jsval(cx, call_arg2.handle_mut());
+ call_args[0] = call_arg1.handle().get();
+ call_args[1] = call_arg2.handle().get();
+ let call_args = HandleValueArray { length_: 3, elements_: call_args.as_ptr() };
+ if !Call(cx, arg1, arg0.handle(), &call_args,
+ ignoredReturnVal.handle_mut()) {
+ return false;
+ }
+ }
+
+ let result = ();
+ """,
+ ifaceName=descriptor.interface.identifier.name))
+ return
+ CGGeneric.__init__(self, fill(
+ """
+ let result = ${iterClass}::new(&*this,
+ IteratorType::${itrMethod},
+ super::${ifaceName}IteratorBinding::Wrap);
+ """,
+ iterClass=iteratorNativeType(descriptor, True),
+ ifaceName=descriptor.interface.identifier.name,
+ itrMethod=methodName.title()))
+
+
def camel_to_upper_snake(s):
return "_".join(m.group(0).upper() for m in re.finditer("[A-Z][a-z]*", s))
@@ -6286,12 +6520,12 @@ class GlobalGenRoots():
pairs = []
for d in config.getDescriptors(hasInterfaceObject=True):
binding = toBindingNamespace(d.name)
- pairs.append((d.name, binding))
+ pairs.append((d.name, binding, binding))
for ctor in d.interface.namedConstructors:
- pairs.append((ctor.identifier.name, binding))
+ pairs.append((ctor.identifier.name, binding, binding))
pairs.sort(key=operator.itemgetter(0))
mappings = [
- CGGeneric('b"%s" => codegen::Bindings::%s::DefineDOMInterface as unsafe fn(_, _),' % pair)
+ CGGeneric('b"%s" => codegen::Bindings::%s::%s::DefineDOMInterface as unsafe fn(_, _),' % pair)
for pair in pairs
]
mapType = "phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)>"
@@ -6340,15 +6574,17 @@ class GlobalGenRoots():
CGRegisterProxyHandlers(config),
], "\n")
- return CGImports(code, [], [], [
- 'dom::bindings::codegen',
+ return CGImports(code, descriptors=[], callbacks=[], dictionaries=[], enums=[], imports=[
+ 'dom::bindings::codegen::Bindings',
'dom::bindings::codegen::PrototypeList::Proxies',
'libc',
- ], config, ignored_warnings=[])
+ ], config=config, ignored_warnings=[])
@staticmethod
def InterfaceTypes(config):
- descriptors = [d.name for d in config.getDescriptors(register=True, isCallback=False)]
+ descriptors = [d.name for d in config.getDescriptors(register=True,
+ isCallback=False,
+ isIteratorInterface=False)]
curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@@ -6356,9 +6592,13 @@ class GlobalGenRoots():
@staticmethod
def Bindings(config):
- descriptors = (set(d.name + "Binding" for d in config.getDescriptors(register=True)) |
- set(getModuleFromObject(d) for d in config.callbacks) |
- set(getModuleFromObject(d) for d in config.getDictionaries()))
+ def leafModule(d):
+ return getModuleFromObject(d).split('::')[-1]
+
+ descriptors = config.getDescriptors(register=True, isIteratorInterface=False)
+ descriptors = (set(d.name + "Binding" for d in descriptors) |
+ set(leafModule(d) for d in config.callbacks) |
+ set(leafModule(d) for d in config.getDictionaries()))
curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 4074736a462..c8f92472618 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -4,7 +4,7 @@
import os
-from WebIDL import IDLExternalInterface, IDLInterface, WebIDLError
+from WebIDL import IDLExternalInterface, IDLInterface, IDLWrapperType, WebIDLError
class Configuration:
@@ -89,6 +89,8 @@ class Configuration:
getter = lambda x: x.isGlobal()
elif key == 'isExposedConditionally':
getter = lambda x: x.interface.isExposedConditionally()
+ elif key == 'isIteratorInterface':
+ getter = lambda x: x.interface.isIteratorInterface()
else:
getter = lambda x: getattr(x, key)
curr = filter(lambda x: getter(x) == val, curr)
@@ -177,13 +179,26 @@ class Descriptor(DescriptorProvider):
# Read the desc, and fill in the relevant defaults.
ifaceName = self.interface.identifier.name
- typeName = desc.get('nativeType', ifaceName)
+ nativeTypeDefault = ifaceName
+
+ # For generated iterator interfaces for other iterable interfaces, we
+ # just use IterableIterator as the native type, templated on the
+ # nativeType of the iterable interface. That way we can have a
+ # templated implementation for all the duplicated iterator
+ # functionality.
+ if self.interface.isIteratorInterface():
+ itrName = self.interface.iterableInterface.identifier.name
+ itrDesc = self.getDescriptor(itrName)
+ nativeTypeDefault = iteratorNativeType(itrDesc)
+
+ typeName = desc.get('nativeType', nativeTypeDefault)
# Callback types do not use JS smart pointers, so we should not use the
# built-in rooting mechanisms for them.
if self.interface.isCallback():
self.needsRooting = False
- ty = "%sBinding::%s" % (ifaceName, ifaceName)
+ ty = 'dom::bindings::codegen::Bindings::%sBinding::%s' % (ifaceName, ifaceName)
+ pathDefault = ty
self.returnType = "Rc<%s>" % ty
self.argumentType = "???"
self.nativeType = ty
@@ -192,10 +207,15 @@ class Descriptor(DescriptorProvider):
self.returnType = "Root<%s>" % typeName
self.argumentType = "&%s" % typeName
self.nativeType = "*const %s" % typeName
+ if self.interface.isIteratorInterface():
+ pathDefault = 'dom::bindings::iterable::IterableIterator'
+ else:
+ pathDefault = 'dom::types::%s' % typeName
self.concreteType = typeName
self.register = desc.get('register', True)
- self.path = desc.get('path', 'dom::types::%s' % typeName)
+ self.path = desc.get('path', pathDefault)
+ self.bindingPath = 'dom::bindings::codegen::Bindings::%s' % ('::'.join([ifaceName + 'Binding'] * 2))
self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False
self.weakReferenceable = desc.get('weakReferenceable', False)
@@ -377,7 +397,8 @@ class Descriptor(DescriptorProvider):
# Some utility methods
def getModuleFromObject(object):
- return os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding'
+ return ('dom::bindings::codegen::Bindings::' +
+ os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding')
def getTypesFromDescriptor(descriptor):
@@ -404,6 +425,8 @@ def getTypesFromDictionary(dictionary):
"""
Get all member types for this dictionary
"""
+ if isinstance(dictionary, IDLWrapperType):
+ dictionary = dictionary.inner
types = []
curDict = dictionary
while curDict:
@@ -421,3 +444,10 @@ def getTypesFromCallback(callback):
types = [sig[0]] # Return type
types.extend(arg.type for arg in sig[1]) # Arguments
return types
+
+
+def iteratorNativeType(descriptor, infer=False):
+ assert descriptor.interface.isIterable()
+ iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
+ assert iterableDecl.isPairIterator()
+ return "IterableIterator%s" % ("" if infer else '<%s>' % descriptor.interface.identifier.name)
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index 54d510781a1..f3195050908 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope)
@@ -6534,7 +6534,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
- type = IDLCallbackType(self.getLocation(p, 1), obj)
+ type = IDLCallbackType(obj.location, obj)
else:
type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2])
diff --git a/components/script/dom/bindings/codegen/parser/callback-location.patch b/components/script/dom/bindings/codegen/parser/callback-location.patch
new file mode 100644
index 00000000000..ab6b0ae9b9b
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/callback-location.patch
@@ -0,0 +1,22 @@
+diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
+index da32340..81c52b7 100644
+--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
++++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
+@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
+ return typedefType.complete(scope)
+ elif obj.isCallback() and not obj.isInterface():
+ assert self.name.name == obj.identifier.name
+- return IDLCallbackType(self.location, obj)
++ return IDLCallbackType(obj.location, obj)
+
+ if self._promiseInnerType and not self._promiseInnerType.isComplete():
+ self._promiseInnerType = self._promiseInnerType.complete(scope)
+@@ -6521,7 +6521,7 @@ class Parser(Tokenizer):
+ type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
+ obj.identifier.name)
+ elif obj.isCallback() and not obj.isInterface():
+- type = IDLCallbackType(self.getLocation(p, 1), obj)
++ type = IDLCallbackType(obj.location, obj)
+ else:
+ type = IDLWrapperType(self.getLocation(p, 1), p[1])
+ p[0] = self.handleModifiers(type, p[2]) \ No newline at end of file
diff --git a/components/script/dom/bindings/codegen/parser/update.sh b/components/script/dom/bindings/codegen/parser/update.sh
index 76a99d9cecb..25aeefc5830 100755
--- a/components/script/dom/bindings/codegen/parser/update.sh
+++ b/components/script/dom/bindings/codegen/parser/update.sh
@@ -2,6 +2,7 @@ wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/Web
patch < abstract.patch
patch < debug.patch
patch < pref-main-thread.patch
+patch < callback-location.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests