Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-08-14 15:16:22 -04:00
commit de062041d4
151 changed files with 2248 additions and 1430 deletions

View File

@ -396,7 +396,10 @@ SingleAccIterator::Next()
{
nsRefPtr<Accessible> nextAcc;
mAcc.swap(nextAcc);
return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nullptr;
if (!nextAcc || nextAcc->IsDefunct()) {
return nullptr;
}
return nextAcc;
}

View File

@ -486,7 +486,10 @@ HTMLTextFieldAccessible::IsWidget() const
Accessible*
HTMLTextFieldAccessible::ContainerWidget() const
{
return mParent && mParent->Role() == roles::AUTOCOMPLETE ? mParent : nullptr;
if (!mParent || mParent->Role() != roles::AUTOCOMPLETE) {
return nullptr;
}
return mParent;
}

View File

@ -32,10 +32,14 @@ this.ContentWebRTC = {
},
uninit: function() {
Services.obs.removeObserver(handleRequest, "getUserMedia:request");
Services.obs.removeObserver(handleGUMRequest, "getUserMedia:request");
Services.obs.removeObserver(handlePCRequest, "PeerConnection:request");
Services.obs.removeObserver(updateIndicators, "recording-device-events");
Services.obs.removeObserver(removeBrowserSpecificIndicator, "recording-window-ended");
Services.obs.removeObserver(processShutdown, "content-child-shutdown");
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT)
Services.obs.removeObserver(processShutdown, "content-child-shutdown");
this._initialized = false;
},

View File

@ -747,6 +747,7 @@ media/stagefright/foundation/hexdump.h
media/stagefright/MediaBuffer.h
media/stagefright/MediaBufferGroup.h
media/stagefright/MediaCodec.h
media/stagefright/MediaCodecSource.h
media/stagefright/MediaDefs.h
media/stagefright/MediaErrors.h
media/stagefright/MediaExtractor.h

View File

@ -4338,7 +4338,10 @@ nsDocShell::GetDocument()
nsPIDOMWindow*
nsDocShell::GetWindow()
{
return NS_SUCCEEDED(EnsureScriptEnvironment()) ? mScriptGlobal : nullptr;
if (NS_FAILED(EnsureScriptEnvironment())) {
return nullptr;
}
return mScriptGlobal;
}
NS_IMETHODIMP

View File

@ -210,25 +210,19 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
nsCOMPtr<nsIContent> root;
rv = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr, kNameSpaceID_XHTML,
getter_AddRefs(root));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> root = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr,
kNameSpaceID_XHTML);
rv = doc->AppendChildTo(root, false);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> head;
rv = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr, kNameSpaceID_XHTML,
getter_AddRefs(head));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> head = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr,
kNameSpaceID_XHTML);
rv = root->AppendChildTo(head, false);
NS_ENSURE_SUCCESS(rv, rv);
if (!DOMStringIsNull(aTitle)) {
nsCOMPtr<nsIContent> title;
rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr,
kNameSpaceID_XHTML, getter_AddRefs(title));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> title = doc->CreateElem(NS_LITERAL_STRING("title"),
nullptr, kNameSpaceID_XHTML);
rv = head->AppendChildTo(title, false);
NS_ENSURE_SUCCESS(rv, rv);
@ -239,10 +233,8 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIContent> body;
rv = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML,
getter_AddRefs(body));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> body = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr,
kNameSpaceID_XHTML);
rv = root->AppendChildTo(body, false);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -84,7 +84,10 @@ public:
File* IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mFiles.Length();
return aFound ? mFiles.ElementAt(aIndex) : nullptr;
if (!aFound) {
return nullptr;
}
return mFiles.ElementAt(aIndex);
}
uint32_t Length()

View File

@ -706,7 +706,7 @@ ImportManager::AddLoaderWithNewURI(ImportLoader* aLoader, nsIURI* aNewURI)
mImports.Put(aNewURI, aLoader);
}
nsRefPtr<ImportLoader> ImportManager::GetNearestPredecessor(nsINode* aNode)
ImportLoader* ImportManager::GetNearestPredecessor(nsINode* aNode)
{
// Return the previous link if there is any in the same document.
nsIDocument* doc = aNode->OwnerDoc();

View File

@ -265,7 +265,7 @@ public:
// It finds the predecessor for an import link node that runs its
// scripts the latest among its predecessors.
nsRefPtr<ImportLoader> GetNearestPredecessor(nsINode* aNode);
ImportLoader* GetNearestPredecessor(nsINode* aNode);
private:
ImportMap mImports;

View File

@ -5447,13 +5447,8 @@ nsIDocument::CreateElement(const nsAString& aTagName, ErrorResult& rv)
nsContentUtils::ASCIIToLower(aTagName, lcTagName);
}
nsCOMPtr<nsIContent> content;
rv = CreateElem(needsLowercase ? lcTagName : aTagName,
nullptr, mDefaultElementType, getter_AddRefs(content));
if (rv.Failed()) {
return nullptr;
}
return dont_AddRef(content.forget().take()->AsElement());
return CreateElem(needsLowercase ? lcTagName : aTagName, nullptr,
mDefaultElementType);
}
void
@ -5797,13 +5792,10 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
nsDependentAtomString localName(definition->mLocalName);
nsCOMPtr<nsIContent> newElement;
nsresult rv = document->CreateElem(localName, nullptr,
definition->mNamespaceID,
getter_AddRefs(newElement));
NS_ENSURE_SUCCESS(rv, true);
nsCOMPtr<Element> element =
document->CreateElem(localName, nullptr, definition->mNamespaceID);
NS_ENSURE_TRUE(element, true);
nsCOMPtr<Element> element = do_QueryInterface(newElement);
if (definition->mLocalName != typeAtom) {
// This element is a custom element by extension, thus we need to
// do some special setup. For non-extended custom elements, this happens
@ -5811,7 +5803,7 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
document->SetupCustomElement(element, definition->mNamespaceID, &elemName);
}
rv = nsContentUtils::WrapNative(aCx, newElement, newElement, args.rval());
nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval());
NS_ENSURE_SUCCESS(rv, true);
return true;
@ -8600,9 +8592,9 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
}
}
nsresult
nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, int32_t aNamespaceID,
nsIContent **aResult)
already_AddRefed<Element>
nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix,
int32_t aNamespaceID)
{
#ifdef DEBUG
nsAutoString qName;
@ -8621,19 +8613,16 @@ nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, int32_t aNamesp
"check caller.");
#endif
*aResult = nullptr;
nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID,
nsIDOMNode::ELEMENT_NODE,
getter_AddRefs(nodeInfo));
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(nodeInfo, nullptr);
nsCOMPtr<Element> element;
nsresult rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
NOT_FROM_PARSER);
element.forget(aResult);
return rv;
return NS_SUCCEEDED(rv) ? element.forget() : nullptr;
}
bool

View File

@ -1011,9 +1011,9 @@ public:
virtual nsresult Init();
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
int32_t aNamespaceID,
nsIContent **aResult) override;
virtual already_AddRefed<Element> CreateElem(const nsAString& aName,
nsIAtom* aPrefix,
int32_t aNamespaceID) override;
virtual void Sanitize() override;

View File

@ -696,7 +696,10 @@ ShadowRoot *
nsGenericDOMDataNode::GetContainingShadow() const
{
nsDataSlots *slots = GetExistingDataSlots();
return slots ? slots->mContainingShadow : nullptr;
if (!slots) {
return nullptr;
}
return slots->mContainingShadow;
}
void

View File

@ -152,8 +152,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x6d18ec0b, 0x1f68, 0x4ae6, \
{ 0x8b, 0x3d, 0x8d, 0x7d, 0x8b, 0x8e, 0x28, 0xd4 } }
{ 0x292450a1, 0x285e, 0x4a09, \
{ 0x9a, 0xf9, 0x61, 0xf9, 0xb1, 0xbd, 0x27, 0xcc } }
// Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor {
@ -1372,10 +1372,11 @@ public:
/**
* Create an element with the specified name, prefix and namespace ID.
* Returns null if element name parsing failed.
*/
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
int32_t aNamespaceID,
nsIContent** aResult) = 0;
virtual already_AddRefed<Element> CreateElem(const nsAString& aName,
nsIAtom* aPrefix,
int32_t aNamespaceID) = 0;
/**
* Get the security info (i.e. SSL state etc) that the document got

View File

@ -264,8 +264,10 @@ nsMimeType::GetDescription(nsString& aRetval) const
nsPluginElement*
nsMimeType::GetEnabledPlugin() const
{
return (mPluginElement && mPluginElement->PluginTag()->IsEnabled()) ?
mPluginElement : nullptr;
if (!mPluginElement || !mPluginElement->PluginTag()->IsEnabled()) {
return nullptr;
}
return mPluginElement;
}
void

View File

@ -175,7 +175,11 @@ nsPluginArray::IndexedGetter(uint32_t aIndex, bool &aFound)
aFound = aIndex < mPlugins.Length();
return aFound ? mPlugins[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mPlugins[aIndex];
}
void
@ -391,7 +395,11 @@ nsPluginElement::IndexedGetter(uint32_t aIndex, bool &aFound)
aFound = aIndex < mMimeTypes.Length();
return aFound ? mMimeTypes[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mMimeTypes[aIndex];
}
nsMimeType*

View File

@ -113,6 +113,7 @@ def memoize(fn):
grows without bound.
"""
cache = {}
@functools.wraps(fn)
def wrapper(arg):
retval = cache.get(arg)
@ -121,6 +122,7 @@ def memoize(fn):
return retval
return wrapper
@memoize
def dedent(s):
"""
@ -595,6 +597,7 @@ def InterfacePrototypeObjectProtoGetter(descriptor):
return (protoGetter, protoHandleGetter)
class CGPrototypeJSClass(CGThing):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
@ -656,6 +659,7 @@ def NeedsGeneratedHasInstance(descriptor):
assert descriptor.interface.hasInterfaceObject()
return descriptor.hasXPConnectImpls or descriptor.interface.isConsequential()
def InterfaceObjectProtoGetter(descriptor):
"""
Returns a tuple with two elements:
@ -679,6 +683,7 @@ def InterfaceObjectProtoGetter(descriptor):
protoHandleGetter = None
return (protoGetter, protoHandleGetter)
class CGInterfaceObjectJSClass(CGThing):
def __init__(self, descriptor, properties):
CGThing.__init__(self)
@ -1020,7 +1025,7 @@ class CGHeaders(CGWrapper):
implementationIncludes |= set(self.getDeclarationFilename(i) for i in
interfacesImplementingSelf)
# Grab the includes for the things that involve XPCOM interfaces
# Grab the includes for the things that involve XPCOM interfaces
hasInstanceIncludes = set("nsIDOM" + d.interface.identifier.name + ".h" for d
in descriptors if
d.interface.hasInterfaceObject() and
@ -1214,6 +1219,7 @@ def SortedDictValues(d):
"""
return [v for k, v in sorted(d.items())]
def UnionsForFile(config, webIDLFile):
"""
Returns a list of tuples each containing two elements (type and descriptor)
@ -1223,6 +1229,7 @@ def UnionsForFile(config, webIDLFile):
"""
return config.unionsPerFilename.get(webIDLFile, [])
def UnionTypes(unionTypes, config):
"""
The unionTypes argument should be a list of tuples, each containing two
@ -1322,6 +1329,7 @@ def UnionTypes(unionTypes, config):
SortedDictValues(traverseMethods), SortedDictValues(unlinkMethods),
SortedDictValues(unionStructs))
def UnionConversions(unionTypes, config):
"""
The unionTypes argument should be a list of tuples, each containing two
@ -1339,6 +1347,7 @@ def UnionConversions(unionTypes, config):
if name not in unionConversions:
providers = getRelevantProviders(descriptor, config)
unionConversions[name] = CGUnionConversionStruct(t, providers[0])
def addHeadersForType(f, providers):
f = f.unroll()
if f.isInterface():
@ -2028,8 +2037,8 @@ class PropertyDefiner:
# pref control is added to members while still allowing us to define all
# the members in the smallest number of JSAPI calls.
assert len(array) != 0
lastCondition = getCondition(array[0], self.descriptor) # So we won't put a specTerminator
# at the very front of the list.
# So we won't put a specTerminator at the very front of the list:
lastCondition = getCondition(array[0], self.descriptor)
specs = []
prefableSpecs = []
@ -2107,6 +2116,7 @@ def isMaybeExposedIn(member, descriptor):
# and member is not exposed in any worker, then it's not exposed.
return not descriptor.workers or member.isExposedInAnyWorker()
def clearableCachedAttrs(descriptor):
return (m for m in descriptor.interface.members if
m.isAttr() and
@ -2114,12 +2124,15 @@ def clearableCachedAttrs(descriptor):
m.dependsOn != "Nothing" and
m.slotIndex is not None)
def MakeClearCachedValueNativeName(member):
return "ClearCached%sValue" % MakeNativeName(member.identifier.name)
def MakeJSImplClearCachedValueNativeName(member):
return "_" + MakeClearCachedValueNativeName(member)
def IDLToCIdentifier(name):
return name.replace("-", "_")
@ -2292,8 +2305,8 @@ class MethodDefiner(PropertyDefiner):
"nativeName": "UnforgeableValueOf",
"methodInfo": False,
"length": 0,
"flags": "JSPROP_ENUMERATE", # readonly/permanent added
# automatically.
"flags": "JSPROP_ENUMERATE", # readonly/permanent added
# automatically.
"condition": MemberCondition(None, None)
})
@ -2405,7 +2418,7 @@ def IsCrossOriginWritable(attr, descriptor):
crossOriginWritable = attr.getExtendedAttribute("CrossOriginWritable")
if not crossOriginWritable:
return False
if crossOriginWritable == True:
if crossOriginWritable is True:
return True
assert (isinstance(crossOriginWritable, list) and
len(crossOriginWritable) == 1)
@ -2585,7 +2598,7 @@ class CGNativeProperties(CGList):
if item.get("hasIteratorAlias"):
iteratorAliasIndex = index
break
nativeProps.append(CGGeneric(str(iteratorAliasIndex)));
nativeProps.append(CGGeneric(str(iteratorAliasIndex)))
return CGWrapper(CGIndenter(CGList(nativeProps, ",\n")),
pre="static const NativeProperties %s = {\n" % name,
post="\n};\n")
@ -2606,6 +2619,7 @@ class CGNativeProperties(CGList):
def define(self):
return CGList.define(self)
class CGJsonifyAttributesMethod(CGAbstractMethod):
"""
Generate the JsonifyAttributes method for an interface descriptor
@ -2638,6 +2652,7 @@ class CGJsonifyAttributesMethod(CGAbstractMethod):
ret += 'return true;\n'
return ret
class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
"""
Generate the CreateInterfaceObjects method for an interface descriptor.
@ -2891,18 +2906,20 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
# XXX If we ever create non-enumerate properties that can be
# aliased, we should consider making the aliases match
# the enumerability of the property being aliased.
CGGeneric(fill("""
if (!${defineFn}(aCx, proto, ${prop}, aliasedVal, JSPROP_ENUMERATE)) {
return;
}
""",
defineFn=defineFn,
prop=prop))
CGGeneric(fill(
"""
if (!${defineFn}(aCx, proto, ${prop}, aliasedVal, JSPROP_ENUMERATE)) {
return;
}
""",
defineFn=defineFn,
prop=prop))
], "\n")
def defineAliasesFor(m):
return CGList([
CGGeneric(fill("""
CGGeneric(fill(
"""
if (!JS_GetProperty(aCx, proto, \"${prop}\", &aliasedVal)) {
return;
}
@ -2991,12 +3008,14 @@ class CGGetProtoObjectMethod(CGAbstractMethod):
"""
def __init__(self, descriptor):
CGAbstractMethod.__init__(
self, descriptor, "GetProtoObject", "JSObject*", [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal')])
self, descriptor, "GetProtoObject", "JSObject*",
[Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal')])
def definition_body(self):
return "return GetProtoObjectHandle(aCx, aGlobal);\n"
class CGGetConstructorObjectHandleMethod(CGGetPerInterfaceObject):
"""
A method for getting the interface constructor object.
@ -3014,18 +3033,21 @@ class CGGetConstructorObjectHandleMethod(CGGetPerInterfaceObject):
""") + CGGetPerInterfaceObject.definition_body(self)
class CGGetConstructorObjectMethod(CGAbstractMethod):
"""
A method for getting the interface constructor object.
"""
def __init__(self, descriptor):
CGAbstractMethod.__init__(
self, descriptor, "GetConstructorObject", "JSObject*", [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal')])
self, descriptor, "GetConstructorObject", "JSObject*",
[Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal')])
def definition_body(self):
return "return GetConstructorObjectHandle(aCx, aGlobal);\n"
class CGGetNamedPropertiesObjectMethod(CGAbstractStaticMethod):
def __init__(self, descriptor):
args = [Argument('JSContext*', 'aCx'),
@ -3190,11 +3212,13 @@ class CGConstructorEnabled(CGAbstractMethod):
conditionsWrapper = ""
if len(conditions):
conditionsWrapper = CGWrapper(CGList((CGGeneric(cond) for cond in conditions),
" &&\n"),
pre="return ", post=";\n", reindent=True)
conditionsWrapper = CGWrapper(CGList((CGGeneric(cond) for cond in conditions),
" &&\n"),
pre="return ",
post=";\n",
reindent=True)
else:
conditionsWrapper = CGGeneric("return true;\n")
conditionsWrapper = CGGeneric("return true;\n")
body.append(conditionsWrapper)
return body.define()
@ -3288,6 +3312,7 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode):
return CGWrapper(CGList(unforgeables), pre="\n")
def CopyUnforgeablePropertiesToInstance(descriptor, wrapperCache):
"""
Copy the unforgeable properties from the unforgeable holder for
@ -4280,7 +4305,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
failureBody=onFailureNotAnObject(failureCode).define())
if isinstance(defaultValue, IDLNullValue):
assert type.nullable() # Parser should enforce this
assert type.nullable() # Parser should enforce this
templateBody = handleDefault(templateBody, codeToSetNull)
elif isinstance(defaultValue, IDLEmptySequenceValue):
# Our caller will handle it
@ -4311,14 +4336,15 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# For JS-implemented APIs, we refuse to allow passing objects that the
# API consumer does not subsume.
if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
templateBody = fill("""
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
$*{exceptionCode}
}
""",
sourceDescription=sourceDescription,
exceptionCode=exceptionCode) + templateBody
templateBody = fill(
"""
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
$*{exceptionCode}
}
""",
sourceDescription=sourceDescription,
exceptionCode=exceptionCode) + templateBody
setToNullCode = "${declName} = nullptr;\n"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
@ -4395,14 +4421,14 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
arrayRef = "${declName}"
elementConversion = string.Template(elementInfo.template).substitute({
"val": "temp" + str(nestingLevel),
"declName": "slot" + str(nestingLevel),
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder" + str(nestingLevel),
"passedToJSImpl": "${passedToJSImpl}"
})
"val": "temp" + str(nestingLevel),
"declName": "slot" + str(nestingLevel),
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder" + str(nestingLevel),
"passedToJSImpl": "${passedToJSImpl}"
})
# NOTE: Keep this in sync with variadic conversions as needed
templateBody = fill(
@ -4471,7 +4497,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not isEnforceRange and not isClamp
if failureCode is None:
notMozMap = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
"%s" % (firstCap(sourceDescription), exceptionCode))
"%s" % (firstCap(sourceDescription), exceptionCode))
else:
notMozMap = failureCode
@ -4502,14 +4528,14 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
mozMapRef = "${declName}"
valueConversion = string.Template(valueInfo.template).substitute({
"val": "temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder",
"passedToJSImpl": "${passedToJSImpl}"
})
"val": "temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder",
"passedToJSImpl": "${passedToJSImpl}"
})
templateBody = fill(
"""
@ -5075,7 +5101,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if type.isSpiderMonkeyInterface():
assert not isEnforceRange and not isClamp
name = type.unroll().name # unroll() because it may be nullable
name = type.unroll().name # unroll() because it may be nullable
arrayType = CGGeneric(name)
declType = arrayType
if type.nullable():
@ -5347,14 +5373,15 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# For JS-implemented APIs, we refuse to allow passing objects that the
# API consumer does not subsume.
if not isinstance(descriptorProvider, Descriptor) or descriptorProvider.interface.isJSImplemented():
templateBody = fill("""
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
$*{exceptionCode}
}
""",
sourceDescription=sourceDescription,
exceptionCode=exceptionCode) + templateBody
templateBody = fill(
"""
if ($${passedToJSImpl} && !CallerSubsumes($${val})) {
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
$*{exceptionCode}
}
""",
sourceDescription=sourceDescription,
exceptionCode=exceptionCode) + templateBody
# We may not have a default value if we're being converted for
# a setter, say.
@ -5939,7 +5966,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
$*{recTemplate}
""",
result=result,
setNull=setNull(),
setNull=setNull(),
recTemplate=recTemplate)
return code, recInfall
@ -6078,7 +6105,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
if not descriptor.hasXPConnectImpls:
# Can only fail to wrap as a new-binding object
# if they already threw an exception.
#XXX Assertion disabled for now, see bug 991271.
# XXX Assertion disabled for now, see bug 991271.
failed = ("MOZ_ASSERT(true || JS_IsExceptionPending(cx));\n" +
exceptionCode)
else:
@ -6648,6 +6675,7 @@ class MethodNotNewObjectError(Exception):
sequenceWrapLevel = 0
mapWrapLevel = 0
def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
"""
Take the thing named by "value" and if it contains "any",
@ -7496,7 +7524,7 @@ class CGMethodCall(CGThing):
if (distinguishingType(s).isArray() or
distinguishingType(s).isDictionary() or
distinguishingType(s).isMozMap() or
distinguishingType(s).isCallbackInterface()) ]
distinguishingType(s).isCallbackInterface())]
assert len(genericObjectSigs) <= 1
objectSigs.extend(genericObjectSigs)
@ -7611,6 +7639,7 @@ class FakeIdentifier():
def __init__(self, name):
self.name = name
class FakeArgument():
"""
A class that quacks like an IDLArgument. This is used to make
@ -7808,6 +7837,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
return ok;
"""))
class CGGenericPromiseReturningMethod(CGAbstractBindingMethod):
"""
A class for generating the C++ code for an IDL method that returns a Promise.
@ -7819,7 +7849,7 @@ class CGGenericPromiseReturningMethod(CGAbstractBindingMethod):
ThrowInvalidThis(cx, args, GetInvalidThisErrorForMethod(%%(securityError)s), "%s");\n
return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
args.rval());\n""" %
descriptor.interface.identifier.name)
descriptor.interface.identifier.name)
name = "genericPromiseReturningMethod"
customCallArgs = dedent("""
@ -7852,7 +7882,6 @@ class CGGenericPromiseReturningMethod(CGAbstractBindingMethod):
"""))
class CGSpecializedMethod(CGAbstractStaticMethod):
"""
A class for generating the C++ code for a specialized method that the JIT
@ -7924,7 +7953,7 @@ class CGJsonifierMethod(CGSpecializedMethod):
}
""")
jsonDescriptors = [ self.descriptor ]
jsonDescriptors = [self.descriptor]
interface = self.descriptor.interface.parent
while interface:
descriptor = self.descriptor.getDescriptor(interface.identifier.name)
@ -8446,7 +8475,7 @@ class CGMemberJITInfo(CGThing):
assert(not movable or aliasSet != "AliasEverything") # Can't move write-aliasing things
assert(not alwaysInSlot or movable) # Things always in slots had better be movable
assert(not eliminatable or aliasSet != "AliasEverything") # Can't eliminate write-aliasing things
assert(not alwaysInSlot or eliminatable) # Things always in slots had better be eliminatable
assert(not alwaysInSlot or eliminatable) # Things always in slots had better be eliminatable
def jitInfoInitializer(isTypedMethod):
initializer = fill(
@ -9495,6 +9524,7 @@ class CGUnionConversionStruct(CGThing):
def define(self):
return ""
def deps(self):
return set()
@ -10567,7 +10597,8 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
callNamedGetter = !hasOnProto;
""")
if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
computeCondition = fill("""
computeCondition = fill(
"""
if (!isXray) {
callNamedGetter = true;
} else {
@ -10580,6 +10611,8 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
if self.descriptor.supportsIndexedProperties():
outerCondition = "!IsArrayIndex(index) && " + outerCondition
namedGetCode = CGProxyNamedGetter(self.descriptor,
templateValues).define()
namedGet = fill("""
bool callNamedGetter = false;
if (${outerCondition}) {
@ -10589,9 +10622,9 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
$*{namedGetCode}
}
""",
outerCondition=outerCondition,
computeCondition=computeCondition,
namedGetCode=CGProxyNamedGetter(self.descriptor, templateValues).define())
outerCondition=outerCondition,
computeCondition=computeCondition,
namedGetCode=namedGetCode)
namedGet += "\n"
else:
namedGet = ""
@ -10815,7 +10848,8 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
""",
namedBody=namedBody)
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
delete = fill("""
delete = fill(
"""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
@ -10936,7 +10970,8 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
""",
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define())
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
named = fill("""
named = fill(
"""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
@ -11251,8 +11286,9 @@ class CGDOMJSProxyHandler_call(ClassMethod):
class CGDOMJSProxyHandler_isCallable(ClassMethod):
def __init__(self):
ClassMethod.__init__(self, "isCallable", "bool", [Argument('JSObject*', 'obj')],
virtual=True, override=True, const=True)
ClassMethod.__init__(self, "isCallable", "bool",
[Argument('JSObject*', 'obj')],
virtual=True, override=True, const=True)
def getBody(self):
return dedent("""
@ -11284,7 +11320,6 @@ class CGDOMJSProxyHandler(CGClass):
explicit=True)
]
if descriptor.supportsIndexedProperties():
methods.append(CGDOMJSProxyHandler_getElements(descriptor))
if (descriptor.operations['IndexedSetter'] is not None or
@ -11335,6 +11370,7 @@ def stripTrailingWhitespace(text):
lines = text.splitlines()
return '\n'.join(line.rstrip() for line in lines) + tail
class MemberProperties:
def __init__(self):
self.isGenericMethod = False
@ -11348,6 +11384,7 @@ class MemberProperties:
self.isCrossOriginSetter = False
self.isJsonifier = False
def memberProperties(m, descriptor):
props = MemberProperties()
if m.isMethod():
@ -11390,6 +11427,7 @@ def memberProperties(m, descriptor):
return props
class CGDescriptor(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
@ -11735,6 +11773,7 @@ class CGNamespacedEnum(CGThing):
def define(self):
return ""
def initIdsClassMethod(identifiers, atomCacheName):
idinit = ['!atomsCache->%s.init(cx, "%s")' %
(CGDictionary.makeIdName(id),
@ -11758,6 +11797,7 @@ def initIdsClassMethod(identifiers, atomCacheName):
Argument("%s*" % atomCacheName, "atomsCache")
], static=True, body=body, visibility="private")
class CGDictionary(CGThing):
def __init__(self, dictionary, descriptorProvider):
self.dictionary = dictionary
@ -12173,7 +12213,7 @@ class CGDictionary(CGThing):
"%s");
}
""" % self.getMemberSourceDescription(member))
conversionReplacements["convert"] = indent(conversionReplacements["convert"]).rstrip();
conversionReplacements["convert"] = indent(conversionReplacements["convert"]).rstrip()
else:
conversion += (
"if (!isNull && !temp->isUndefined()) {\n"
@ -12322,7 +12362,7 @@ class CGDictionary(CGThing):
# dictionaries. Either we're being constructed-but-not-initialized
# ourselves (and then we don't want to init them) or we're about to
# init ourselves and then we'll init them anyway.
return CGDictionary.getNonInitializingCtorArg();
return CGDictionary.getNonInitializingCtorArg()
return None
def getMemberSourceDescription(self, member):
@ -12812,8 +12852,8 @@ class CGBindingRoot(CGThing):
bindingHeaders["WrapperFactory.h"] = descriptors
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
bindingHeaders["xpcpublic.h"] = dictionaries ## xpc::UnprivilegedJunkScope
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope
cgthings.extend(traverseMethods)
cgthings.extend(unlinkMethods)
@ -13516,7 +13556,7 @@ class CGBindingImplClass(CGClass):
[FakeArgument(BuiltinTypes[IDLBuiltinType.Types.domstring],
FakeMember(),
name="aName")]),
{ "infallible": True }))
{"infallible": True}))
wrapArgs = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGivenProto')]
@ -13571,7 +13611,7 @@ class CGExampleClass(CGBindingImplClass):
self.parentIface.identifier.name)
bases = [ClassBase(self.nativeLeafName(self.parentDesc))]
else:
bases = [ ClassBase("nsISupports /* or NonRefcountedDOMObject if this is a non-refcounted object */") ]
bases = [ClassBase("nsISupports /* or NonRefcountedDOMObject if this is a non-refcounted object */")]
if descriptor.wrapperCache:
bases.append(ClassBase("nsWrapperCache /* Change wrapperCache in the binding configuration if you don't want this */"))
@ -13622,7 +13662,11 @@ class CGExampleClass(CGBindingImplClass):
ccImpl = dedent("""
// Only needed for refcounted objects.
#error "If you don't have members that need cycle collection, then remove all the cycle collection bits from this implementation and the corresponding header. If you do, you want NS_IMPL_CYCLE_COLLECTION_INHERITED(${nativeType}, ${parentType}, your, members, here)"
# error "If you don't have members that need cycle collection,
# then remove all the cycle collection bits from this
# implementation and the corresponding header. If you do, you
# want NS_IMPL_CYCLE_COLLECTION_INHERITED(${nativeType},
# ${parentType}, your, members, here)"
NS_IMPL_ADDREF_INHERITED(${nativeType}, ${parentType})
NS_IMPL_RELEASE_INHERITED(${nativeType}, ${parentType})
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${nativeType})
@ -15072,9 +15116,9 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
assert self.maplikeOrSetlike.isMaplike()
r = self.appendKeyArgConversion()
code = [CGGeneric(dedent(
"""
JS::Rooted<JS::Value> result(cx);
"""))]
"""
JS::Rooted<JS::Value> result(cx);
"""))]
arguments = ["&result"]
return self.mergeTuples(r, (code, arguments, []))
@ -15227,7 +15271,6 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
return " false"
return ""
def getCall(self):
return CGMaplikeOrSetlikeMethodGenerator(self.descriptorProvider,
self.maplikeOrSetlike,
@ -15304,6 +15347,7 @@ class GlobalGenRoots():
binaryMemberName = binaryNameFor(m.identifier.name)
return ClassMember(CGDictionary.makeIdName(binaryMemberName),
"PinnedStringId", visibility="public")
def buildAtomCacheStructure(idlobj, binaryNameFor, members):
classMembers = [memberToAtomCacheMember(binaryNameFor, m)
for m in members]
@ -15365,7 +15409,7 @@ class GlobalGenRoots():
@staticmethod
def GeneratedEventList(config):
eventList = CGList([]);
eventList = CGList([])
for generatedEvent in config.generatedEvents:
eventList.append(CGGeneric(declare=("GENERATED_EVENT(%s)\n" % generatedEvent)))
return eventList
@ -15524,9 +15568,9 @@ class GlobalGenRoots():
register=True,
isExposedInSystemGlobals=True,
skipGen=False)]
defineIncludes.append("nsThreadUtils.h") # For NS_IsMainThread
defineIncludes.append("js/Id.h") # For jsid
defineIncludes.append("mozilla/dom/BindingUtils.h") # AtomizeAndPinJSString
defineIncludes.append("nsThreadUtils.h") # For NS_IsMainThread
defineIncludes.append("js/Id.h") # For jsid
defineIncludes.append("mozilla/dom/BindingUtils.h") # AtomizeAndPinJSString
curr = CGHeaders([], [], [], [], [], defineIncludes,
'ResolveSystemBinding', curr)
@ -15608,11 +15652,14 @@ class GlobalGenRoots():
things.update(d.featureDetectibleThings)
things = CGList((CGGeneric(declare='"%s",' % t) for t in sorted(things)), joiner="\n")
things.append(CGGeneric(declare="nullptr"))
things = CGWrapper(CGIndenter(things), pre="static const char* const FeatureList[] = {\n",
post="\n};\n")
things = CGWrapper(CGIndenter(things),
pre="static const char* const FeatureList[] = {\n",
post="\n};\n")
helper = CGWrapper(CGIndenter(things), pre="bool IsFeatureDetectible(const nsAString& aFeature) {\n",
post=dedent("""
helper_pre = "bool IsFeatureDetectible(const nsAString& aFeature) {\n"
helper = CGWrapper(CGIndenter(things),
pre=helper_pre,
post=dedent("""
const char* const* feature = FeatureList;
while (*feature) {
if (aFeature.EqualsASCII(*feature)) {
@ -15631,6 +15678,7 @@ class GlobalGenRoots():
return curr
# Code generator for simple events
class CGEventGetter(CGNativeMember):
def __init__(self, descriptor, attr):
@ -15733,7 +15781,6 @@ class CGEventMethod(CGNativeMember):
if not allowed:
raise TypeError("Event code generator does not support methods!")
def getArgs(self, returnType, argList):
args = [self.getArg(arg) for arg in argList]
return args
@ -15769,7 +15816,7 @@ class CGEventMethod(CGNativeMember):
iface = self.descriptorProvider.interface
members = ""
while iface.identifier.name != "Event":
i = 3 # Skip the boilerplate args: type, bubble,s cancelable.
i = 3 # Skip the boilerplate args: type, bubble,s cancelable.
for m in iface.members:
if m.isAttr():
# We need to initialize all the member variables that do
@ -15791,10 +15838,10 @@ class CGEventMethod(CGNativeMember):
}
${members}
""",
typeArg = self.args[0].name,
bubblesArg = self.args[1].name,
cancelableArg = self.args[2].name,
members = members)
typeArg=self.args[0].name,
bubblesArg=self.args[1].name,
cancelableArg=self.args[2].name,
members=members)
self.args.append(Argument('ErrorResult&', 'aRv'))
@ -15825,7 +15872,7 @@ class CGEventMethod(CGNativeMember):
# use AppendElements, which is actually a template on
# the incoming type on nsTArray and does the right thing
# for this case.
target = name;
target = name
source = "%s.%s" % (self.args[1].name, name)
sequenceCopy = "e->%s.AppendElements(%s);\n"
if m.type.nullable():
@ -15846,14 +15893,14 @@ class CGEventMethod(CGNativeMember):
e->${varname} = ${srcname}.Value().Obj();
}
""",
varname=name,
srcname=srcname);
varname=name,
srcname=srcname)
else:
members += fill(
"""
e->${varname}.set(${srcname}.Obj());
""",
varname=name, srcname=srcname);
varname=name, srcname=srcname)
else:
members += "e->%s = %s.%s;\n" % (name, self.args[1].name, name)
if m.type.isAny() or m.type.isObject() or m.type.isSpiderMonkeyInterface():
@ -16110,20 +16157,24 @@ class CGEventRoot(CGThing):
parent = descriptor.interface.parent.identifier.name
# Throw in our #includes
self.root = CGHeaders([descriptor], [], [], [],
[
config.getDescriptor(parent, False).headerFile,
"mozilla/Attributes.h",
"mozilla/ErrorResult.h",
"mozilla/dom/%sBinding.h" % interfaceName,
'mozilla/dom/BindingUtils.h',
],
[
"%s.h" % interfaceName,
"js/GCAPI.h",
'mozilla/dom/Nullable.h',
],
"", self.root, config)
self.root = CGHeaders(
[descriptor],
[],
[],
[],
[
config.getDescriptor(parent, False).headerFile,
"mozilla/Attributes.h",
"mozilla/ErrorResult.h",
"mozilla/dom/%sBinding.h" % interfaceName,
'mozilla/dom/BindingUtils.h',
],
[
"%s.h" % interfaceName,
"js/GCAPI.h",
'mozilla/dom/Nullable.h',
],
"", self.root, config)
# And now some include guards
self.root = CGIncludeGuard(interfaceName, self.root)

View File

@ -8,6 +8,7 @@ from collections import defaultdict
autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
class Configuration:
"""
Represents global configuration state based on IDL parse data and
@ -26,8 +27,8 @@ class Configuration:
self.descriptors = []
self.interfaces = {}
self.optimizedOutDescriptorNames = set()
self.generatedEvents = generatedEvents;
self.maxProtoChainLength = 0;
self.generatedEvents = generatedEvents
self.maxProtoChainLength = 0
for thing in parseData:
if isinstance(thing, IDLImplementsStatement):
# Our build system doesn't support dep build involving
@ -49,7 +50,7 @@ class Configuration:
"%s" %
(thing.location, thing.implementor.location))
assert not thing.isType();
assert not thing.isType()
if not thing.isInterface():
continue
@ -88,7 +89,7 @@ class Configuration:
self.descriptors.extend([Descriptor(self, iface, x) for x in entry])
# Keep the descriptor list sorted for determinism.
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
self.descriptors.sort(lambda x, y: cmp(x.name, y.name))
self.descriptorsByName = {}
for d in self.descriptors:
@ -110,7 +111,7 @@ class Configuration:
mainTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
(mainCallbacks, mainDictionaries) = findCallbacksAndDictionaries(mainTypes)
workerTypes = set();
workerTypes = set()
for descriptor in ([self.getDescriptor("DummyInterfaceWorkers", workers=True)] +
self.getDescriptors(workers=True, isExternal=False, skipGen=False)):
workerTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor)))
@ -182,6 +183,7 @@ class Configuration:
def getInterface(self, ifname):
return self.interfaces[ifname]
def getDescriptors(self, **filters):
"""Gets the descriptors that match the given filters."""
curr = self.descriptors
@ -211,7 +213,7 @@ class Configuration:
elif key == 'isJSImplemented':
getter = lambda x: x.interface.isJSImplemented()
elif key == 'isNavigatorProperty':
getter = lambda x: x.interface.getNavigatorProperty() != None
getter = lambda x: x.interface.getNavigatorProperty() is not None
elif key == 'isExposedInAnyWorker':
getter = lambda x: x.interface.isExposedInAnyWorker()
elif key == 'isExposedInSystemGlobals':
@ -226,6 +228,7 @@ class Configuration:
for f in tofilter:
curr = filter(lambda x: f[0](x) == f[1], curr)
return curr
def getEnums(self, webIDLFile):
return filter(lambda e: e.filename() == webIDLFile, self.enums)
@ -241,10 +244,12 @@ class Configuration:
else:
items = filter(lambda x: x.getUserData("mainThread", False), items)
else:
assert(0) # Unknown key
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)
@ -271,7 +276,8 @@ class Configuration:
"and a consequential interface) without an explicit "
"Bindings.conf annotation." % interfaceName)
raise NoSuchDescriptorError("For " + interfaceName + " found no matches");
raise NoSuchDescriptorError("For " + interfaceName + " found no matches")
def getDescriptorProvider(self, workers):
"""
Gets a descriptor provider that can provide descriptors as needed,
@ -279,10 +285,12 @@ class Configuration:
"""
return DescriptorProvider(self, workers)
class NoSuchDescriptorError(TypeError):
def __init__(self, str):
TypeError.__init__(self, str)
class DescriptorProvider:
"""
A way of getting descriptors for interface names
@ -299,6 +307,7 @@ class DescriptorProvider:
"""
return self.config.getDescriptor(interfaceName, self.workers)
def methodReturnsJSObject(method):
assert method.isMethod()
if method.returnsPromise():
@ -415,6 +424,7 @@ class Descriptor(DescriptorProvider):
'LegacyCaller': None,
'Jsonifier': None
}
# Stringifiers and jsonifiers need to be set up whether an interface is
# concrete or not, because they're actually prototype methods and hence
# can apply to instances of descendant interfaces. Legacy callers and
@ -443,7 +453,7 @@ class Descriptor(DescriptorProvider):
if m.isMethod() and m.isLegacycaller():
if not m.isIdentifierLess():
raise TypeError("We don't support legacycaller with "
"identifier.\n%s" % m.location);
"identifier.\n%s" % m.location)
if len(m.signatures()) != 1:
raise TypeError("We don't support overloaded "
"legacycaller.\n%s" % m.location)
@ -501,7 +511,7 @@ class Descriptor(DescriptorProvider):
iface.setUserData('hasProxyDescendant', True)
iface = iface.parent
if desc.get('wantsQI', None) != None:
if desc.get('wantsQI', None) is not None:
self._wantsQI = desc.get('wantsQI', None)
self.wrapperCache = (not self.interface.isCallback() and
desc.get('wrapperCache', True))
@ -513,7 +523,7 @@ class Descriptor(DescriptorProvider):
# self.extendedAttributes is a dict of dicts, keyed on
# all/getterOnly/setterOnly and then on member name. Values are an
# array of extended attributes.
self.extendedAttributes = { 'all': {}, 'getterOnly': {}, 'setterOnly': {} }
self.extendedAttributes = {'all': {}, 'getterOnly': {}, 'setterOnly': {}}
def addExtendedAttribute(attribute, config):
def add(key, members, attribute):
@ -713,10 +723,9 @@ class Descriptor(DescriptorProvider):
"""
return (self.interface.isExternal() or self.concrete or
self.interface.hasInterfacePrototypeObject() or
any((m.isAttr() or m.isMethod()) and m.isStatic() for m
in self.interface.members) or
self.interface.parent)
self.interface.hasInterfacePrototypeObject() or
any((m.isAttr() or m.isMethod()) and m.isStatic() for m in self.interface.members) or
self.interface.parent)
def hasThreadChecks(self):
return ((self.isExposedConditionally() and
@ -759,6 +768,7 @@ class Descriptor(DescriptorProvider):
return (self.interface.getExtendedAttribute("Global") or
self.interface.getExtendedAttribute("PrimaryGlobal"))
# Some utility methods
def getTypesFromDescriptor(descriptor):
"""
@ -779,6 +789,7 @@ def getTypesFromDescriptor(descriptor):
types.extend(a.type for a in members if a.isAttr())
return types
def getFlatTypes(types):
retval = set()
for type in types:
@ -789,6 +800,7 @@ def getFlatTypes(types):
retval.add(type)
return retval
def getTypesFromDictionary(dictionary):
"""
Get all member types for this dictionary
@ -800,16 +812,18 @@ def getTypesFromDictionary(dictionary):
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
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
@ -839,6 +853,7 @@ def findCallbacksAndDictionaries(inputTypes):
doFindCallbacksAndDictionaries(inputTypes, retCallbacks, retDictionaries)
return (retCallbacks, retDictionaries)
def getAllTypes(descriptors, dictionaries, callbacks):
"""
Generate all the types we're dealing with. For each type, a tuple

View File

@ -46,12 +46,13 @@ for [name, prop, id, flags, pref] in propList:
extendedAttrs.append('BinaryName="%s"' % prop)
# Throw in a '_' before the attribute name, because some of these
# property names collide with IDL reserved words.
props += " [%s] attribute DOMString _%s;\n" % (", ".join(extendedAttrs),
name)
props += " [%s] attribute DOMString _%s;\n" % (
", ".join(extendedAttrs),
name)
idlFile = open(sys.argv[1], "r");
idlTemplate = idlFile.read();
idlFile.close();
idlFile = open(sys.argv[1], "r")
idlTemplate = idlFile.read()
idlFile.close()
print ("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n" +
string.Template(idlTemplate).substitute({ "props": props }))
string.Template(idlTemplate).substitute({"props": props}))

View File

@ -19,9 +19,9 @@ from mozbuild.base import MachCommandBase
@CommandProvider
class WebIDLProvider(MachCommandBase):
@Command('webidl-example', category='misc',
description='Generate example files for a WebIDL interface.')
description='Generate example files for a WebIDL interface.')
@CommandArgument('interface', nargs='+',
help='Interface(s) whose examples to generate.')
help='Interface(s) whose examples to generate.')
def webidl_example(self, interface):
from mozwebidlcodegen import BuildSystemWebIDL
@ -30,12 +30,12 @@ class WebIDLProvider(MachCommandBase):
manager.generate_example_files(i)
@Command('webidl-parser-test', category='testing',
description='Run WebIDL tests (Interface Browser parser).')
description='Run WebIDL tests (Interface Browser parser).')
@CommandArgument('--verbose', '-v', action='store_true',
help='Run tests in verbose mode.')
help='Run tests in verbose mode.')
def webidl_test(self, verbose=False):
sys.path.insert(0, os.path.join(self.topsrcdir, 'other-licenses',
'ply'))
'ply'))
# Make sure we drop our cached grammar bits in the objdir, not
# wherever we happen to be running from.
@ -45,7 +45,7 @@ class WebIDLProvider(MachCommandBase):
# objdir. But we're going to try loading it as a python
# module, so we need to make sure the objdir is in our search
# path.
sys.path.insert(0, self.topobjdir);
sys.path.insert(0, self.topobjdir)
from runtests import run_tests
return run_tests(None, verbose=verbose)

View File

@ -148,8 +148,8 @@ class WebIDLCodegenManager(LoggingMixin):
}
def __init__(self, config_path, inputs, exported_header_dir,
codegen_dir, state_path, cache_dir=None, make_deps_path=None,
make_deps_target=None):
codegen_dir, state_path, cache_dir=None, make_deps_path=None,
make_deps_target=None):
"""Create an instance that manages WebIDLs in the build system.
config_path refers to a WebIDL config file (e.g. Bindings.conf).
@ -176,7 +176,7 @@ class WebIDLCodegenManager(LoggingMixin):
self._input_paths = set(input_paths)
self._exported_stems = set(exported_stems)
self._generated_events_stems = set(generated_events_stems)
self._generated_events_stems_as_array = generated_events_stems;
self._generated_events_stems_as_array = generated_events_stems
self._example_interfaces = set(example_interfaces)
self._exported_header_dir = exported_header_dir
self._codegen_dir = codegen_dir
@ -185,10 +185,10 @@ class WebIDLCodegenManager(LoggingMixin):
self._make_deps_path = make_deps_path
self._make_deps_target = make_deps_target
if (make_deps_path and not make_deps_target) or (not make_deps_path and
make_deps_target):
if ((make_deps_path and not make_deps_target) or
(not make_deps_path and make_deps_target)):
raise Exception('Must define both make_deps_path and make_deps_target '
'if one is defined.')
'if one is defined.')
self._parser_results = None
self._config = None
@ -200,7 +200,7 @@ class WebIDLCodegenManager(LoggingMixin):
self._state = WebIDLCodegenManagerState(fh=fh)
except Exception as e:
self.log(logging.WARN, 'webidl_bad_state', {'msg': str(e)},
'Bad WebIDL state: {msg}')
'Bad WebIDL state: {msg}')
@property
def config(self):
@ -313,8 +313,8 @@ class WebIDLCodegenManager(LoggingMixin):
from Configuration import Configuration
self.log(logging.INFO, 'webidl_parse',
{'count': len(self._input_paths)},
'Parsing {count} WebIDL files.')
{'count': len(self._input_paths)},
'Parsing {count} WebIDL files.')
hashes = {}
parser = WebIDL.Parser(self._cache_dir)
@ -372,7 +372,7 @@ class WebIDLCodegenManager(LoggingMixin):
# Now we move on to the input files.
old_hashes = {v['filename']: v['sha1']
for v in self._state['webidls'].values()}
for v in self._state['webidls'].values()}
old_filenames = set(old_hashes.keys())
new_filenames = self._input_paths
@ -465,8 +465,8 @@ class WebIDLCodegenManager(LoggingMixin):
)
self.log(logging.INFO, 'webidl_generate_build_for_input',
{'filename': filename},
'Generating WebIDL files derived from {filename}')
{'filename': filename},
'Generating WebIDL files derived from {filename}')
stem, binding_stem, is_event, header_dir, files = self._binding_info(filename)
root = CGBindingRoot(self._config, binding_stem, filename)
@ -476,7 +476,7 @@ class WebIDLCodegenManager(LoggingMixin):
if is_event:
generated_event = CGEventRoot(self._config, stem)
result = self._maybe_write_codegen(generated_event, files[2],
files[3], result)
files[3], result)
return result, root.deps()
@ -544,7 +544,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir):
files = json.load(fh)
inputs = (files['webidls'], files['exported_stems'],
files['generated_events_stems'], files['example_interfaces'])
files['generated_events_stems'], files['example_interfaces'])
cache_dir = os.path.join(obj_dir, '_cache')
try:

View File

@ -42,7 +42,7 @@ class TestWebIDLCodegenManager(unittest.TestCase):
@property
def _static_input_paths(self):
s = {mozpath.join(OUR_DIR, p) for p in os.listdir(OUR_DIR)
if p.endswith('.webidl')}
if p.endswith('.webidl')}
return s
@ -98,7 +98,7 @@ class TestWebIDLCodegenManager(unittest.TestCase):
manager = WebIDLCodegenManager(**args)
self.assertEqual(manager._state['version'],
WebIDLCodegenManagerState.VERSION)
WebIDLCodegenManagerState.VERSION)
self.assertNotIn('foobar', manager._state)
def test_generate_build_files(self):

File diff suppressed because it is too large Load Diff

View File

@ -137,7 +137,10 @@ BluetoothManager::DisconnectFromOwner()
BluetoothAdapter*
BluetoothManager::GetDefaultAdapter()
{
return DefaultAdapterExists() ? mAdapters[mDefaultAdapterIndex] : nullptr;
if (!DefaultAdapterExists()) {
return nullptr;
}
return mAdapters[mDefaultAdapterIndex];
}
void

View File

@ -40,7 +40,11 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#if ANDROID_VERSION >= 21
#include <media/stagefright/MediaCodecSource.h>
#else
#include <media/stagefright/OMXCodec.h>
#endif
#include <media/MediaProfiles.h>
#include <utils/Errors.h>
@ -68,10 +72,21 @@ GonkRecorder::GonkRecorder()
GonkRecorder::~GonkRecorder() {
RE_LOGV("Destructor");
stop();
#if ANDROID_VERSION >= 21
if (mLooper != NULL) {
mLooper->stop();
}
#endif
}
status_t GonkRecorder::init() {
RE_LOGV("init");
#if ANDROID_VERSION >= 21
mLooper = new ALooper;
mLooper->setName("recorder_looper");
mLooper->start();
#endif
return OK;
}
@ -724,6 +739,71 @@ status_t GonkRecorder::start() {
return status;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
sp<MediaSource> GonkRecorder::createAudioSource() {
sp<AudioSource> audioSource =
new AudioSource(
mAudioSource,
mSampleRate,
mAudioChannels);
status_t err = audioSource->initCheck();
if (err != OK) {
RE_LOGE("audio source is not initialized");
return NULL;
}
sp<AMessage> format = new AMessage;
switch (mAudioEncoder) {
case AUDIO_ENCODER_AMR_NB:
case AUDIO_ENCODER_DEFAULT:
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
break;
case AUDIO_ENCODER_AMR_WB:
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
break;
case AUDIO_ENCODER_AAC:
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
break;
case AUDIO_ENCODER_HE_AAC:
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE);
break;
case AUDIO_ENCODER_AAC_ELD:
format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD);
break;
default:
RE_LOGE("Unknown audio encoder: %d", mAudioEncoder);
return NULL;
}
int32_t maxInputSize;
CHECK(audioSource->getFormat()->findInt32(
kKeyMaxInputSize, &maxInputSize));
format->setInt32("max-input-size", maxInputSize);
format->setInt32("channel-count", mAudioChannels);
format->setInt32("sample-rate", mSampleRate);
format->setInt32("bitrate", mAudioBitRate);
if (mAudioTimeScale > 0) {
format->setInt32("time-scale", mAudioTimeScale);
}
sp<MediaSource> audioEncoder =
MediaCodecSource::Create(mLooper, format, audioSource);
mAudioSourceNode = audioSource;
if (audioEncoder == NULL) {
RE_LOGE("Failed to create audio encoder");
}
return audioEncoder;
}
#else
sp<MediaSource> GonkRecorder::createAudioSource() {
sp<AudioSource> audioSource =
new AudioSource(
@ -792,6 +872,7 @@ sp<MediaSource> GonkRecorder::createAudioSource() {
return audioEncoder;
}
#endif
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
status_t GonkRecorder::startAACRecording() {
@ -1213,6 +1294,87 @@ status_t GonkRecorder::setupCameraSource(
return OK;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
status_t GonkRecorder::setupVideoEncoder(
sp<MediaSource> cameraSource,
int32_t videoBitRate,
sp<MediaSource> *source) {
source->clear();
sp<AMessage> format = new AMessage();
switch (mVideoEncoder) {
case VIDEO_ENCODER_H263:
format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
break;
case VIDEO_ENCODER_MPEG_4_SP:
format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
break;
case VIDEO_ENCODER_H264:
format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
break;
case VIDEO_ENCODER_VP8:
format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
break;
default:
CHECK(!"Should not be here, unsupported video encoding.");
break;
}
sp<MetaData> meta = cameraSource->getFormat();
int32_t width, height, stride, sliceHeight, colorFormat;
CHECK(meta->findInt32(kKeyWidth, &width));
CHECK(meta->findInt32(kKeyHeight, &height));
CHECK(meta->findInt32(kKeyStride, &stride));
CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
format->setInt32("width", width);
format->setInt32("height", height);
format->setInt32("stride", stride);
format->setInt32("slice-height", sliceHeight);
format->setInt32("color-format", colorFormat);
format->setInt32("bitrate", videoBitRate);
format->setInt32("frame-rate", mFrameRate);
format->setInt32("i-frame-interval", mIFramesIntervalSec);
if (mVideoTimeScale > 0) {
format->setInt32("time-scale", mVideoTimeScale);
}
if (mVideoEncoderProfile != -1) {
format->setInt32("profile", mVideoEncoderProfile);
}
if (mVideoEncoderLevel != -1) {
format->setInt32("level", mVideoEncoderLevel);
}
uint32_t flags = 0;
if (mIsMetaDataStoredInVideoBuffers) {
flags |= MediaCodecSource::FLAG_USE_METADATA_INPUT;
}
sp<MediaCodecSource> encoder =
MediaCodecSource::Create(mLooper, format, cameraSource, flags);
if (encoder == NULL) {
RE_LOGE("Failed to create video encoder");
// When the encoder fails to be created, we need
// release the camera source due to the camera's lock
// and unlock mechanism.
cameraSource->stop();
return UNKNOWN_ERROR;
}
*source = encoder;
return OK;
}
#else
status_t GonkRecorder::setupVideoEncoder(
sp<MediaSource> cameraSource,
int32_t videoBitRate,
@ -1301,6 +1463,7 @@ status_t GonkRecorder::setupVideoEncoder(
return OK;
}
#endif
status_t GonkRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
status_t status = BAD_VALUE;

View File

@ -24,6 +24,10 @@
#include <camera/CameraParameters.h>
#include <utils/String8.h>
#include <system/audio.h>
#if ANDROID_VERSION >= 21
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#endif
#include "mozilla/RefPtr.h"
#include "GonkCameraHwMgr.h"
@ -111,10 +115,10 @@ private:
MediaProfiles *mEncoderProfiles;
bool mStarted;
// Needed when GLFrames are encoded.
// An <IGraphicBufferProducer> pointer
// will be sent to the client side using which the
// frame buffers will be queued and dequeued
#if ANDROID_VERSION >= 21
sp<ALooper> mLooper;
#endif
sp<GonkCameraHardware> mCameraHw;

View File

@ -89,7 +89,10 @@ public:
PaintRequest* IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mArray.Length();
return aFound ? mArray.ElementAt(aIndex) : nullptr;
if (!aFound) {
return nullptr;
}
return mArray.ElementAt(aIndex);
}
private:

View File

@ -689,7 +689,10 @@ TextComposition*
TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
{
index_type i = IndexOf(aWidget);
return i != NoIndex ? ElementAt(i) : nullptr;
if (i == NoIndex) {
return nullptr;
}
return ElementAt(i);
}
TextComposition*
@ -697,7 +700,10 @@ TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
nsINode* aNode)
{
index_type i = IndexOf(aPresContext, aNode);
return i != NoIndex ? ElementAt(i) : nullptr;
if (i == NoIndex) {
return nullptr;
}
return ElementAt(i);
}
TextComposition*

View File

@ -345,7 +345,7 @@ MP3TrackDemuxer::GetEvictionOffset(TimeUnit aTime) {
int64_t
MP3TrackDemuxer::StreamLength() const {
return mSource->GetLength();
return mSource.GetLength();
}
TimeUnit
@ -525,8 +525,8 @@ MP3TrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize) {
uint32_t read = 0;
MP3DEMUXER_LOGV("MP3TrackDemuxer::Read -> ReadAt(%d)", aSize);
const nsresult rv = mSource->ReadAt(aOffset, reinterpret_cast<char*>(aBuffer),
static_cast<uint32_t>(aSize), &read);
const nsresult rv = mSource.ReadAt(aOffset, reinterpret_cast<char*>(aBuffer),
static_cast<uint32_t>(aSize), &read);
NS_ENSURE_SUCCESS(rv, 0);
return static_cast<int32_t>(read);
}

View File

@ -377,7 +377,7 @@ private:
double AverageFrameLength() const;
// The (hopefully) MPEG resource.
nsRefPtr<MediaResource> mSource;
MediaResourceIndex mSource;
// MPEG frame parser used to detect frames and extract side info.
FrameParser mParser;

View File

@ -532,7 +532,7 @@ nsresult MediaDecoder::InitializeStateMachine(MediaDecoder* aCloneDonor)
MediaDecoder* cloneDonor = static_cast<MediaDecoder*>(aCloneDonor);
nsresult rv = mDecoderStateMachine->Init(
cloneDonor ? cloneDonor->mDecoderStateMachine : nullptr);
cloneDonor ? cloneDonor->mDecoderStateMachine.get() : nullptr);
NS_ENSURE_SUCCESS(rv, rv);
// If some parameters got set before the state machine got created,

View File

@ -674,7 +674,7 @@ MediaDecoderStateMachine::PushFront(VideoData* aSample)
}
void
MediaDecoderStateMachine::OnAudioPopped(const MediaData* aSample)
MediaDecoderStateMachine::OnAudioPopped(const nsRefPtr<MediaData>& aSample)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@ -684,7 +684,7 @@ MediaDecoderStateMachine::OnAudioPopped(const MediaData* aSample)
}
void
MediaDecoderStateMachine::OnVideoPopped(const MediaData* aSample)
MediaDecoderStateMachine::OnVideoPopped(const nsRefPtr<MediaData>& aSample)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());

View File

@ -399,8 +399,8 @@ protected:
void PushFront(AudioData* aSample);
void PushFront(VideoData* aSample);
void OnAudioPopped(const MediaData* aSample);
void OnVideoPopped(const MediaData* aSample);
void OnAudioPopped(const nsRefPtr<MediaData>& aSample);
void OnVideoPopped(const nsRefPtr<MediaData>& aSample);
void VolumeChanged();
void LogicalPlaybackRateChanged();

View File

@ -2849,8 +2849,8 @@ GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aID, bool aIsAudio)
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_STOP_TRACK,
this, nullptr, nullptr,
aIsAudio ? mAudioSource : nullptr,
!aIsAudio ? mVideoSource : nullptr,
aIsAudio ? mAudioSource.get() : nullptr,
!aIsAudio ? mVideoSource.get() : nullptr,
mFinished, mWindowID, nullptr));
} else {
LOG(("gUM track %d ended, but we don't have type %s",

View File

@ -74,7 +74,10 @@ MediaTrack*
MediaTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mTracks.Length();
return aFound ? mTracks[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mTracks[aIndex];
}
MediaTrack*

View File

@ -814,6 +814,12 @@ public:
MozPromiseRequestHolder() {}
~MozPromiseRequestHolder() { MOZ_ASSERT(!mRequest); }
void Begin(nsRefPtr<typename PromiseType::Request>&& aRequest)
{
MOZ_DIAGNOSTIC_ASSERT(!Exists());
mRequest = Move(aRequest);
}
void Begin(typename PromiseType::Request* aRequest)
{
MOZ_DIAGNOSTIC_ASSERT(!Exists());

View File

@ -50,7 +50,10 @@ TextTrackCue*
TextTrackCueList::IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mList.Length();
return aFound ? mList[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mList[aIndex];
}
TextTrackCue*

View File

@ -69,7 +69,10 @@ TextTrack*
TextTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mTextTracks.Length();
return aFound ? mTextTracks[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mTextTracks[aIndex];
}
TextTrack*

View File

@ -38,7 +38,11 @@ SourceBufferList::IndexedGetter(uint32_t aIndex, bool& aFound)
{
MOZ_ASSERT(NS_IsMainThread());
aFound = aIndex < mSourceBuffers.Length();
return aFound ? mSourceBuffers[aIndex] : nullptr;
if (!aFound) {
return nullptr;
}
return mSourceBuffers[aIndex];
}
uint32_t

View File

@ -276,7 +276,7 @@ void
AppleVDADecoder::DrainReorderedFrames()
{
while (!mReorderQueue.IsEmpty()) {
mCallback->Output(mReorderQueue.Pop());
mCallback->Output(mReorderQueue.Pop().get());
}
}
@ -406,7 +406,7 @@ AppleVDADecoder::OutputFrame(CFRefPtr<CVPixelBufferRef> aImage,
// in composition order.
mReorderQueue.Push(data);
while (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop());
mCallback->Output(mReorderQueue.Pop().get());
}
LOG("%llu decoded frames queued",
static_cast<unsigned long long>(mReorderQueue.Length()));

View File

@ -1709,13 +1709,18 @@ PeerConnectionWrapper.prototype = {
rId = stats[name].remoteCandidateId;
}
});
info("checkStatsIceConnectionType verifying: local=" +
JSON.stringify(stats[lId]) + " remote=" + JSON.stringify(stats[rId]));
ok(typeof lId !== 'undefined', "Got local candidate ID " +
JSON.stringify(lId) + " for selected pair");
ok(typeof rId !== 'undefined', "Got remote candidate ID " +
JSON.stringify(rId) + " for selected pair");
if ((typeof stats[lId] === 'undefined') ||
(typeof stats[rId] === 'undefined')) {
info("checkStatsIceConnectionType failed to find candidatepair IDs");
ok(false, "failed to find candidatepair IDs or stats for local: " +
JSON.stringify(lId) + " remote: " + JSON.stringify(rId));
return;
}
info("checkStatsIceConnectionType verifying: local=" +
JSON.stringify(stats[lId]) + " remote=" + JSON.stringify(stats[rId]));
var lType = stats[lId].candidateType;
var rType = stats[rId].candidateType;
var lIp = stats[lId].ipAddress;
@ -1754,6 +1759,7 @@ PeerConnectionWrapper.prototype = {
}
});
info("ICE connections according to stats: " + numIceConnections);
isnot(numIceConnections, 0, "Number of ICE connections according to stats is not zero");
if (answer.sdp.includes('a=group:BUNDLE')) {
is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
} else {

View File

@ -461,25 +461,25 @@ var commandsPeerConnectionOfferAnswer = [
},
function PC_REMOTE_CHECK_STATS(test) {
test.pcRemote.getStats().then(stats => {
return test.pcRemote.getStats().then(stats => {
test.pcRemote.checkStats(stats, test.steeplechase);
});
},
function PC_LOCAL_CHECK_ICE_CONNECTION_TYPE(test) {
test.pcLocal.getStats().then(stats => {
return test.pcLocal.getStats().then(stats => {
test.pcLocal.checkStatsIceConnectionType(stats);
});
},
function PC_REMOTE_CHECK_ICE_CONNECTION_TYPE(test) {
test.pcRemote.getStats().then(stats => {
return test.pcRemote.getStats().then(stats => {
test.pcRemote.checkStatsIceConnectionType(stats);
});
},
function PC_LOCAL_CHECK_ICE_CONNECTIONS(test) {
test.pcLocal.getStats().then(stats => {
return test.pcLocal.getStats().then(stats => {
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
@ -488,7 +488,7 @@ var commandsPeerConnectionOfferAnswer = [
},
function PC_REMOTE_CHECK_ICE_CONNECTIONS(test) {
test.pcRemote.getStats().then(stats => {
return test.pcRemote.getStats().then(stats => {
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,

View File

@ -88,10 +88,10 @@ class WebMPacketQueue {
mQueue.push_front(Move(aItem));
}
nsRefPtr<NesteggPacketHolder> PopFront() {
already_AddRefed<NesteggPacketHolder> PopFront() {
nsRefPtr<NesteggPacketHolder> result = mQueue.front();
mQueue.pop_front();
return result;
return result.forget();
}
void Reset() {

View File

@ -880,7 +880,8 @@ WebMTrackDemuxer::SetNextKeyFrameTime()
skipSamplesQueue.PushFront(sample);
}
while(skipSamplesQueue.GetSize()) {
mSamples.PushFront(skipSamplesQueue.PopFront());
nsRefPtr<MediaRawData> data = skipSamplesQueue.PopFront();
mSamples.PushFront(data);
}
if (frameTime == -1) {
frameTime = mParent->GetNextKeyframeTime();

View File

@ -32,10 +32,10 @@ class MediaRawDataQueue {
mQueue.push_front(aItem);
}
nsRefPtr<MediaRawData> PopFront() {
already_AddRefed<MediaRawData> PopFront() {
nsRefPtr<MediaRawData> result = mQueue.front();
mQueue.pop_front();
return result;
return result.forget();
}
void Reset() {

View File

@ -670,7 +670,8 @@ int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
// Restore the packets before we return -1.
uint32_t size = skipPacketQueue.GetSize();
for (uint32_t i = 0; i < size; ++i) {
PushVideoPacket(skipPacketQueue.PopFront());
nsRefPtr<NesteggPacketHolder> packetHolder = skipPacketQueue.PopFront();
PushVideoPacket(packetHolder);
}
return -1;
}
@ -694,7 +695,8 @@ int64_t WebMReader::GetNextKeyframeTime(int64_t aTimeThreshold)
uint32_t size = skipPacketQueue.GetSize();
for (uint32_t i = 0; i < size; ++i) {
PushVideoPacket(skipPacketQueue.PopFront());
nsRefPtr<NesteggPacketHolder> packetHolder = skipPacketQueue.PopFront();
PushVideoPacket(packetHolder);
}
return keyframeTime;

View File

@ -41,7 +41,7 @@ PluginScriptableObjectChild::IdentifierTable PluginScriptableObjectChild::sIdent
/* static */ PluginScriptableObjectChild::StoredIdentifier*
PluginScriptableObjectChild::HashIdentifier(const nsCString& aIdentifier)
{
StoredIdentifier* stored = sIdentifiers.Get(aIdentifier);
StoredIdentifier* stored = sIdentifiers.Get(aIdentifier).get();
if (stored) {
return stored;
}

View File

@ -48,7 +48,8 @@ SVGAngle::SetValue(float aValue, ErrorResult& rv)
return;
}
bool isBaseVal = mType == BaseValue;
mVal->SetBaseValue(aValue, isBaseVal ? mSVGElement : nullptr, isBaseVal);
mVal->SetBaseValue(aValue, isBaseVal ? mSVGElement.get() : nullptr,
isBaseVal);
}
float
@ -83,7 +84,8 @@ SVGAngle::NewValueSpecifiedUnits(uint16_t unitType,
return;
}
rv = mVal->NewValueSpecifiedUnits(unitType, valueInSpecifiedUnits,
mType == BaseValue ? mSVGElement : nullptr);
mType == BaseValue ? mSVGElement.get()
: nullptr);
}
void
@ -93,7 +95,8 @@ SVGAngle::ConvertToSpecifiedUnits(uint16_t unitType, ErrorResult& rv)
rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}
rv = mVal->ConvertToSpecifiedUnits(unitType, mType == BaseValue ? mSVGElement : nullptr);
rv = mVal->ConvertToSpecifiedUnits(unitType, mType == BaseValue ?
mSVGElement.get() : nullptr);
}
void
@ -104,7 +107,8 @@ SVGAngle::SetValueAsString(const nsAString& aValue, ErrorResult& rv)
return;
}
bool isBaseVal = mType == BaseValue;
rv = mVal->SetBaseValueString(aValue, isBaseVal ? mSVGElement : nullptr, isBaseVal);
rv = mVal->SetBaseValueString(aValue, isBaseVal ? mSVGElement.get() : nullptr,
isBaseVal);
}
void

View File

@ -880,8 +880,8 @@ nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
mBaseTag = do_GetAtom(baseTag);
}
aDocument->CreateElem(NS_LITERAL_STRING("binding"), nullptr, kNameSpaceID_XBL,
getter_AddRefs(mBinding));
mBinding = aDocument->CreateElem(NS_LITERAL_STRING("binding"), nullptr,
kNameSpaceID_XBL);
nsCOMPtr<nsIContent> child;
rv = ReadContentNode(aStream, aDocument, aDocument->NodeInfoManager(), getter_AddRefs(child));

View File

@ -125,15 +125,13 @@ createAndAddToResult(nsIAtom* aName, const nsSubstring& aValue,
"invalid result-holder");
nsIDocument* doc = aResultHolder->OwnerDoc();
nsCOMPtr<nsIContent> elem;
nsresult rv = doc->CreateElem(nsDependentAtomString(aName),
nullptr, kNameSpaceID_None,
getter_AddRefs(elem));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> elem = doc->CreateElem(nsDependentAtomString(aName),
nullptr, kNameSpaceID_None);
NS_ENSURE_TRUE(elem, NS_ERROR_NULL_POINTER);
nsRefPtr<nsTextNode> text = new nsTextNode(doc->NodeInfoManager());
rv = text->SetText(aValue, false);
nsresult rv = text->SetText(aValue, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = elem->AppendChildTo(text, false);

View File

@ -175,10 +175,9 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
RegisterNameSpace(NS_LITERAL_STRING(kTXNameSpaceURI), namespaceID);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
nsGkAtoms::transformiix, namespaceID,
getter_AddRefs(mTextParent));
NS_ENSURE_SUCCESS(rv, rv);
mTextParent =
mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
nsGkAtoms::transformiix, namespaceID);
rv = mDocument->AppendChildTo(mTextParent, true);

View File

@ -619,11 +619,9 @@ txMozillaXMLOutput::createTxWrapper()
RegisterNameSpace(NS_LITERAL_STRING(kTXNameSpaceURI), namespaceID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> wrapper;
rv = mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
nsGkAtoms::transformiix, namespaceID,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> wrapper =
mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
nsGkAtoms::transformiix, namespaceID);
uint32_t i, j, childCount = mDocument->GetChildCount();
#ifdef DEBUG

View File

@ -3719,11 +3719,9 @@ XULDocument::CreateTemplateBuilder(nsIContent* aElement)
getter_AddRefs(bodyContent));
if (! bodyContent) {
nsresult rv =
bodyContent =
document->CreateElem(nsDependentAtomString(nsGkAtoms::treechildren),
nullptr, kNameSpaceID_XUL,
getter_AddRefs(bodyContent));
NS_ENSURE_SUCCESS(rv, rv);
nullptr, kNameSpaceID_XUL);
aElement->AppendChildTo(bodyContent, false);
}

View File

@ -4652,11 +4652,8 @@ nsEditor::CreateHTMLContent(nsIAtom* aTag)
return nullptr;
}
nsCOMPtr<nsIContent> ret;
nsresult res = doc->CreateElem(nsDependentAtomString(aTag), nullptr,
kNameSpaceID_XHTML, getter_AddRefs(ret));
NS_ENSURE_SUCCESS(res, nullptr);
return dont_AddRef(ret.forget().take()->AsElement());
return doc->CreateElem(nsDependentAtomString(aTag), nullptr,
kNameSpaceID_XHTML);
}
nsresult

View File

@ -24,6 +24,11 @@
#include "GLLibraryEGL.h"
#endif
#ifdef XP_MACOSX
#include "MacIOSurfaceImage.h"
#include "GLContextCGL.h"
#endif
using mozilla::layers::PlanarYCbCrImage;
using mozilla::layers::PlanarYCbCrData;
@ -155,8 +160,10 @@ GLBlitHelper::GLBlitHelper(GLContext* gl)
, mTextureTransformLoc(-1)
, mTexExternalBlit_FragShader(0)
, mTexYUVPlanarBlit_FragShader(0)
, mTexNV12PlanarBlit_FragShader(0)
, mTexExternalBlit_Program(0)
, mTexYUVPlanarBlit_Program(0)
, mTexNV12PlanarBlit_Program(0)
, mFBO(0)
, mSrcTexY(0)
, mSrcTexCb(0)
@ -301,6 +308,33 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
} \n\
";
#ifdef XP_MACOSX
const char kTexNV12PlanarBlit_FragShaderSource[] = "\
#extension GL_ARB_texture_rectangle : require \n\
#ifdef GL_ES \n\
precision mediump float \n\
#endif \n\
varying vec2 vTexCoord; \n\
uniform sampler2DRect uYTexture; \n\
uniform sampler2DRect uCbCrTexture; \n\
uniform vec2 uYTexScale; \n\
uniform vec2 uCbCrTexScale; \n\
void main() \n\
{ \n\
float y = texture2DRect(uYTexture, vTexCoord * uYTexScale).r; \n\
float cb = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).r; \n\
float cr = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).a; \n\
y = (y - 0.06275) * 1.16438; \n\
cb = cb - 0.50196; \n\
cr = cr - 0.50196; \n\
gl_FragColor.r = y + cr * 1.59603; \n\
gl_FragColor.g = y - 0.81297 * cr - 0.39176 * cb; \n\
gl_FragColor.b = y + cb * 2.01723; \n\
gl_FragColor.a = 1.0; \n\
} \n\
";
#endif
bool success = false;
GLuint *programPtr;
@ -331,6 +365,13 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
fragShaderPtr = &mTexYUVPlanarBlit_FragShader;
fragShaderSource = kTexYUVPlanarBlit_FragShaderSource;
break;
#ifdef XP_MACOSX
case ConvertMacIOSurfaceImage:
programPtr = &mTexNV12PlanarBlit_Program;
fragShaderPtr = &mTexNV12PlanarBlit_FragShader;
fragShaderSource = kTexNV12PlanarBlit_FragShaderSource;
break;
#endif
default:
return false;
}
@ -483,6 +524,24 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
mGL->fUniform1i(texCr, Channel_Cr);
break;
}
case ConvertMacIOSurfaceImage: {
#ifdef XP_MACOSX
GLint texY = mGL->fGetUniformLocation(program, "uYTexture");
GLint texCbCr = mGL->fGetUniformLocation(program, "uCbCrTexture");
mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale");
mCbCrTexScaleLoc= mGL->fGetUniformLocation(program, "uCbCrTexScale");
DebugOnly<bool> hasUniformLocations = texY != -1 &&
texCbCr != -1 &&
mYTexScaleLoc != -1 &&
mCbCrTexScaleLoc != -1;
MOZ_ASSERT(hasUniformLocations, "uniforms not found");
mGL->fUniform1i(texY, Channel_Y);
mGL->fUniform1i(texCbCr, Channel_Cb);
#endif
break;
}
}
MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0);
mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip");
@ -565,6 +624,10 @@ GLBlitHelper::DeleteTexBlitProgram()
mGL->fDeleteShader(mTexYUVPlanarBlit_FragShader);
mTexYUVPlanarBlit_FragShader = 0;
}
if (mTexNV12PlanarBlit_FragShader) {
mGL->fDeleteShader(mTexNV12PlanarBlit_FragShader);
mTexNV12PlanarBlit_FragShader = 0;
}
if (mTexExternalBlit_Program) {
mGL->fDeleteProgram(mTexExternalBlit_Program);
mTexExternalBlit_Program = 0;
@ -573,6 +636,10 @@ GLBlitHelper::DeleteTexBlitProgram()
mGL->fDeleteProgram(mTexYUVPlanarBlit_Program);
mTexYUVPlanarBlit_Program = 0;
}
if (mTexNV12PlanarBlit_Program) {
mGL->fDeleteProgram(mTexNV12PlanarBlit_Program);
mTexNV12PlanarBlit_Program = 0;
}
}
void
@ -816,6 +883,47 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage)
return true;
}
#ifdef XP_MACOSX
bool
GLBlitHelper::BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage)
{
ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
MacIOSurface* surf = ioImage->GetSurface();
GLint oldTex[2];
for (int i = 0; i < 2; i++) {
mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]);
}
GLuint textures[2];
mGL->fGenTextures(2, textures);
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[0]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 0);
mGL->fUniform2f(mYTexScaleLoc, surf->GetWidth(0), surf->GetHeight(0));
mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[1]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 1);
mGL->fUniform2f(mCbCrTexScaleLoc, surf->GetWidth(1), surf->GetHeight(1));
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
for (int i = 0; i < 2; i++) {
mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]);
}
mGL->fDeleteTextures(2, textures);
return true;
}
#endif
bool
GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
const gfx::IntSize& destSize,
@ -852,6 +960,12 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
srcOrigin = static_cast<layers::EGLImageImage*>(srcImage)->GetData()->mOriginPos;
break;
#endif
#ifdef XP_MACOSX
case ImageFormat::MAC_IOSURFACE:
type = ConvertMacIOSurfaceImage;
srcOrigin = OriginPos::TopLeft;
break;
#endif
default:
return false;
@ -887,6 +1001,11 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
return BlitEGLImageImage(static_cast<layers::EGLImageImage*>(srcImage));
#endif
#ifdef XP_MACOSX
case ConvertMacIOSurfaceImage:
return BlitMacIOSurfaceImage(static_cast<layers::MacIOSurfaceImage*>(srcImage));
#endif
default:
return false;
}

View File

@ -20,6 +20,7 @@ class Image;
class PlanarYCbCrImage;
class GrallocImage;
class SurfaceTextureImage;
class MacIOSurfaceImage;
class EGLImageImage;
} // namespace layers
@ -100,7 +101,8 @@ class GLBlitHelper final
ConvertGralloc,
ConvertPlanarYCbCr,
ConvertSurfaceTexture,
ConvertEGLImage
ConvertEGLImage,
ConvertMacIOSurfaceImage
};
// The GLContext is the sole owner of the GLBlitHelper.
GLContext* mGL;
@ -119,8 +121,10 @@ class GLBlitHelper final
// Data for image blit path
GLuint mTexExternalBlit_FragShader;
GLuint mTexYUVPlanarBlit_FragShader;
GLuint mTexNV12PlanarBlit_FragShader;
GLuint mTexExternalBlit_Program;
GLuint mTexYUVPlanarBlit_Program;
GLuint mTexNV12PlanarBlit_Program;
GLuint mFBO;
GLuint mSrcTexY;
GLuint mSrcTexCb;
@ -153,6 +157,9 @@ class GLBlitHelper final
bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage);
bool BlitEGLImageImage(layers::EGLImageImage* eglImage);
#endif
#ifdef XP_MACOSX
bool BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage);
#endif
explicit GLBlitHelper(GLContext* gl);

View File

@ -131,7 +131,10 @@ TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
TextureHost*
TextureHost::AsTextureHost(PTextureParent* actor)
{
return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
if (!actor) {
return nullptr;
}
return static_cast<TextureParent*>(actor)->mTextureHost;
}
PTextureParent*

View File

@ -2985,7 +2985,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
convertedString,
true,
mStyle.explicitLanguage
? mStyle.language : nullptr,
? mStyle.language.get() : nullptr,
charsToMergeArray,
deletedCharsArray);

View File

@ -226,6 +226,15 @@ function ArrayForEach(callbackfn/*, thisArg*/) {
return void 0;
}
function ArrayStaticForEach(list, callbackfn/*, thisArg*/) {
if (arguments.length < 2)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach');
if (!IsCallable(callbackfn))
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
var T = arguments.length > 2 ? arguments[2] : void 0;
callFunction(ArrayForEach, list, callbackfn, T);
}
/* ES5 15.4.4.19. */
function ArrayMap(callbackfn/*, thisArg*/) {
/* Step 1. */
@ -270,13 +279,52 @@ function ArrayStaticMap(list, callbackfn/*, thisArg*/) {
return callFunction(ArrayMap, list, callbackfn, T);
}
function ArrayStaticForEach(list, callbackfn/*, thisArg*/) {
/* ES2015 22.1.3.7 Array.prototype.filter. */
function ArrayFilter(callbackfn/*, thisArg*/) {
/* Steps 1-2. */
var O = ToObject(this);
/* Steps 3-4. */
var len = ToInteger(O.length);
/* Step 5. */
if (arguments.length === 0)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.filter');
if (!IsCallable(callbackfn))
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
/* Step 6. */
var T = arguments.length > 1 ? arguments[1] : void 0;
/* Step 7. */
var A = [];
/* Steps 8-11. */
/* Steps 11.a (implicit), and 11.e. */
for (var k = 0, to = 0; k < len; k++) {
/* Steps 11.b-c. */
if (k in O) {
/* Steps 11.c.i-ii. */
var kValue = O[k];
/* Steps 11.c.iii-iv. */
var selected = callFunction(callbackfn, T, kValue, k, O);
/* Step 11.c.v. */
if (selected)
_DefineDataProperty(A, to++, kValue);
}
}
/* Step 12. */
return A;
}
function ArrayStaticFilter(list, callbackfn/*, thisArg*/) {
if (arguments.length < 2)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach');
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.filter');
if (!IsCallable(callbackfn))
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
var T = arguments.length > 2 ? arguments[2] : void 0;
callFunction(ArrayForEach, list, callbackfn, T);
return callFunction(ArrayFilter, list, callbackfn, T);
}
/* ES5 15.4.4.21. */
@ -793,3 +841,111 @@ function ArrayToString() {
return callFunction(std_Object_toString, array);
return callFunction(func, array);
}
//ES 2015, 22.1.3.25 Array.prototype.splice.
function ArraySplice(start, deleteCount /*, ...items */) {
// Steps 1-2.
var O = ToObject(this);
// Steps 3-4.
// FIXME: Array operations should use ToLength (bug 924058).
var len = ToInteger(O.length);
// Steps 5-6.
var relativeStart = ToInteger(start);
// Step 7.
var actualStart = relativeStart < 0
? std_Math_max(len + relativeStart, 0)
: std_Math_min(relativeStart, len);
// Steps 8-10.
var insertCount = 0;
var actualDeleteCount = 0;
var numArgs = arguments.length;
if (numArgs === 1) {
actualDeleteCount = len - actualStart;
} else if (numArgs > 1) {
// Step 10.a.
insertCount = numArgs - 2;
// Steps 10.b-c.
var dc = ToInteger(deleteCount);
// Step 10.d.
actualDeleteCount = std_Math_min(std_Math_max(dc, 0), len - actualStart);
}
// Step 11.
if (len + insertCount - actualDeleteCount > 2 ** 53 - 1)
ThrowTypeError(JSMSG_BAD_ARRAY_LENGTH_SPLICE);
// Steps 12-13.
// FIXME: Use ArraySpeciesCreate here.
var A = NewDenseArray(actualDeleteCount);
// Steps 14-15.
for (var k = 0; k < actualDeleteCount; k++) {
// Step 15.a.
var from = actualStart + k;
// Steps 15.b-d.
if (from in O)
_DefineDataProperty(A, k, O[from]);
}
// Steps 16-17.
A.length = actualDeleteCount;
// Step 18 (implicit).
// Step 19.
var itemCount = insertCount;
// Step 20.
if (itemCount < actualDeleteCount) {
// Steps 20.a-b.
for (var k = actualStart, kMax = len - actualDeleteCount; k < kMax; k++) {
// Step 20.b.i.
var from = k + actualDeleteCount;
// Step 20.b.ii.
var to = k + itemCount;
// Steps 20.b.iii-v.
if (from in O) {
O[to] = O[from];
} else {
// Step 20.b.vi.
delete O[to];
}
}
// Steps 20.c-d.
// For packed arrays we can skip these steps: the fact that we don't
// delete the elements one by one isn't visible to content code.
if (!IsPackedArray(O)) {
for (var k = len, kMin = len - actualDeleteCount + itemCount; k > kMin; k--)
delete O[k - 1];
}
} else if (itemCount > actualDeleteCount) {
// Step 21.
// Steps 21 a-b.
for (var k = len - actualDeleteCount, kMin = actualStart; k > kMin; k--) {
// Step 21.b.i.
var from = k + actualDeleteCount - 1;
// Step 21.b.ii.
var to = k + itemCount - 1;
// Steps 21.b.iii-v.
if (from in O) {
O[to] = O[from];
} else {
// Step 21.b.vi.
delete O[to];
}
}
}
// Steps 22-23.
for (var k = actualStart, itemIndex = 2; itemIndex < numArgs; k++, itemIndex++)
O[k] = arguments[itemIndex];
// Steps 24-25.
O.length = len - actualDeleteCount + itemCount;
// Step 26.
return A;
}

View File

@ -70,8 +70,8 @@ function Number_isSafeInteger(number) {
if (integer !== number)
return false;
// Step 5. If abs(integer) <= 2**53 - 1, return true.
if (std_Math_abs(integer) <= 9007199254740991)
// Step 5.
if (std_Math_abs(integer) <= 2 ** 53 - 1)
return true;
// Step 6.

View File

@ -917,6 +917,25 @@ SaveStack(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
CallFunctionFromNativeFrame(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1) {
JS_ReportError(cx, "The function takes exactly one argument.");
return false;
}
if (!args[0].isObject() || !IsCallable(args[0])) {
JS_ReportError(cx, "The first argument should be a function.");
return false;
}
RootedObject function(cx, &args[0].toObject());
return Call(cx, UndefinedHandleValue, function,
JS::HandleValueArray::empty(), args.rval());
}
static bool
CallFunctionWithAsyncStack(JSContext* cx, unsigned argc, Value* vp)
{
@ -2728,6 +2747,11 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
" of frames. If 'compartment' is given, allocate the js::SavedFrame instances\n"
" with the given object's compartment."),
JS_FN_HELP("callFunctionFromNativeFrame", CallFunctionFromNativeFrame, 1, 0,
"callFunctionFromNativeFrame(function)",
" Call 'function' with a (C++-)native frame on stack.\n"
" Required for testing that SaveStack properly handles native frames."),
JS_FN_HELP("callFunctionWithAsyncStack", CallFunctionWithAsyncStack, 0, 0,
"callFunctionWithAsyncStack(function, stack, asyncCause)",
" Call 'function', using the provided stack as the async stack responsible\n"

View File

@ -110,8 +110,7 @@ function ToLength(v) {
if (v <= 0)
return 0;
// Math.pow(2, 53) - 1 = 0x1fffffffffffff
return std_Math_min(v, 0x1fffffffffffff);
return std_Math_min(v, 2 ** 53 - 1);
}
/* Spec: ECMAScript Draft, 6th edition Oct 14, 2014, 7.2.4 */

View File

@ -0,0 +1,5 @@
const dbg = new Debugger();
const g = evalcx("lazy");
dbg.addDebuggee(g);
dbg.memory.trackingAllocationSites = true;
g.eval("this.alloc = {}");

View File

@ -245,6 +245,38 @@ function refuseAbs() {
}
test(refuseAbs);
function acceptFilterTypeSet() {
var res = f32[0];
if (!res) {
} else {
f32[0] = res;
assertFloat32(res, true);
}
}
test(acceptFilterTypeSet);
function acceptFilterTypeSet2() {
var res = f32[0];
if (!res) {
} else {
var res1 = Math.abs(res);
f32[0] = res1;
assertFloat32(res1, true);
}
}
test(acceptFilterTypeSet2);
function refuseFilterTypeSet() {
var res = f32[0];
if (!res) {
} else {
var res1 = Math.abs(res);
f64[0] = res1 + 1;
assertFloat32(res1, false);
}
}
test(refuseFilterTypeSet);
function refuseTrigo() {
var res = Math.cos(f32[0]);
f32[0] = res;

View File

@ -3,7 +3,7 @@
// Unlike Array.prototype.map, Array.prototype.filter is not self-hosted.
const filter = (function iife() {
try {
[3].filter(n => { throw saveStack() });
callFunctionFromNativeFrame(n => { throw saveStack() });
} catch (s) {
return s;
}

View File

@ -3438,18 +3438,6 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric* apply)
emitPopArguments(apply, extraStackSpace);
}
typedef bool (*ArraySpliceDenseFn)(JSContext*, HandleObject, uint32_t, uint32_t);
static const VMFunction ArraySpliceDenseInfo = FunctionInfo<ArraySpliceDenseFn>(ArraySpliceDense);
void
CodeGenerator::visitArraySplice(LArraySplice* lir)
{
pushArg(ToRegister(lir->getDeleteCount()));
pushArg(ToRegister(lir->getStart()));
pushArg(ToRegister(lir->getObject()));
callVM(ArraySpliceDenseInfo, lir);
}
void
CodeGenerator::visitBail(LBail* lir)
{

View File

@ -216,7 +216,6 @@ class CodeGenerator : public CodeGeneratorSpecific
void emitSetPropertyPolymorphic(LInstruction* lir, Register obj,
Register scratch, const ConstantOrRegister& value);
void visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV* ins);
void visitArraySplice(LArraySplice* splice);
void visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins);
void visitAbsI(LAbsI* lir);
void visitAtan2D(LAtan2D* lir);

View File

@ -2985,7 +2985,7 @@ jit::ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block, const LinearSum&
if (term.scale == 1) {
if (def) {
def = MAdd::New(alloc, def, term.term);
def->toAdd()->setInt32();
def->toAdd()->setInt32Specialization();
block->insertAtEnd(def->toInstruction());
def->computeRange(alloc);
} else {
@ -2998,7 +2998,7 @@ jit::ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block, const LinearSum&
def->computeRange(alloc);
}
def = MSub::New(alloc, def, term.term);
def->toSub()->setInt32();
def->toSub()->setInt32Specialization();
block->insertAtEnd(def->toInstruction());
def->computeRange(alloc);
} else {
@ -3006,12 +3006,12 @@ jit::ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block, const LinearSum&
MConstant* factor = MConstant::New(alloc, Int32Value(term.scale));
block->insertAtEnd(factor);
MMul* mul = MMul::New(alloc, term.term, factor);
mul->setInt32();
mul->setInt32Specialization();
block->insertAtEnd(mul);
mul->computeRange(alloc);
if (def) {
def = MAdd::New(alloc, def, mul);
def->toAdd()->setInt32();
def->toAdd()->setInt32Specialization();
block->insertAtEnd(def->toInstruction());
def->computeRange(alloc);
} else {
@ -3026,7 +3026,7 @@ jit::ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block, const LinearSum&
constant->computeRange(alloc);
if (def) {
def = MAdd::New(alloc, def, constant);
def->toAdd()->setInt32();
def->toAdd()->setInt32Specialization();
block->insertAtEnd(def->toInstruction());
def->computeRange(alloc);
} else {
@ -3092,7 +3092,7 @@ jit::ConvertLinearInequality(TempAllocator& alloc, MBasicBlock* block, const Lin
block->insertAtEnd(constant->toInstruction());
constant->computeRange(alloc);
lhsDef = MAdd::New(alloc, lhsDef, constant);
lhsDef->toAdd()->setInt32();
lhsDef->toAdd()->setInt32Specialization();
block->insertAtEnd(lhsDef->toInstruction());
lhsDef->computeRange(alloc);
} while (false);

View File

@ -1656,7 +1656,7 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_MUL:
case JSOP_DIV:
case JSOP_MOD:
return jsop_binary(op);
return jsop_binary_arith(op);
case JSOP_POW:
return jsop_pow();
@ -4545,60 +4545,169 @@ IonBuilder::jsop_bitop(JSOp op)
return true;
}
bool
IonBuilder::jsop_binary(JSOp op, MDefinition* left, MDefinition* right)
MDefinition::Opcode
JSOpToMDefinition(JSOp op)
{
// Do a string concatenation if adding two inputs that are int or string
// and at least one is a string.
if (op == JSOP_ADD &&
((left->type() == MIRType_String &&
(right->type() == MIRType_String ||
right->type() == MIRType_Int32 ||
right->type() == MIRType_Double)) ||
(left->type() == MIRType_Int32 &&
right->type() == MIRType_String) ||
(left->type() == MIRType_Double &&
right->type() == MIRType_String)))
{
MConcat* ins = MConcat::New(alloc(), left, right);
current->add(ins);
current->push(ins);
return maybeInsertResume();
}
MBinaryArithInstruction* ins;
switch (op) {
case JSOP_ADD:
ins = MAdd::New(alloc(), left, right);
break;
return MDefinition::Op_Add;
case JSOP_SUB:
ins = MSub::New(alloc(), left, right);
break;
return MDefinition::Op_Sub;
case JSOP_MUL:
ins = MMul::New(alloc(), left, right);
break;
return MDefinition::Op_Mul;
case JSOP_DIV:
ins = MDiv::New(alloc(), left, right);
break;
return MDefinition::Op_Div;
case JSOP_MOD:
ins = MMod::New(alloc(), left, right);
break;
return MDefinition::Op_Mod;
default:
MOZ_CRASH("unexpected binary opcode");
}
}
bool
IonBuilder::binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left, MDefinition* right)
{
MOZ_ASSERT(*emitted == false);
// Try to convert an addition into a concat operation if the inputs
// indicate this might be a concatenation.
// Only try to replace this with concat when we have an addition.
if (op != JSOP_ADD)
return true;
// Make sure one of the inputs is a string.
if (left->type() != MIRType_String && right->type() != MIRType_String)
return true;
// The none-string input (if present) should be atleast a numerical type.
// Which we can easily coerce to string.
if (right->type() != MIRType_String && !IsNumberType(right->type()))
return true;
if (left->type() != MIRType_String && !IsNumberType(left->type()))
return true;
MConcat* ins = MConcat::New(alloc(), left, right);
current->add(ins);
ins->infer(alloc(), inspector, pc);
current->push(ins);
if (ins->isEffectful())
return resumeAfter(ins);
return maybeInsertResume();
if (!maybeInsertResume())
return false;
*emitted = true;
return true;
}
static inline bool
SimpleArithOperand(MDefinition* op)
{
return !op->mightBeType(MIRType_Object)
&& !op->mightBeType(MIRType_String)
&& !op->mightBeType(MIRType_Symbol)
&& !op->mightBeType(MIRType_MagicOptimizedArguments)
&& !op->mightBeType(MIRType_MagicHole)
&& !op->mightBeType(MIRType_MagicIsConstructing);
}
bool
IonBuilder::binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDefinition* right)
{
MOZ_ASSERT(*emitted == false);
// Try to emit a specialized binary instruction based on the input types
// of the operands.
// Anything complex - strings, symbols, and objects - are not specialized
if (!SimpleArithOperand(left) || !SimpleArithOperand(right))
return true;
// One of the inputs need to be a number.
if (!IsNumberType(left->type()) && !IsNumberType(right->type()))
return true;
MDefinition::Opcode defOp = JSOpToMDefinition(op);
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), defOp, left, right);
ins->setNumberSpecialization(alloc(), inspector, pc);
if (op == JSOP_ADD || op == JSOP_MUL)
ins->setCommutative();
current->add(ins);
current->push(ins);
MOZ_ASSERT(!ins->isEffectful());
if (!maybeInsertResume())
return false;
*emitted = true;
return true;
}
bool
IonBuilder::binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
MDefinition* left, MDefinition* right)
{
MOZ_ASSERT(*emitted == false);
// Try to emit a specialized binary instruction speculating the
// type using the baseline caches.
MIRType specialization = inspector->expectedBinaryArithSpecialization(pc);
if (specialization == MIRType_None)
return true;
MDefinition::Opcode def_op = JSOpToMDefinition(op);
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), def_op, left, right);
ins->setSpecialization(specialization);
current->add(ins);
current->push(ins);
MOZ_ASSERT(!ins->isEffectful());
if (!maybeInsertResume())
return false;
*emitted = true;
return true;
}
bool
IonBuilder::jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right)
{
bool emitted = false;
if (!forceInlineCaches()) {
if (!binaryArithTryConcat(&emitted, op, left, right) || emitted)
return emitted;
if (!binaryArithTrySpecialized(&emitted, op, left, right) || emitted)
return emitted;
if (!binaryArithTrySpecializedOnBaselineInspector(&emitted, op, left, right) || emitted)
return emitted;
}
// Not possible to optimize. Do a slow vm call.
MDefinition::Opcode def_op = JSOpToMDefinition(op);
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), def_op, left, right);
// Decrease type from 'any type' to 'empty type' when one of the operands
// is 'empty typed'.
maybeMarkEmpty(ins);
current->add(ins);
current->push(ins);
MOZ_ASSERT(ins->isEffectful());
return resumeAfter(ins);
}
bool
IonBuilder::jsop_binary_arith(JSOp op)
{
MDefinition* right = current->pop();
MDefinition* left = current->pop();
return jsop_binary_arith(op, left, right);
}
bool
@ -4620,15 +4729,6 @@ IonBuilder::jsop_pow()
return true;
}
bool
IonBuilder::jsop_binary(JSOp op)
{
MDefinition* right = current->pop();
MDefinition* left = current->pop();
return jsop_binary(op, left, right);
}
bool
IonBuilder::jsop_pos()
{
@ -4645,7 +4745,7 @@ IonBuilder::jsop_pos()
MConstant* one = MConstant::New(alloc(), Int32Value(1));
current->add(one);
return jsop_binary(JSOP_MUL, value, one);
return jsop_binary_arith(JSOP_MUL, value, one);
}
bool
@ -4658,7 +4758,7 @@ IonBuilder::jsop_neg()
MDefinition* right = current->pop();
if (!jsop_binary(JSOP_MUL, negator, right))
if (!jsop_binary_arith(JSOP_MUL, negator, right))
return false;
return true;
}
@ -7166,6 +7266,24 @@ IonBuilder::maybeInsertResume()
return resumeAfter(ins);
}
void
IonBuilder::maybeMarkEmpty(MDefinition* ins)
{
MOZ_ASSERT(ins->type() == MIRType_Value);
// When one of the operands has no type information, mark the output
// as having no possible types too. This is to avoid degrading
// subsequent analysis.
for (size_t i = 0; i < ins->numOperands(); i++) {
if (!ins->emptyResultTypeSet())
continue;
TemporaryTypeSet* types = alloc().lifoAlloc()->new_<TemporaryTypeSet>();
if (types)
ins->setResultTypeSet(types);
}
}
// Return whether property lookups can be performed effectlessly on clasp.
static bool
ClassHasEffectlessLookup(const Class* clasp)

View File

@ -374,6 +374,8 @@ class IonBuilder
// Creates a MDefinition based on the given def improved with type as TypeSet.
MDefinition* ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet* types);
void maybeMarkEmpty(MDefinition* ins);
JSObject* getSingletonPrototype(JSFunction* target);
MDefinition* createThisScripted(MDefinition* callee);
@ -481,6 +483,13 @@ class IonBuilder
PropertyName* name, MDefinition* value,
bool barrier, TemporaryTypeSet* objTypes);
// jsop_binary_arith helpers.
MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
bool binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
bool binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDefinition* right);
bool binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op, MDefinition* left,
MDefinition* right);
// binary data lookup helpers.
TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
@ -622,8 +631,8 @@ class IonBuilder
bool jsop_add(MDefinition* left, MDefinition* right);
bool jsop_bitnot();
bool jsop_bitop(JSOp op);
bool jsop_binary(JSOp op);
bool jsop_binary(JSOp op, MDefinition* left, MDefinition* right);
bool jsop_binary_arith(JSOp op);
bool jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right);
bool jsop_pow();
bool jsop_pos();
bool jsop_neg();
@ -744,7 +753,6 @@ class IonBuilder
InliningStatus inlineArrayConcat(CallInfo& callInfo);
InliningStatus inlineArraySlice(CallInfo& callInfo);
InliningStatus inlineArrayJoin(CallInfo& callInfo);
InliningStatus inlineArraySplice(CallInfo& callInfo);
// Math natives.
InliningStatus inlineMathAbs(CallInfo& callInfo);

View File

@ -556,16 +556,6 @@ LIRGenerator::visitAssertRecoveredOnBailout(MAssertRecoveredOnBailout* assertion
MOZ_CRASH("AssertRecoveredOnBailout nodes are always recovered on bailouts.");
}
void
LIRGenerator::visitArraySplice(MArraySplice* ins)
{
LArraySplice* lir = new(alloc()) LArraySplice(useRegisterAtStart(ins->object()),
useRegisterAtStart(ins->start()),
useRegisterAtStart(ins->deleteCount()));
add(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitGetDynamicName(MGetDynamicName* ins)
{

View File

@ -99,7 +99,6 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitLoadArrowThis(MLoadArrowThis* ins);
void visitCall(MCall* call);
void visitApplyArgs(MApplyArgs* apply);
void visitArraySplice(MArraySplice* splice);
void visitBail(MBail* bail);
void visitUnreachable(MUnreachable* unreachable);
void visitEncodeSnapshot(MEncodeSnapshot* ins);

View File

@ -90,8 +90,6 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
return inlineArrayConcat(callInfo);
if (native == js::array_slice)
return inlineArraySlice(callInfo);
if (native == js::array_splice)
return inlineArraySplice(callInfo);
// Math natives.
if (native == js::math_abs)
@ -693,46 +691,6 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineArraySplice(CallInfo& callInfo)
{
if (callInfo.argc() != 2 || callInfo.constructing()) {
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
return InliningStatus_NotInlined;
}
// Ensure |this|, argument and result are objects.
if (getInlineReturnType() != MIRType_Object)
return InliningStatus_NotInlined;
if (callInfo.thisArg()->type() != MIRType_Object)
return InliningStatus_NotInlined;
if (callInfo.getArg(0)->type() != MIRType_Int32)
return InliningStatus_NotInlined;
if (callInfo.getArg(1)->type() != MIRType_Int32)
return InliningStatus_NotInlined;
callInfo.setImplicitlyUsedUnchecked();
// Specialize arr.splice(start, deleteCount) with unused return value and
// avoid creating the result array in this case.
if (!BytecodeIsPopped(pc)) {
trackOptimizationOutcome(TrackedOutcome::CantInlineGeneric);
return InliningStatus_NotInlined;
}
MArraySplice* ins = MArraySplice::New(alloc(),
callInfo.thisArg(),
callInfo.getArg(0),
callInfo.getArg(1));
current->add(ins);
pushConstant(UndefinedValue());
if (!resumeAfter(ins))
return InliningStatus_Error;
return InliningStatus_Inlined;
}
IonBuilder::InliningStatus
IonBuilder::inlineArrayJoin(CallInfo& callInfo)
{
@ -3429,7 +3387,7 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, M
MAdd* addedIndex = MAdd::New(alloc(), *index, suppSlots);
// We're fine even with the add overflows, as long as the generated code
// for the bounds check uses an unsigned comparison.
addedIndex->setInt32();
addedIndex->setInt32Specialization();
current->add(addedIndex);
indexForBoundsCheck = addedIndex;
}

View File

@ -56,7 +56,7 @@ ConvertDefinitionToDouble(TempAllocator& alloc, MDefinition* def, MInstruction*
}
static bool
CheckUsesAreFloat32Consumers(MInstruction* ins)
CheckUsesAreFloat32Consumers(const MInstruction* ins)
{
bool allConsumerUses = true;
for (MUseDefIterator use(ins); allConsumerUses && use; use++)
@ -113,6 +113,8 @@ EvaluateConstantOperands(TempAllocator& alloc, MBinaryInstruction* ins, bool* pt
MDefinition* left = ins->getOperand(0);
MDefinition* right = ins->getOperand(1);
MOZ_ASSERT(IsNumberType(left->type()) && IsNumberType(right->type()));
if (!left->isConstantValue() || !right->isConstantValue())
return nullptr;
@ -2236,6 +2238,51 @@ NeedNegativeZeroCheck(MDefinition* def)
return false;
}
MBinaryArithInstruction*
MBinaryArithInstruction::New(TempAllocator& alloc, Opcode op,
MDefinition* left, MDefinition* right)
{
switch (op) {
case Op_Add:
return MAdd::New(alloc, left, right);
case Op_Sub:
return MSub::New(alloc, left, right);
case Op_Mul:
return MMul::New(alloc, left, right);
case Op_Div:
return MDiv::New(alloc, left, right);
case Op_Mod:
return MMod::New(alloc, left, right);
default:
MOZ_CRASH("unexpected binary opcode");
}
}
void
MBinaryArithInstruction::setNumberSpecialization(TempAllocator& alloc, BaselineInspector* inspector,
jsbytecode* pc)
{
setSpecialization(MIRType_Double);
// Try to specialize as int32.
if (getOperand(0)->type() == MIRType_Int32 && getOperand(1)->type() == MIRType_Int32) {
bool seenDouble = inspector->hasSeenDoubleResult(pc);
// Use int32 specialization if the operation doesn't overflow on its
// constant operands and if the operation has never overflowed.
if (!seenDouble && !constantDoubleResult(alloc))
setInt32Specialization();
}
}
bool
MBinaryArithInstruction::constantDoubleResult(TempAllocator& alloc)
{
bool typeChange = false;
EvaluateConstantOperands(alloc, this, &typeChange);
return typeChange;
}
MDefinition*
MBinaryArithInstruction::foldsTo(TempAllocator& alloc)
{
@ -2276,6 +2323,23 @@ MBinaryArithInstruction::foldsTo(TempAllocator& alloc)
return this;
}
void
MFilterTypeSet::trySpecializeFloat32(TempAllocator& alloc)
{
MDefinition* in = input();
if (in->type() != MIRType_Float32)
return;
setResultType(MIRType_Float32);
}
bool
MFilterTypeSet::canConsumeFloat32(MUse* operand) const
{
MOZ_ASSERT(getUseFor(0) == operand);
return CheckUsesAreFloat32Consumers(this);
}
void
MBinaryArithInstruction::trySpecializeFloat32(TempAllocator& alloc)
{
@ -2637,81 +2701,6 @@ SimpleArithOperand(MDefinition* op)
&& !op->mightBeType(MIRType_MagicIsConstructing);
}
void
MBinaryArithInstruction::infer(TempAllocator& alloc, BaselineInspector* inspector, jsbytecode* pc)
{
MOZ_ASSERT(this->type() == MIRType_Value);
specialization_ = MIRType_None;
// Anything complex - strings, symbols, and objects - are not specialized
// unless baseline type hints suggest it might be profitable
if (!SimpleArithOperand(getOperand(0)) || !SimpleArithOperand(getOperand(1)))
return inferFallback(inspector, pc);
// Retrieve type information of lhs and rhs.
MIRType lhs = getOperand(0)->type();
MIRType rhs = getOperand(1)->type();
// Guess a result type based on the inputs.
// Don't specialize for neither-integer-nor-double results.
if (lhs == MIRType_Int32 && rhs == MIRType_Int32) {
setResultType(MIRType_Int32);
// If the operation will always overflow on its constant operands, use a
// double specialization so that it can be constant folded later.
if (isMul() || isDiv()) {
bool typeChange = false;
EvaluateConstantOperands(alloc, this, &typeChange);
if (typeChange)
setResultType(MIRType_Double);
}
// If the operation has ever overflowed, use a double specialization.
if (inspector->hasSeenDoubleResult(pc))
setResultType(MIRType_Double);
} else if (IsFloatingPointType(lhs) || IsFloatingPointType(rhs)) {
// Double operations take precedence over float32 operations (i.e. if
// any operand needs a double as an input, convert all operands to
// doubles)
setResultType(MIRType_Double);
} else {
return inferFallback(inspector, pc);
}
MOZ_ASSERT(lhs < MIRType_String || lhs == MIRType_Value);
MOZ_ASSERT(rhs < MIRType_String || rhs == MIRType_Value);
if (isAdd() || isMul())
setCommutative();
MOZ_ASSERT(IsNumberType(this->type()));
specialization_ = this->type();
}
void
MBinaryArithInstruction::inferFallback(BaselineInspector* inspector,
jsbytecode* pc)
{
// Try to specialize based on what baseline observed in practice.
specialization_ = inspector->expectedBinaryArithSpecialization(pc);
if (specialization_ != MIRType_None) {
setResultType(specialization_);
return;
}
// If we can't specialize because we have no type information at all for
// the lhs or rhs, mark the binary instruction as having no possible types
// either to avoid degrading subsequent analysis.
if (getOperand(0)->emptyResultTypeSet() || getOperand(1)->emptyResultTypeSet()) {
LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
TemporaryTypeSet* types = alloc->new_<TemporaryTypeSet>();
if (types)
setResultTypeSet(types);
}
}
static bool
SafelyCoercesToDouble(MDefinition* op)
{

View File

@ -852,7 +852,7 @@ class MDefinition : public MNode
// iteration.
class MUseDefIterator
{
MDefinition* def_;
const MDefinition* def_;
MUseIterator current_;
MUseIterator search(MUseIterator start) {
@ -865,7 +865,7 @@ class MUseDefIterator
}
public:
explicit MUseDefIterator(MDefinition* def)
explicit MUseDefIterator(const MDefinition* def)
: def_(def),
current_(search(def->usesBegin()))
{ }
@ -3813,42 +3813,6 @@ class MCallDOMNative : public MCall
virtual void computeMovable() override;
};
// arr.splice(start, deleteCount) with unused return value.
class MArraySplice
: public MTernaryInstruction,
public Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2> >::Data
{
private:
MArraySplice(MDefinition* object, MDefinition* start, MDefinition* deleteCount)
: MTernaryInstruction(object, start, deleteCount)
{ }
public:
INSTRUCTION_HEADER(ArraySplice)
static MArraySplice* New(TempAllocator& alloc, MDefinition* object,
MDefinition* start, MDefinition* deleteCount)
{
return new(alloc) MArraySplice(object, start, deleteCount);
}
MDefinition* object() const {
return getOperand(0);
}
MDefinition* start() const {
return getOperand(1);
}
MDefinition* deleteCount() const {
return getOperand(2);
}
bool possiblyCalls() const override {
return true;
}
};
// fun.apply(self, arguments)
class MApplyArgs
: public MAryInstruction<3>,
@ -5594,26 +5558,33 @@ class MBinaryArithInstruction
// analysis detect a precision loss in the multiplication.
TruncateKind implicitTruncate_;
void inferFallback(BaselineInspector* inspector, jsbytecode* pc);
public:
MBinaryArithInstruction(MDefinition* left, MDefinition* right)
: MBinaryInstruction(left, right),
implicitTruncate_(NoTruncate)
{
specialization_ = MIRType_None;
setMovable();
}
static MBinaryArithInstruction* New(TempAllocator& alloc, Opcode op,
MDefinition* left, MDefinition* right);
bool constantDoubleResult(TempAllocator& alloc);
MDefinition* foldsTo(TempAllocator& alloc) override;
virtual double getIdentity() = 0;
void infer(TempAllocator& alloc, BaselineInspector* inspector, jsbytecode* pc);
void setInt32() {
void setSpecialization(MIRType type) {
specialization_ = type;
setResultType(type);
}
void setInt32Specialization() {
specialization_ = MIRType_Int32;
setResultType(MIRType_Int32);
}
void setNumberSpecialization(TempAllocator& alloc, BaselineInspector* inspector, jsbytecode* pc);
virtual void trySpecializeFloat32(TempAllocator& alloc) override;
@ -12280,6 +12251,11 @@ class MFilterTypeSet
return resultTypeSet()->empty();
}
void computeRange(TempAllocator& alloc) override;
bool isFloat32Commutative() const override { return true; }
bool canProduceFloat32() const override { return input()->canProduceFloat32(); }
bool canConsumeFloat32(MUse* operand) const override;
void trySpecializeFloat32(TempAllocator& alloc) override;
};
// Given a value, guard that the value is in a particular TypeSet, then returns

View File

@ -62,7 +62,6 @@ namespace jit {
_(LoadArrowThis) \
_(Call) \
_(ApplyArgs) \
_(ArraySplice) \
_(Bail) \
_(Unreachable) \
_(EncodeSnapshot) \

View File

@ -251,18 +251,6 @@ StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res)
template bool StringsEqual<true>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
template bool StringsEqual<false>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
bool
ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount)
{
JS::AutoValueArray<4> argv(cx);
argv[0].setUndefined();
argv[1].setObject(*obj);
argv[2].set(Int32Value(start));
argv[3].set(Int32Value(deleteCount));
return js::array_splice_impl(cx, 2, argv.begin(), false);
}
bool
ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
{

View File

@ -688,8 +688,6 @@ bool InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame
JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
HandleObject owner, int32_t offset);
bool ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount);
bool Recompile(JSContext* cx);
bool ForcedRecompile(JSContext* cx);
JSString* RegExpReplace(JSContext* cx, HandleString string, HandleObject regexp,

View File

@ -959,6 +959,32 @@ public:
MOZ_CRASH("NYI");
}
template<typename T>
void atomicExchange8SignExtend(const T& mem, Register value, Register output)
{
MOZ_CRASH("NYI");
}
template<typename T>
void atomicExchange8ZeroExtend(const T& mem, Register value, Register output)
{
MOZ_CRASH("NYI");
}
template<typename T>
void atomicExchange16SignExtend(const T& mem, Register value, Register output)
{
MOZ_CRASH("NYI");
}
template<typename T>
void atomicExchange16ZeroExtend(const T& mem, Register value, Register output)
{
MOZ_CRASH("NYI");
}
template<typename T>
void atomicExchange32(const T& mem, Register value, Register output)
{
MOZ_CRASH("NYI");
}
template<typename T, typename S>
void atomicFetchAdd8SignExtend(const S& value, const T& mem, Register temp, Register output) {
MOZ_CRASH("NYI");

View File

@ -1809,34 +1809,6 @@ class LApplyArgsGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES +
}
};
class LArraySplice : public LCallInstructionHelper<0, 3, 0>
{
public:
LIR_HEADER(ArraySplice)
LArraySplice(const LAllocation& object, const LAllocation& start,
const LAllocation& deleteCount)
{
setOperand(0, object);
setOperand(1, start);
setOperand(2, deleteCount);
}
MArraySplice* mir() const {
return mir_->toArraySplice();
}
const LAllocation* getObject() {
return getOperand(0);
}
const LAllocation* getStart() {
return getOperand(1);
}
const LAllocation* getDeleteCount() {
return getOperand(2);
}
};
class LGetDynamicName : public LCallInstructionHelper<BOX_PIECES, 2, 3>
{
public:

View File

@ -53,7 +53,6 @@
_(NewArray) \
_(NewArrayCopyOnWrite) \
_(NewArrayDynamicLength) \
_(ArraySplice) \
_(NewObject) \
_(NewTypedObject) \
_(NewDeclEnvObject) \

View File

@ -61,6 +61,7 @@ MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 0, JSEXN_RANGEERR, "array too large due t
MSG_DEF(JSMSG_BAD_WEAKMAP_KEY, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key")
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 1, JSEXN_TYPEERR, "invalid {0} usage")
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 0, JSEXN_RANGEERR, "invalid array length")
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH_SPLICE, 0, JSEXN_TYPEERR, "resulting array length too large")
MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
MSG_DEF(JSMSG_GETTER_ONLY, 0, JSEXN_TYPEERR, "setting a property that has only a getter")

View File

@ -28,8 +28,12 @@ BEGIN_TEST(testJitDCEinGVN_ins)
block->add(p);
MMul* mul0 = MMul::New(func.alloc, p, p, MIRType_Double);
block->add(mul0);
if (!mul0->typePolicy()->adjustInputs(func.alloc, mul0))
return false;
MMul* mul1 = MMul::New(func.alloc, mul0, mul0, MIRType_Double);
block->add(mul1);
if (!mul1->typePolicy()->adjustInputs(func.alloc, mul1))
return false;
MReturn* ret = MReturn::New(func.alloc, p);
block->end(ret);

View File

@ -28,6 +28,9 @@ BEGIN_TEST(testJitFoldsTo_DivReciprocal)
block->add(c);
MDiv* div = MDiv::New(func.alloc, p, c, MIRType_Double);
block->add(div);
if (!div->typePolicy()->adjustInputs(func.alloc, div))
return false;
MDefinition* left = div->getOperand(0);
MReturn* ret = MReturn::New(func.alloc, div);
block->end(ret);
@ -37,7 +40,7 @@ BEGIN_TEST(testJitFoldsTo_DivReciprocal)
// Test that the div got folded to p * 0.25.
MDefinition* op = ret->getOperand(0);
CHECK(op->isMul());
CHECK(op->getOperand(0) == p);
CHECK(op->getOperand(0) == left);
CHECK(op->getOperand(1)->isConstant());
CHECK(op->getOperand(1)->toConstant()->value().toNumber() == 0.25);
return true;
@ -56,6 +59,10 @@ BEGIN_TEST(testJitFoldsTo_NoDivReciprocal)
block->add(c);
MDiv* div = MDiv::New(func.alloc, p, c, MIRType_Double);
block->add(div);
if (!div->typePolicy()->adjustInputs(func.alloc, div))
return false;
MDefinition* left = div->getOperand(0);
MDefinition* right = div->getOperand(1);
MReturn* ret = MReturn::New(func.alloc, div);
block->end(ret);
@ -65,8 +72,8 @@ BEGIN_TEST(testJitFoldsTo_NoDivReciprocal)
// Test that the div didn't get folded.
MDefinition* op = ret->getOperand(0);
CHECK(op->isDiv());
CHECK(op->getOperand(0) == p);
CHECK(op->getOperand(1) == c);
CHECK(op->getOperand(0) == left);
CHECK(op->getOperand(1) == right);
return true;
}
END_TEST(testJitFoldsTo_NoDivReciprocal)

View File

@ -579,7 +579,14 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// that element must prevent any deletions below it. Bug 586842 should
// fix this inefficiency by moving indexed storage to be entirely
// separate from non-indexed storage.
if (!arr->isIndexed()) {
// A second reason for this optimization to be invalid is an active
// for..in iteration over the array. Keys deleted before being reached
// during the iteration must not be visited, and suppressing them here
// would be too costly.
ObjectGroup* arrGroup = arr->getGroup(cx);
if (!arr->isIndexed() &&
!MOZ_UNLIKELY(!arrGroup || arrGroup->hasAllFlags(OBJECT_FLAG_ITERATED)))
{
if (!arr->maybeCopyElementsForWrite(cx))
return false;
@ -2254,277 +2261,6 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
return true;
}
/*
* Returns true if this is a dense or unboxed array whose |count| properties
* starting from |startingIndex| may be accessed (get, set, delete) directly
* through its contiguous vector of elements without fear of getters, setters,
* etc. along the prototype chain, or of enumerators requiring notification of
* modifications.
*/
static inline bool
CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t count, JSContext* cx)
{
/* If the desired properties overflow dense storage, we can't optimize. */
if (UINT32_MAX - startingIndex < count)
return false;
/* There's no optimizing possible if it's not an array. */
if (!arr->is<ArrayObject>() && !arr->is<UnboxedArrayObject>())
return false;
/*
* Don't optimize if the array might be in the midst of iteration. We
* rely on this to be able to safely move dense array elements around with
* just a memmove (see NativeObject::moveDenseArrayElements), without worrying
* about updating any in-progress enumerators for properties implicitly
* deleted if a hole is moved from one location to another location not yet
* visited. See bug 690622.
*/
ObjectGroup* arrGroup = arr->getGroup(cx);
if (MOZ_UNLIKELY(!arrGroup || arrGroup->hasAllFlags(OBJECT_FLAG_ITERATED)))
return false;
/*
* Another potential wrinkle: what if the enumeration is happening on an
* object which merely has |arr| on its prototype chain?
*/
if (arr->isDelegate())
return false;
/*
* Now watch out for getters and setters along the prototype chain or in
* other indexed properties on the object. (Note that non-writable length
* is subsumed by the initializedLength comparison.)
*/
return !ObjectMayHaveExtraIndexedProperties(arr) &&
startingIndex + count <= GetAnyBoxedOrUnboxedInitializedLength(arr);
}
/* ES5 15.4.4.12. */
bool
js::array_splice(JSContext* cx, unsigned argc, Value* vp)
{
return array_splice_impl(cx, argc, vp, true);
}
bool
js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed)
{
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
/* Steps 3-4. */
uint32_t len;
if (!GetLengthProperty(cx, obj, &len))
return false;
/* Step 5. */
double relativeStart;
if (!ToInteger(cx, args.get(0), &relativeStart))
return false;
/* Step 6. */
uint32_t actualStart;
if (relativeStart < 0)
actualStart = Max(len + relativeStart, 0.0);
else
actualStart = Min(relativeStart, double(len));
/* Step 7. */
uint32_t actualDeleteCount;
if (args.length() != 1) {
double deleteCountDouble;
RootedValue cnt(cx, args.length() >= 2 ? args[1] : Int32Value(0));
if (!ToInteger(cx, cnt, &deleteCountDouble))
return false;
actualDeleteCount = Min(Max(deleteCountDouble, 0.0), double(len - actualStart));
} else {
/*
* Non-standard: if start was specified but deleteCount was omitted,
* delete to the end of the array. See bug 668024 for discussion.
*/
actualDeleteCount = len - actualStart;
}
MOZ_ASSERT(len - actualStart >= actualDeleteCount);
/* Steps 2, 8-9. */
RootedObject arr(cx);
if (CanOptimizeForDenseStorage(obj, actualStart, actualDeleteCount, cx)) {
if (returnValueIsUsed) {
arr = NewFullyAllocatedArrayTryReuseGroup(cx, obj, actualDeleteCount);
if (!arr)
return false;
DebugOnly<DenseElementResult> result =
CopyAnyBoxedOrUnboxedDenseElements(cx, arr, obj, 0, actualStart, actualDeleteCount);
MOZ_ASSERT(result.value == DenseElementResult::Success);
}
} else {
arr = NewFullyAllocatedArrayTryReuseGroup(cx, obj, actualDeleteCount);
if (!arr)
return false;
RootedValue fromValue(cx);
for (uint32_t k = 0; k < actualDeleteCount; k++) {
bool hole;
if (!CheckForInterrupt(cx) ||
!GetElement(cx, obj, actualStart + k, &hole, &fromValue) ||
(!hole && !DefineElement(cx, arr, k, fromValue)))
{
return false;
}
}
}
/* Step 11. */
uint32_t itemCount = (args.length() >= 2) ? (args.length() - 2) : 0;
if (itemCount < actualDeleteCount) {
/* Step 12: the array is being shrunk. */
uint32_t sourceIndex = actualStart + actualDeleteCount;
uint32_t targetIndex = actualStart + itemCount;
uint32_t finalLength = len - actualDeleteCount + itemCount;
if (CanOptimizeForDenseStorage(obj, 0, len, cx)) {
/* Steps 12(a)-(b). */
DenseElementResult result =
MoveAnyBoxedOrUnboxedDenseElements(cx, obj, targetIndex, sourceIndex,
len - sourceIndex);
MOZ_ASSERT(result != DenseElementResult::Incomplete);
if (result == DenseElementResult::Failure)
return false;
/* Steps 12(c)-(d). */
SetAnyBoxedOrUnboxedInitializedLength(cx, obj, finalLength);
} else {
/*
* This is all very slow if the length is very large. We don't yet
* have the ability to iterate in sorted order, so we just do the
* pessimistic thing and let CheckForInterrupt handle the
* fallout.
*/
/* Steps 12(a)-(b). */
RootedValue fromValue(cx);
for (uint32_t from = sourceIndex, to = targetIndex; from < len; from++, to++) {
if (!CheckForInterrupt(cx))
return false;
bool hole;
if (!GetElement(cx, obj, from, &hole, &fromValue))
return false;
if (hole) {
if (!DeletePropertyOrThrow(cx, obj, to))
return false;
} else {
if (!SetArrayElement(cx, obj, to, fromValue))
return false;
}
}
/* Steps 12(c)-(d). */
for (uint32_t k = len; k > finalLength; k--) {
if (!DeletePropertyOrThrow(cx, obj, k - 1))
return false;
}
}
} else if (itemCount > actualDeleteCount) {
/* Step 13. */
/*
* Optimize only if the array is already dense and we can extend it to
* its new length. It would be wrong to extend the elements here for a
* number of reasons.
*
* First, this could cause us to fall into the fast-path below. This
* would cause elements to be moved into places past the non-writable
* length. And when the dense initialized length is updated, that'll
* cause the |in| operator to think that those elements actually exist,
* even though, properly, setting them must fail.
*
* Second, extending the elements here will trigger assertions inside
* ensureDenseElements that the elements aren't being extended past the
* length of a non-writable array. This is because extending elements
* will extend capacity -- which might extend them past a non-writable
* length, violating the |capacity <= length| invariant for such
* arrays. And that would make the various JITted fast-path method
* implementations of [].push, [].unshift, and so on wrong.
*
* If the array length is non-writable, this method *will* throw. For
* simplicity, have the slow-path code do it. (Also note that the slow
* path may validly *not* throw -- if all the elements being moved are
* holes.)
*/
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (arr->lengthIsWritable()) {
DenseElementResult result =
arr->ensureDenseElements(cx, arr->length(), itemCount - actualDeleteCount);
if (result == DenseElementResult::Failure)
return false;
}
}
if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
DenseElementResult result =
MoveAnyBoxedOrUnboxedDenseElements(cx, obj, actualStart + itemCount,
actualStart + actualDeleteCount,
len - (actualStart + actualDeleteCount));
MOZ_ASSERT(result != DenseElementResult::Incomplete);
if (result == DenseElementResult::Failure)
return false;
/* Steps 12(c)-(d). */
SetAnyBoxedOrUnboxedInitializedLength(cx, obj, len + itemCount - actualDeleteCount);
} else {
RootedValue fromValue(cx);
for (double k = len - actualDeleteCount; k > actualStart; k--) {
if (!CheckForInterrupt(cx))
return false;
double from = k + actualDeleteCount - 1;
double to = k + itemCount - 1;
bool hole;
if (!GetElement(cx, obj, from, &hole, &fromValue))
return false;
if (hole) {
if (!DeletePropertyOrThrow(cx, obj, to))
return false;
} else {
if (!SetArrayElement(cx, obj, to, fromValue))
return false;
}
}
}
}
/* Step 10. */
Value* items = args.array() + 2;
/* Steps 14-15. */
for (uint32_t k = actualStart, i = 0; i < itemCount; i++, k++) {
if (!SetArrayElement(cx, obj, k, HandleValue::fromMarkedLocation(&items[i])))
return false;
}
/* Step 16. */
double finalLength = double(len) - actualDeleteCount + itemCount;
if (!SetLengthProperty(cx, obj, finalLength))
return false;
/* Step 17. */
if (returnValueIsUsed)
args.rval().setObject(*arr);
return true;
}
template <JSValueType Type>
DenseElementResult
ArrayConcatDenseKernel(JSContext* cx, JSObject* obj1, JSObject* obj2, JSObject* result)
@ -2931,86 +2667,6 @@ js::array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t en
return &argv[0].toObject();
}
/* ES5 15.4.4.20. */
static bool
array_filter(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
/* Step 2-3. */
uint32_t len;
if (!GetLengthProperty(cx, obj, &len))
return false;
/* Step 4. */
if (args.length() == 0) {
ReportMissingArg(cx, args.calleev(), 0);
return false;
}
RootedObject callable(cx, ValueToCallable(cx, args[0], args.length() - 1));
if (!callable)
return false;
/* Step 5. */
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
/* Step 6. */
RootedObject arr(cx, NewFullyAllocatedArrayForCallingAllocationSite(cx, 0));
if (!arr)
return false;
/* Step 7. */
uint32_t k = 0;
/* Step 8. */
uint32_t to = 0;
/* Step 9. */
FastInvokeGuard fig(cx, ObjectValue(*callable));
InvokeArgs& args2 = fig.args();
RootedValue kValue(cx);
while (k < len) {
if (!CheckForInterrupt(cx))
return false;
/* Step a, b, and c.i. */
bool kNotPresent;
if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
return false;
/* Step c.ii-iii. */
if (!kNotPresent) {
if (!args2.init(3))
return false;
args2.setCallee(ObjectValue(*callable));
args2.setThis(thisv);
args2[0].set(kValue);
args2[1].setNumber(k);
args2[2].setObject(*obj);
if (!fig.invoke(cx))
return false;
if (ToBoolean(args2.rval())) {
if (!SetArrayElement(cx, arr, to, kValue))
return false;
to++;
}
}
/* Step d. */
k++;
}
/* Step 10. */
args.rval().setObject(*arr);
return true;
}
static bool
array_isArray(JSContext* cx, unsigned argc, Value* vp)
{
@ -3102,7 +2758,7 @@ static const JSFunctionSpec array_methods[] = {
JS_FN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE),
JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
JS_SELF_HOSTED_FN("splice", "ArraySplice", 2,0),
/* Pythonic sequence methods. */
JS_FN("concat", array_concat, 1,JSFUN_GENERIC_NATIVE),
@ -3112,9 +2768,9 @@ static const JSFunctionSpec array_methods[] = {
JS_SELF_HOSTED_FN("indexOf", "ArrayIndexOf", 1,0),
JS_SELF_HOSTED_FN("forEach", "ArrayForEach", 1,0),
JS_SELF_HOSTED_FN("map", "ArrayMap", 1,0),
JS_SELF_HOSTED_FN("filter", "ArrayFilter", 1,0),
JS_SELF_HOSTED_FN("reduce", "ArrayReduce", 1,0),
JS_SELF_HOSTED_FN("reduceRight", "ArrayReduceRight", 1,0),
JS_FN("filter", array_filter, 1,JSFUN_GENERIC_NATIVE),
JS_SELF_HOSTED_FN("some", "ArraySome", 1,0),
JS_SELF_HOSTED_FN("every", "ArrayEvery", 1,0),
@ -3143,6 +2799,7 @@ static const JSFunctionSpec array_static_methods[] = {
JS_SELF_HOSTED_FN("indexOf", "ArrayStaticIndexOf", 2,0),
JS_SELF_HOSTED_FN("forEach", "ArrayStaticForEach", 2,0),
JS_SELF_HOSTED_FN("map", "ArrayStaticMap", 2,0),
JS_SELF_HOSTED_FN("filter", "ArrayStaticFilter", 2,0),
JS_SELF_HOSTED_FN("every", "ArrayStaticEvery", 2,0),
JS_SELF_HOSTED_FN("some", "ArrayStaticSome", 2,0),
JS_SELF_HOSTED_FN("reduce", "ArrayStaticReduce", 2,0),

View File

@ -0,0 +1,10 @@
var a = [0, 1];
var iterations = 0;
for (var k in a) {
iterations++;
a.length = 1;
}
assertEq(iterations, 1);
if (typeof reportCompare === "function")
reportCompare(true, true);

View File

@ -0,0 +1,14 @@
var a = {};
a[2 ** 53 - 2] = 1;
a.length = 2 ** 53 - 1;
var exception;
try {
[].splice.call(a, 2 ** 53 - 2, 0, 2, 3, 4, 5);
} catch (e) {
exception = e;
}
reportCompare(a[2 ** 53 - 2], 1);
reportCompare(a.length, 2 ** 53 - 1);
reportCompare(exception instanceof TypeError, true, "Array#splice throws TypeError for length overflows");
reportCompare(exception.message.indexOf('array length') > -1, true, "Array#splice throws correct error for length overflows");

View File

@ -901,7 +901,10 @@ SavedStacks::saveCurrentStack(JSContext* cx, MutableHandleSavedFrame frame, unsi
MOZ_ASSERT(initialized());
assertSameCompartment(cx, this);
if (creatingSavedFrame || cx->isExceptionPending()) {
if (creatingSavedFrame ||
cx->isExceptionPending() ||
!cx->global()->isStandardClassResolved(JSProto_Object))
{
frame.set(nullptr);
return true;
}

View File

@ -29,11 +29,11 @@ namespace js {
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 299;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 300;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 407,
static_assert(JSErr_Limit == 408,
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "

View File

@ -873,7 +873,10 @@ nsRangeFrame::GetAdditionalStyleContext(int32_t aIndex) const
// We only implement this so that SetAdditionalStyleContext will be
// called if style changes that would change the -moz-focus-outer
// pseudo-element have occurred.
return aIndex == 0 ? mOuterFocusStyle : nullptr;
if (aIndex != 0) {
return nullptr;
}
return mOuterFocusStyle;
}
void

View File

@ -66,6 +66,7 @@ let windows_versions = [
// Possible values for '-moz-windows-theme'
let windows_themes = [
"aero",
"aero-lite",
"luna-blue",
"luna-olive",
"luna-silver",
@ -119,14 +120,17 @@ let testToggles = function (resisting) {
// __testWindowsSpecific__.
// Runs a media query on the queryName with the given possible matching values.
let testWindowsSpecific = function (resisting, queryName, possibleValues) {
let found = false;
let foundValue = null;
possibleValues.forEach(function (val) {
found = found || keyValMatches(queryName, val);
if (keyValMatches(queryName, val)) {
foundValue = val;
}
});
if (resisting) {
ok(!found, queryName + " should have no match");
ok(!foundValue, queryName + " should have no match");
} else {
ok(found, queryName + " should match");
ok(foundValue, foundValue ? ("Match found: '" + queryName + ":" + foundValue + "'")
: "Should have a match for '" + queryName + "'");
}
};

View File

@ -703,7 +703,15 @@ class IceTestPeer : public sigslot::has_slots<> {
ASSERT_EQ(expected_local_type_, local->type);
ASSERT_EQ(expected_local_transport_, local->local_addr.transport);
DumpCandidate("Remote ", *remote);
ASSERT_EQ(expected_remote_type_, remote->type);
/* Remote ICE TCP active candidates are always trickled with port 9
so they will get discovered as peer reflexive locally. */
if (expected_local_transport_ == kNrIceTransportTcp &&
expected_remote_type_ == NrIceCandidate::ICE_HOST) {
ASSERT_NE(NrIceCandidate::ICE_SERVER_REFLEXIVE, remote->type);
ASSERT_NE(NrIceCandidate::ICE_RELAYED, remote->type);
} else {
ASSERT_EQ(expected_remote_type_, remote->type);
}
if (!expected_remote_addr_.empty()) {
ASSERT_EQ(expected_remote_addr_, remote->cand_addr.host);
}

View File

@ -532,6 +532,22 @@
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
#endif /* MOZ_CLANG_PLUGIN */
/*
* MOZ_HAVE_REF_QUALIFIERS is defined for compilers that support C++11's rvalue
* qualifier, "&&".
*/
#if defined(_MSC_VER) && _MSC_VER >= 1900
# define MOZ_HAVE_REF_QUALIFIERS
#elif defined(__clang__)
// All supported Clang versions
# define MOZ_HAVE_REF_QUALIFIERS
#elif defined(__GNUC__)
# include "mozilla/Compiler.h"
# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 1)
# define MOZ_HAVE_REF_QUALIFIERS
# endif
#endif
#endif /* __cplusplus */
#endif /* mozilla_Attributes_h */

View File

@ -15,6 +15,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include "mozilla/RefCountType.h"
#include "mozilla/nsRefPtr.h"
#include "mozilla/TypeTraits.h"
#if defined(MOZILLA_INTERNAL_API)
#include "nsXPCOM.h"
@ -278,10 +279,23 @@ public:
}
T* get() const { return mPtr; }
operator T*() const { return mPtr; }
operator T*() const
#ifdef MOZ_HAVE_REF_QUALIFIERS
&
#endif
{ return mPtr; }
T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mPtr; }
T& operator*() const { return *mPtr; }
#ifdef MOZ_HAVE_REF_QUALIFIERS
// Don't allow implicit conversion of temporary RefPtr to raw pointer, because
// the refcount might be one and the pointer will immediately become invalid.
operator T*() const && = delete;
// Needed to avoid the deleted operator above
explicit operator bool() const { return !!mPtr; }
#endif
private:
void assign(T* aVal)
{
@ -375,4 +389,19 @@ MakeAndAddRef(Args&&... aArgs)
} // namespace mozilla
// Declared in nsRefPtr.h
template<class T> template<class U>
nsRefPtr<T>::nsRefPtr(mozilla::RefPtr<U>&& aOther)
: nsRefPtr(aOther.forget())
{
}
template<class T> template<class U>
nsRefPtr<T>&
nsRefPtr<T>::operator=(mozilla::RefPtr<U>&& aOther)
{
assign_assuming_AddRef(aOther.forget().take());
return *this;
}
#endif /* mozilla_RefPtr_h */

View File

@ -19,6 +19,7 @@ class nsCOMPtr_helper;
namespace mozilla {
template<class T> class OwningNonNull;
template<class T> class RefPtr;
} // namespace mozilla
template <class T>
@ -127,6 +128,10 @@ public:
template<class U>
MOZ_IMPLICIT nsRefPtr(const mozilla::OwningNonNull<U>& aOther);
// Defined in RefPtr.h
template<class U>
MOZ_IMPLICIT nsRefPtr(mozilla::RefPtr<U>&& aOther);
// Assignment operators
nsRefPtr<T>&
@ -187,6 +192,11 @@ public:
nsRefPtr<T>&
operator=(const mozilla::OwningNonNull<U>& aOther);
// Defined in RefPtr.h
template<class U>
nsRefPtr<T>&
operator=(mozilla::RefPtr<U>&& aOther);
// Other pointer operators
void
@ -241,6 +251,9 @@ public:
}
operator T*() const
#ifdef MOZ_HAVE_REF_QUALIFIERS
&
#endif
/*
...makes an |nsRefPtr| act like its underlying raw pointer type whenever it
is used in a context where a raw pointer is expected. It is this operator
@ -253,6 +266,19 @@ public:
return get();
}
#ifdef MOZ_HAVE_REF_QUALIFIERS
// Don't allow implicit conversion of temporary nsRefPtr to raw pointer,
// because the refcount might be one and the pointer will immediately become
// invalid.
operator T*() const && = delete;
// These are needed to avoid the deleted operator above. XXX Why is operator!
// needed separately? Shouldn't the compiler prefer using the non-deleted
// operator bool instead of the deleted operator T*?
explicit operator bool() const { return !!mRawPtr; }
bool operator!() const { return !mRawPtr; }
#endif
T*
operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{

View File

@ -771,7 +771,8 @@ nsCertTree::DeleteEntryObject(uint32_t index)
if (certdi->mAddonInfo) {
cert = certdi->mAddonInfo->mCert;
}
nsCertAddonInfo *addonInfo = certdi->mAddonInfo ? certdi->mAddonInfo : nullptr;
nsCertAddonInfo* addonInfo =
certdi->mAddonInfo ? certdi->mAddonInfo.get() : nullptr;
if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort);
if (addonInfo) {

View File

@ -190,37 +190,56 @@ InstallSigSysHandler(void)
}
/**
* This function installs the syscall filter, a.k.a. seccomp.
* PR_SET_NO_NEW_PRIVS ensures that it is impossible to grant more
* syscalls to the process beyond this point (even after fork()).
* This function installs the syscall filter, a.k.a. seccomp. The
* aUseTSync flag indicates whether this should apply to all threads
* in the process -- which will fail if the kernel doesn't support
* that -- or only the current thread.
*
* SECCOMP_MODE_FILTER is the "bpf" mode of seccomp which allows
* to pass a bpf program (in our case, it contains a syscall
* whitelist).
*
* Reports failure by crashing.
* PR_SET_NO_NEW_PRIVS ensures that it is impossible to grant more
* syscalls to the process beyond this point (even after fork()), and
* prevents gaining capabilities (e.g., by exec'ing a setuid root
* program). The kernel won't allow seccomp-bpf without doing this,
* because otherwise it could be used for privilege escalation attacks.
*
* @see sock_fprog (the seccomp_prog).
* Returns false (and sets errno) on failure.
*
* @see SandboxInfo
* @see BroadcastSetThreadSandbox
*/
static void
InstallSyscallFilter(const sock_fprog *prog)
static bool MOZ_WARN_UNUSED_RESULT
InstallSyscallFilter(const sock_fprog *aProg, bool aUseTSync)
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
SANDBOX_LOG_ERROR("prctl(PR_SET_NO_NEW_PRIVS) failed: %s", strerror(errno));
MOZ_CRASH("prctl(PR_SET_NO_NEW_PRIVS)");
}
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)prog, 0, 0)) {
SANDBOX_LOG_ERROR("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER) failed: %s",
strerror(errno));
MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
if (aUseTSync) {
if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,
SECCOMP_FILTER_FLAG_TSYNC, aProg) != 0) {
SANDBOX_LOG_ERROR("thread-synchronized seccomp failed: %s",
strerror(errno));
return false;
}
} else {
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)aProg, 0, 0)) {
SANDBOX_LOG_ERROR("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER) failed: %s",
strerror(errno));
return false;
}
}
return true;
}
// Use signals for permissions that need to be set per-thread.
// The communication channel from the signal handler back to the main thread.
static mozilla::Atomic<int> gSetSandboxDone;
// Pass the filter itself through a global.
static sock_fprog gSetSandboxFilter;
static const sock_fprog* gSetSandboxFilter;
// We have to dynamically allocate the signal number; see bug 1038900.
// This function returns the first realtime signal currently set to
@ -250,7 +269,9 @@ static bool
SetThreadSandbox()
{
if (prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
InstallSyscallFilter(&gSetSandboxFilter);
if (!InstallSyscallFilter(gSetSandboxFilter, false)) {
MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)");
}
return true;
}
return false;
@ -273,19 +294,25 @@ SetThreadSandboxHandler(int signum)
}
static void
BroadcastSetThreadSandbox(UniquePtr<sock_filter[]> aProgram, size_t aProgLen)
EnterChroot()
{
if (gChrootHelper) {
gChrootHelper->Invoke();
gChrootHelper = nullptr;
}
}
static void
BroadcastSetThreadSandbox(const sock_fprog* aFilter)
{
int signum;
pid_t pid, tid, myTid;
DIR *taskdp;
struct dirent *de;
// Note: this is an unsafe copy of the unique pointer, but it's
// zeroed (and the signal handler that would access it is removed)
// before the end of this function.
gSetSandboxFilter.filter = aProgram.get();
gSetSandboxFilter.len = static_cast<unsigned short>(aProgLen);
MOZ_RELEASE_ASSERT(static_cast<size_t>(gSetSandboxFilter.len) == aProgLen);
// This function does not own *aFilter, so this global needs to
// always be zeroed before returning.
gSetSandboxFilter = aFilter;
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
"mozilla::Atomic<int> isn't represented by an int");
@ -297,10 +324,7 @@ BroadcastSetThreadSandbox(UniquePtr<sock_filter[]> aProgram, size_t aProgLen)
MOZ_CRASH();
}
if (gChrootHelper) {
gChrootHelper->Invoke();
gChrootHelper = nullptr;
}
EnterChroot();
signum = FindFreeSignalNumber();
if (signum == 0) {
@ -416,7 +440,20 @@ BroadcastSetThreadSandbox(UniquePtr<sock_filter[]> aProgram, size_t aProgLen)
unused << closedir(taskdp);
// And now, deprivilege the main thread:
SetThreadSandbox();
gSetSandboxFilter.filter = nullptr;
gSetSandboxFilter = nullptr;
}
static void
ApplySandboxWithTSync(sock_fprog* aFilter)
{
EnterChroot();
// At this point we're committed to using tsync, because the signal
// broadcast workaround needs to access procfs. (Unless chroot
// isn't used... but this failure shouldn't happen in the first
// place, so let's not make extra special cases for it.)
if (!InstallSyscallFilter(aFilter, true)) {
MOZ_CRASH("seccomp+tsync failed, but kernel supports tsync");
}
}
// Common code for sandbox startup.
@ -445,12 +482,30 @@ SetCurrentProcessSandbox(UniquePtr<sandbox::bpf_dsl::Policy> aPolicy)
#endif
// The syscall takes a C-style array, so copy the vector into one.
UniquePtr<sock_filter[]> flatProgram(new sock_filter[program->size()]);
size_t programLen = program->size();
UniquePtr<sock_filter[]> flatProgram(new sock_filter[programLen]);
for (auto i = program->begin(); i != program->end(); ++i) {
flatProgram[i - program->begin()] = *i;
}
BroadcastSetThreadSandbox(Move(flatProgram), program->size());
sock_fprog fprog;
fprog.filter = flatProgram.get();
fprog.len = static_cast<unsigned short>(programLen);
MOZ_RELEASE_ASSERT(static_cast<size_t>(fprog.len) == programLen);
const SandboxInfo info = SandboxInfo::Get();
if (info.Test(SandboxInfo::kHasSeccompTSync)) {
if (info.Test(SandboxInfo::kVerbose)) {
SANDBOX_LOG_ERROR("using seccomp tsync");
}
ApplySandboxWithTSync(&fprog);
} else {
if (info.Test(SandboxInfo::kVerbose)) {
SANDBOX_LOG_ERROR("no tsync support; using signal broadcast");
}
BroadcastSetThreadSandbox(&fprog);
}
MOZ_RELEASE_ASSERT(!gChrootHelper, "forgot to chroot");
}
void

View File

@ -46,6 +46,7 @@ SandboxChroot::SendCommand(Command aComm)
{
MOZ_ALWAYS_ZERO(pthread_mutex_lock(&mMutex));
if (mCommand == NO_THREAD) {
MOZ_RELEASE_ASSERT(aComm == JUST_EXIT);
MOZ_ALWAYS_ZERO(pthread_mutex_unlock(&mMutex));
return false;
} else {

View File

@ -28,6 +28,29 @@ class unknown(object):
return 'UNKNOWN'
unknown = unknown() # singleton
def get_windows_version():
import ctypes
class OSVERSIONINFOEXW(ctypes.Structure):
_fields_ = [('dwOSVersionInfoSize', ctypes.c_ulong),
('dwMajorVersion', ctypes.c_ulong),
('dwMinorVersion', ctypes.c_ulong),
('dwBuildNumber', ctypes.c_ulong),
('dwPlatformId', ctypes.c_ulong),
('szCSDVersion', ctypes.c_wchar*128),
('wServicePackMajor', ctypes.c_ushort),
('wServicePackMinor', ctypes.c_ushort),
('wSuiteMask', ctypes.c_ushort),
('wProductType', ctypes.c_byte),
('wReserved', ctypes.c_byte)]
os_version = OSVERSIONINFOEXW()
os_version.dwOSVersionInfoSize = ctypes.sizeof(os_version)
retcode = ctypes.windll.Ntdll.RtlGetVersion(ctypes.byref(os_version))
if retcode != 0:
raise OSError
return os_version.dwMajorVersion, os_version.dwMinorVersion, os_version.dwBuildNumber
# get system information
info = {'os': unknown,
'processor': unknown,
@ -50,6 +73,14 @@ if system in ["Microsoft", "Windows"]:
system = os.environ.get("OS", system).replace('_', ' ')
(major, minor, _, _, service_pack) = os.sys.getwindowsversion()
info['service_pack'] = service_pack
if major >= 6 and minor >= 2:
# On windows >= 8.1 the system call that getwindowsversion uses has
# been frozen to always return the same values. In this case we call
# the RtlGetVersion API directly, which still provides meaningful
# values, at least for now.
major, minor, build_number = get_windows_version()
version = "%d.%d.%d" % (major, minor, build_number)
os_version = "%d.%d" % (major, minor)
elif system == "Linux":
if hasattr(platform, "linux_distribution"):

View File

@ -51,6 +51,9 @@ config = {
("browser/config/mozconfigs/macosx-universal/nightly",
"ac_add_options --with-branding=browser/branding/nightly",
"ac_add_options --with-branding=browser/branding/aurora"),
("browser/config/mozconfigs/macosx-universal/l10n-mozconfig",
"ac_add_options --with-branding=browser/branding/nightly",
"ac_add_options --with-branding=browser/branding/aurora"),
("browser/config/mozconfigs/whitelist",
"ac_add_options --with-branding=browser/branding/nightly",
"ac_add_options --with-branding=browser/branding/aurora"),

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More