зеркало из https://github.com/mozilla/gecko-dev.git
Bug 830099. Flag WebIDL dictionaries and callbacks with some information indicating whether we need main-thread and worker codegen for them and then use that information to skip unneccessary codegen. r=peterv
This commit is contained in:
Родитель
8ccc3897f4
Коммит
719c7bf030
|
@ -248,6 +248,17 @@ DOMInterfaces = {
|
|||
}
|
||||
},
|
||||
|
||||
'DummyInterface': {
|
||||
'skipGen': True,
|
||||
'register': False,
|
||||
},
|
||||
|
||||
'DummyInterfaceWorkers': {
|
||||
'skipGen': True,
|
||||
'register': False,
|
||||
'workers': True
|
||||
},
|
||||
|
||||
'DynamicsCompressorNode': {
|
||||
'resultNotAddRefed': [ 'threshold', 'knee', 'ratio',
|
||||
'reduction', 'attack', 'release' ],
|
||||
|
|
|
@ -10,7 +10,7 @@ import re
|
|||
import string
|
||||
|
||||
from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType
|
||||
from Configuration import NoSuchDescriptorError
|
||||
from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback
|
||||
|
||||
AUTOGENERATED_WARNING_COMMENT = \
|
||||
"/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
|
||||
|
@ -389,45 +389,6 @@ class CGIncludeGuard(CGWrapper):
|
|||
declarePre='#ifndef %s\n#define %s\n\n' % (define, define),
|
||||
declarePost='\n#endif // %s\n' % define)
|
||||
|
||||
def getTypesFromDescriptor(descriptor):
|
||||
"""
|
||||
Get all argument and return types for all members of the descriptor
|
||||
"""
|
||||
members = [m for m in descriptor.interface.members]
|
||||
if descriptor.interface.ctor():
|
||||
members.append(descriptor.interface.ctor())
|
||||
signatures = [s for m in members if m.isMethod() for s in m.signatures()]
|
||||
types = []
|
||||
for s in signatures:
|
||||
assert len(s) == 2
|
||||
(returnType, arguments) = s
|
||||
types.append(returnType)
|
||||
types.extend(a.type for a in arguments)
|
||||
|
||||
types.extend(a.type for a in members if a.isAttr())
|
||||
return types
|
||||
|
||||
def getTypesFromDictionary(dictionary):
|
||||
"""
|
||||
Get all member types for this dictionary
|
||||
"""
|
||||
types = []
|
||||
curDict = dictionary
|
||||
while curDict:
|
||||
types.extend([m.type for m in curDict.members])
|
||||
curDict = curDict.parent
|
||||
return types
|
||||
|
||||
def getTypesFromCallback(callback):
|
||||
"""
|
||||
Get the types this callback depends on: its return type and the
|
||||
types of its arguments.
|
||||
"""
|
||||
sig = callback.signatures()[0]
|
||||
types = [sig[0]] # Return type
|
||||
types.extend(arg.type for arg in sig[1]) # Arguments
|
||||
return types
|
||||
|
||||
def getRelevantProviders(descriptor, dictionary, config):
|
||||
assert not descriptor or not dictionary
|
||||
if descriptor is not None:
|
||||
|
@ -6523,34 +6484,16 @@ class CGDictionary(CGThing):
|
|||
self.descriptorProvider = descriptorProvider
|
||||
self.workers = descriptorProvider.workers
|
||||
self.needToInitIds = not self.workers and len(dictionary.members) > 0
|
||||
if all(CGDictionary(d, descriptorProvider).generatable for
|
||||
d in CGDictionary.getDictionaryDependencies(dictionary)):
|
||||
self.generatable = True
|
||||
else:
|
||||
self.generatable = False
|
||||
# Nothing else to do here
|
||||
return
|
||||
# Getting a conversion template for interface types can fail
|
||||
# if we don't have a relevant descriptor when self.workers is True.
|
||||
# If that happens, just mark ourselves as not being
|
||||
# generatable and move on.
|
||||
try:
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
getJSToNativeConversionTemplate(member.type,
|
||||
descriptorProvider,
|
||||
isMember="Dictionary",
|
||||
isOptional=(not member.defaultValue),
|
||||
defaultValue=member.defaultValue))
|
||||
for member in dictionary.members ]
|
||||
except NoSuchDescriptorError, err:
|
||||
if not self.workers:
|
||||
raise err
|
||||
self.generatable = False
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
getJSToNativeConversionTemplate(member.type,
|
||||
descriptorProvider,
|
||||
isMember="Dictionary",
|
||||
isOptional=(not member.defaultValue),
|
||||
defaultValue=member.defaultValue))
|
||||
for member in dictionary.members ]
|
||||
|
||||
def declare(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
inheritance = ": public %s " % self.makeClassName(d.parent)
|
||||
|
@ -6599,8 +6542,6 @@ class CGDictionary(CGThing):
|
|||
"inheritance": inheritance }))
|
||||
|
||||
def define(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
initParent = ("// Per spec, we init the parent's members first\n"
|
||||
|
@ -6884,8 +6825,14 @@ class CGBindingRoot(CGThing):
|
|||
descriptors = config.getDescriptors(webIDLFile=webIDLFile,
|
||||
hasInterfaceOrInterfacePrototypeObject=True,
|
||||
skipGen=False)
|
||||
dictionaries = config.getDictionaries(webIDLFile)
|
||||
callbacks = config.getCallbacks(webIDLFile)
|
||||
mainDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
|
||||
workers=False)
|
||||
workerDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
|
||||
workers=True)
|
||||
mainCallbacks = config.getCallbacks(webIDLFile=webIDLFile,
|
||||
workers=False)
|
||||
workerCallbacks = config.getCallbacks(webIDLFile=webIDLFile,
|
||||
workers=True)
|
||||
callbackDescriptors = config.getDescriptors(webIDLFile=webIDLFile,
|
||||
isCallback=True)
|
||||
|
||||
|
@ -6894,20 +6841,23 @@ class CGBindingRoot(CGThing):
|
|||
descriptorsForForwardDeclaration = list(descriptors)
|
||||
ifaces = []
|
||||
workerIfaces = []
|
||||
for dictionary in dictionaries:
|
||||
dictionaryIfaces = [ type.unroll().inner
|
||||
for type in getTypesFromDictionary(dictionary)
|
||||
if type.unroll().isGeckoInterface() ]
|
||||
ifaces.extend(dictionaryIfaces)
|
||||
workerIfaces.extend(dictionaryIfaces)
|
||||
def getInterfacesFromDictionary(d):
|
||||
return [ type.unroll().inner
|
||||
for type in getTypesFromDictionary(d)
|
||||
if type.unroll().isGeckoInterface() ]
|
||||
for dictionary in mainDictionaries:
|
||||
ifaces.extend(getInterfacesFromDictionary(dictionary))
|
||||
for dictionary in workerDictionaries:
|
||||
workerIfaces.extend(getInterfacesFromDictionary(dictionary))
|
||||
|
||||
for callback in callbacks:
|
||||
callbackIfaces = [ t.unroll().inner
|
||||
for t in getTypesFromCallback(callback)
|
||||
if t.unroll().isGeckoInterface() ]
|
||||
workerIfaces.extend(callbackIfaces)
|
||||
if not callback.isWorkerOnly():
|
||||
ifaces.extend(callbackIfaces)
|
||||
def getInterfacesFromCallback(c):
|
||||
return [ t.unroll().inner
|
||||
for t in getTypesFromCallback(c)
|
||||
if t.unroll().isGeckoInterface() ]
|
||||
for callback in mainCallbacks:
|
||||
ifaces.extend(getInterfacesFromCallback(callback))
|
||||
for callback in workerCallbacks:
|
||||
workerIfaces.extend(getInterfacesFromCallback(callback))
|
||||
|
||||
for callbackDescriptor in callbackDescriptors:
|
||||
callbackDescriptorIfaces = [
|
||||
|
@ -6948,7 +6898,7 @@ class CGBindingRoot(CGThing):
|
|||
|
||||
# Now add the forward declarations we need for our union types
|
||||
# and callback functions.
|
||||
for callback in callbacks:
|
||||
for callback in mainCallbacks + workerCallbacks:
|
||||
forwardDeclares.extend(
|
||||
declareNativeType("mozilla::dom::" + str(t.unroll()))
|
||||
for t in getTypesFromCallback(callback)
|
||||
|
@ -6961,7 +6911,7 @@ class CGBindingRoot(CGThing):
|
|||
if t.unroll().isUnion() or t.unroll().isCallback())
|
||||
|
||||
# Forward declarations for callback functions used in dictionaries.
|
||||
for dictionary in dictionaries:
|
||||
for dictionary in mainDictionaries + workerDictionaries:
|
||||
forwardDeclares.extend(
|
||||
declareNativeType("mozilla::dom::" + str(t.unroll()))
|
||||
for t in getTypesFromDictionary(dictionary)
|
||||
|
@ -7007,30 +6957,31 @@ class CGBindingRoot(CGThing):
|
|||
# declares a dictionary which inherits from a dictionary in B and B
|
||||
# declares a dictionary (possibly a different one!) that inherits from a
|
||||
# dictionary in A. The good news is that I expect this to never happen.
|
||||
reSortedDictionaries = []
|
||||
dictionaries = set(dictionaries)
|
||||
while len(dictionaries) != 0:
|
||||
# Find the dictionaries that don't depend on anything else anymore
|
||||
# and move them over.
|
||||
toMove = [d for d in dictionaries if
|
||||
len(CGDictionary.getDictionaryDependencies(d) &
|
||||
dictionaries) == 0]
|
||||
if len(toMove) == 0:
|
||||
raise TypeError("Loop in dictionary dependency graph")
|
||||
dictionaries = dictionaries - set(toMove)
|
||||
reSortedDictionaries.extend(toMove)
|
||||
def sortDictionaries(dictionaries):
|
||||
reSortedDictionaries = []
|
||||
dictionaries = set(dictionaries)
|
||||
while len(dictionaries) != 0:
|
||||
# Find the dictionaries that don't depend on anything else
|
||||
# anymore and move them over.
|
||||
toMove = [d for d in dictionaries if
|
||||
len(CGDictionary.getDictionaryDependencies(d) &
|
||||
dictionaries) == 0]
|
||||
if len(toMove) == 0:
|
||||
raise TypeError("Loop in dictionary dependency graph")
|
||||
dictionaries = dictionaries - set(toMove)
|
||||
reSortedDictionaries.extend(toMove)
|
||||
return reSortedDictionaries
|
||||
|
||||
dictionaries = reSortedDictionaries
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
|
||||
for d in dictionaries])
|
||||
for d in sortDictionaries(workerDictionaries)])
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
|
||||
for d in dictionaries])
|
||||
for d in sortDictionaries(mainDictionaries)])
|
||||
|
||||
# Do codegen for all the callbacks. Only do non-worker codegen for now,
|
||||
# since we don't have a sane setup yet for invoking callbacks in workers
|
||||
# and managing their lifetimes.
|
||||
cgthings.extend(CGCallbackFunction(c, config.getDescriptorProvider(False))
|
||||
for c in callbacks)
|
||||
for c in mainCallbacks)
|
||||
|
||||
# Do codegen for all the descriptors
|
||||
cgthings.extend([CGDescriptor(x) for x in descriptors])
|
||||
|
@ -7053,8 +7004,8 @@ class CGBindingRoot(CGThing):
|
|||
|
||||
# Add header includes.
|
||||
curr = CGHeaders(descriptors,
|
||||
dictionaries,
|
||||
callbacks,
|
||||
mainDictionaries + workerDictionaries,
|
||||
mainCallbacks + workerCallbacks,
|
||||
callbackDescriptors,
|
||||
['mozilla/dom/BindingDeclarations.h',
|
||||
'mozilla/ErrorResult.h',
|
||||
|
@ -7669,38 +7620,22 @@ class CGCallback(CGClass):
|
|||
name = idlObject.identifier.name
|
||||
if descriptorProvider.workers:
|
||||
name += "Workers"
|
||||
try:
|
||||
# For our public methods that needThisHandling we want most of the
|
||||
# same args and the same return type as what CallbackMember
|
||||
# generates. So we want to take advantage of all its
|
||||
# CGNativeMember infrastructure, but that infrastructure can't deal
|
||||
# with templates and most especially template arguments. So just
|
||||
# cheat and have CallbackMember compute all those things for us.
|
||||
realMethods = []
|
||||
for method in methods:
|
||||
if not method.needThisHandling:
|
||||
realMethods.append(method)
|
||||
else:
|
||||
realMethods.extend(self.getMethodImpls(method))
|
||||
CGClass.__init__(self, name,
|
||||
bases=[ClassBase(baseName)],
|
||||
constructors=self.getConstructors(),
|
||||
methods=realMethods+getters+setters)
|
||||
self.generatable = True
|
||||
except NoSuchDescriptorError, err:
|
||||
if not descriptorProvider.workers:
|
||||
raise err
|
||||
self.generatable = False
|
||||
|
||||
def define(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
return CGClass.define(self)
|
||||
|
||||
def declare(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
return CGClass.declare(self)
|
||||
# For our public methods that needThisHandling we want most of the
|
||||
# same args and the same return type as what CallbackMember
|
||||
# generates. So we want to take advantage of all its
|
||||
# CGNativeMember infrastructure, but that infrastructure can't deal
|
||||
# with templates and most especially template arguments. So just
|
||||
# cheat and have CallbackMember compute all those things for us.
|
||||
realMethods = []
|
||||
for method in methods:
|
||||
if not method.needThisHandling:
|
||||
realMethods.append(method)
|
||||
else:
|
||||
realMethods.extend(self.getMethodImpls(method))
|
||||
CGClass.__init__(self, name,
|
||||
bases=[ClassBase(baseName)],
|
||||
constructors=self.getConstructors(),
|
||||
methods=realMethods+getters+setters)
|
||||
|
||||
def getConstructors(self):
|
||||
return [ClassConstructor(
|
||||
|
@ -7768,9 +7703,6 @@ class CGCallback(CGClass):
|
|||
|
||||
class CGCallbackFunction(CGCallback):
|
||||
def __init__(self, callback, descriptorProvider):
|
||||
if callback.isWorkerOnly() and not descriptorProvider.workers:
|
||||
self.generatable = False
|
||||
return
|
||||
CGCallback.__init__(self, callback, descriptorProvider,
|
||||
"CallbackFunction",
|
||||
methods=[CallCallback(callback, descriptorProvider)])
|
||||
|
|
|
@ -62,10 +62,33 @@ class Configuration:
|
|||
descriptor.uniqueImplementation = len(otherDescriptors) == 1
|
||||
|
||||
self.enums = [e for e in parseData if e.isEnum()]
|
||||
|
||||
# Figure out what our main-thread and worker dictionaries and callbacks
|
||||
# are.
|
||||
mainTypes = set()
|
||||
for descriptor in self.getDescriptors(workers=False, isExternal=False):
|
||||
mainTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
|
||||
(mainCallbacks, mainDictionaries) = findCallbacksAndDictionaries(mainTypes)
|
||||
|
||||
workerTypes = set();
|
||||
for descriptor in self.getDescriptors(workers=True, isExternal=False):
|
||||
workerTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
|
||||
(workerCallbacks, workerDictionaries) = findCallbacksAndDictionaries(workerTypes)
|
||||
|
||||
self.dictionaries = [d for d in parseData if d.isDictionary()]
|
||||
self.callbacks = [c for c in parseData if
|
||||
c.isCallback() and not c.isInterface()]
|
||||
|
||||
def flagWorkerOrMainThread(items, main, worker):
|
||||
for item in items:
|
||||
if item in main:
|
||||
item.setUserData("mainThread", True)
|
||||
if item in worker:
|
||||
item.setUserData("workers", True)
|
||||
flagWorkerOrMainThread(self.dictionaries, mainDictionaries,
|
||||
workerDictionaries);
|
||||
flagWorkerOrMainThread(self.callbacks, mainCallbacks, workerCallbacks)
|
||||
|
||||
# Keep the descriptor list sorted for determinism.
|
||||
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
|
||||
|
||||
|
@ -95,14 +118,26 @@ class Configuration:
|
|||
return curr
|
||||
def getEnums(self, webIDLFile):
|
||||
return filter(lambda e: e.filename() == webIDLFile, self.enums)
|
||||
def getDictionaries(self, webIDLFile=None):
|
||||
if not webIDLFile:
|
||||
return self.dictionaries
|
||||
return filter(lambda d: d.filename() == webIDLFile, self.dictionaries)
|
||||
def getCallbacks(self, webIDLFile=None):
|
||||
if not webIDLFile:
|
||||
return self.callbacks
|
||||
return filter(lambda d: d.filename() == webIDLFile, self.callbacks)
|
||||
|
||||
@staticmethod
|
||||
def _filterForFileAndWorkers(items, filters):
|
||||
"""Gets the items that match the given filters."""
|
||||
for key, val in filters.iteritems():
|
||||
if key == 'webIDLFile':
|
||||
items = filter(lambda x: x.filename() == val, items)
|
||||
elif key == 'workers':
|
||||
if val:
|
||||
items = filter(lambda x: x.getUserData("workers", False), items)
|
||||
else:
|
||||
items = filter(lambda x: x.getUserData("mainThread", False), items)
|
||||
else:
|
||||
assert(0) # Unknown key
|
||||
return items
|
||||
def getDictionaries(self, **filters):
|
||||
return self._filterForFileAndWorkers(self.dictionaries, filters)
|
||||
def getCallbacks(self, **filters):
|
||||
return self._filterForFileAndWorkers(self.callbacks, filters)
|
||||
|
||||
def getDescriptor(self, interfaceName, workers):
|
||||
"""
|
||||
Gets the appropriate descriptor for the given interface name
|
||||
|
@ -407,3 +442,82 @@ class Descriptor(DescriptorProvider):
|
|||
def needsConstructHookHolder(self):
|
||||
assert self.interface.hasInterfaceObject()
|
||||
return not self.hasInstanceInterface and not self.interface.isCallback()
|
||||
|
||||
# Some utility methods
|
||||
def getTypesFromDescriptor(descriptor):
|
||||
"""
|
||||
Get all argument and return types for all members of the descriptor
|
||||
"""
|
||||
members = [m for m in descriptor.interface.members]
|
||||
if descriptor.interface.ctor():
|
||||
members.append(descriptor.interface.ctor())
|
||||
signatures = [s for m in members if m.isMethod() for s in m.signatures()]
|
||||
types = []
|
||||
for s in signatures:
|
||||
assert len(s) == 2
|
||||
(returnType, arguments) = s
|
||||
types.append(returnType)
|
||||
types.extend(a.type for a in arguments)
|
||||
|
||||
types.extend(a.type for a in members if a.isAttr())
|
||||
return types
|
||||
|
||||
def getFlatTypes(types):
|
||||
retval = set()
|
||||
for type in types:
|
||||
type = type.unroll()
|
||||
if type.isUnion():
|
||||
retval |= set(type.flatMemberTypes)
|
||||
else:
|
||||
retval.add(type)
|
||||
return retval
|
||||
|
||||
def getTypesFromDictionary(dictionary):
|
||||
"""
|
||||
Get all member types for this dictionary
|
||||
"""
|
||||
types = []
|
||||
curDict = dictionary
|
||||
while curDict:
|
||||
types.extend([m.type for m in curDict.members])
|
||||
curDict = curDict.parent
|
||||
return types
|
||||
|
||||
def getTypesFromCallback(callback):
|
||||
"""
|
||||
Get the types this callback depends on: its return type and the
|
||||
types of its arguments.
|
||||
"""
|
||||
sig = callback.signatures()[0]
|
||||
types = [sig[0]] # Return type
|
||||
types.extend(arg.type for arg in sig[1]) # Arguments
|
||||
return types
|
||||
|
||||
def findCallbacksAndDictionaries(inputTypes):
|
||||
"""
|
||||
Ensure that all callbacks and dictionaries reachable from types end up in
|
||||
the returned callbacks and dictionaries sets.
|
||||
|
||||
Note that we assume that our initial invocation already includes all types
|
||||
reachable via descriptors in "types", so we only have to deal with things
|
||||
that are themeselves reachable via callbacks and dictionaries.
|
||||
"""
|
||||
def doFindCallbacksAndDictionaries(types, callbacks, dictionaries):
|
||||
unhandledTypes = set()
|
||||
for type in types:
|
||||
if type.isCallback() and type not in callbacks:
|
||||
unhandledTypes |= getFlatTypes(getTypesFromCallback(type))
|
||||
callbacks.add(type)
|
||||
elif type.isDictionary() and type.inner not in dictionaries:
|
||||
d = type.inner
|
||||
unhandledTypes |= getFlatTypes(getTypesFromDictionary(d))
|
||||
while d:
|
||||
dictionaries.add(d)
|
||||
d = d.parent
|
||||
if len(unhandledTypes) != 0:
|
||||
doFindCallbacksAndDictionaries(unhandledTypes, callbacks, dictionaries)
|
||||
|
||||
retCallbacks = set()
|
||||
retDictionaries = set()
|
||||
doFindCallbacksAndDictionaries(inputTypes, retCallbacks, retDictionaries)
|
||||
return (retCallbacks, retDictionaries)
|
||||
|
|
|
@ -2346,7 +2346,6 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
|
|||
argument.resolve(self)
|
||||
|
||||
self._treatNonCallableAsNull = False
|
||||
self._workerOnly = False
|
||||
|
||||
def isCallback(self):
|
||||
return True
|
||||
|
@ -2387,16 +2386,11 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
|
|||
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||
other.isNonCallbackInterface() or other.isDate())
|
||||
|
||||
def isWorkerOnly(self):
|
||||
return self._workerOnly
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
unhandledAttrs = []
|
||||
for attr in attrs:
|
||||
if attr.identifier() == "TreatNonCallableAsNull":
|
||||
self._treatNonCallableAsNull = True
|
||||
elif attr.identifier() == "WorkerOnly":
|
||||
self._workerOnly = True
|
||||
else:
|
||||
unhandledAttrs.append(attr)
|
||||
if len(unhandledAttrs) != 0:
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
// Dummy bindings that we need to force generation of things that
|
||||
// aren't actually referenced anywhere in IDL yet but are used in C++.
|
||||
|
||||
interface DummyInterface {
|
||||
readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler;
|
||||
FilePropertyBag fileBag();
|
||||
RTCIceServer rtcIceServer();
|
||||
};
|
||||
|
||||
interface DummyInterfaceWorkers {
|
||||
BlobPropertyBag blobBag();
|
||||
};
|
|
@ -40,6 +40,7 @@ webidl_files = \
|
|||
DOMStringMap.webidl \
|
||||
DOMTokenList.webidl \
|
||||
DOMTransaction.webidl \
|
||||
DummyBinding.webidl \
|
||||
DynamicsCompressorNode.webidl \
|
||||
Element.webidl \
|
||||
EventHandler.webidl \
|
||||
|
|
|
@ -351,6 +351,8 @@ PeerConnectionImpl::ConvertRTCConfiguration(const JS::Value& aSrc,
|
|||
}
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsresult rv;
|
||||
// XXXbz once this moves to WebIDL, remove the RTCIceServer hack
|
||||
// in DummyBinding.webidl.
|
||||
RTCIceServer server;
|
||||
{
|
||||
JS::Value v;
|
||||
|
|
Загрузка…
Ссылка в новой задаче