summaryrefslogtreecommitdiffstats
path: root/dom/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'dom/bindings')
-rw-r--r--dom/bindings/BindingDeclarations.h12
-rw-r--r--dom/bindings/BindingIPCUtils.h9
-rw-r--r--dom/bindings/BindingUtils.h48
-rw-r--r--dom/bindings/Bindings.conf21
-rw-r--r--dom/bindings/Codegen.py171
-rw-r--r--dom/bindings/Configuration.py27
-rw-r--r--dom/bindings/mozwebidlcodegen/__init__.py18
-rw-r--r--dom/bindings/parser/WebIDL.py134
-rw-r--r--dom/bindings/parser/tests/test_builtin_filename.py2
-rw-r--r--dom/bindings/parser/tests/test_distinguishability.py97
-rw-r--r--dom/bindings/parser/tests/test_legacyTreatNonObjectAsNull.py11
-rw-r--r--dom/bindings/parser/tests/test_union_callback_dict.py132
-rw-r--r--dom/bindings/test/TestBindingHeader.h14
-rw-r--r--dom/bindings/test/TestCodeGen.webidl13
-rw-r--r--dom/bindings/test/TestInterfaceJS.sys.mjs8
-rw-r--r--dom/bindings/test/test_async_iterable.html2
-rw-r--r--dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml4
-rw-r--r--dom/bindings/test/test_observablearray.html16
-rw-r--r--dom/bindings/test/test_observablearray_helper.html14
-rw-r--r--dom/bindings/test/test_observablearray_proxyhandler.html10
-rw-r--r--dom/bindings/test/test_promise_rejections_from_jsimplemented.html2
-rw-r--r--dom/bindings/test/test_sequence_wrapping.html2
22 files changed, 532 insertions, 235 deletions
diff --git a/dom/bindings/BindingDeclarations.h b/dom/bindings/BindingDeclarations.h
index 24385c9fa5..c723af0021 100644
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -131,11 +131,6 @@ template <class T>
constexpr bool is_dom_union_with_typedarray_members =
std::is_base_of_v<UnionWithTypedArraysBase, T>;
-struct EnumEntry {
- const char* value;
- size_t length;
-};
-
enum class CallerType : uint32_t;
class MOZ_STACK_CLASS GlobalObject {
@@ -562,6 +557,13 @@ JS::Handle<JSObject*> GetPerInterfaceObjectHandle(
JSContext* aCx, size_t aSlotId, CreateInterfaceObjectsMethod aCreator,
bool aDefineOnGlobal);
+namespace binding_detail {
+
+template <typename Enum>
+struct EnumStrings;
+
+} // namespace binding_detail
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/bindings/BindingIPCUtils.h b/dom/bindings/BindingIPCUtils.h
index 5598e5896b..5cf6edb7a7 100644
--- a/dom/bindings/BindingIPCUtils.h
+++ b/dom/bindings/BindingIPCUtils.h
@@ -6,9 +6,18 @@
#ifndef _mozilla_dom_BindingIPCUtils_h
#define _mozilla_dom_BindingIPCUtils_h
+#include "mozilla/EnumTypeTraits.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "ipc/EnumSerializer.h"
+namespace mozilla::dom {
+
+template <class Enum>
+using WebIDLEnumSerializer = IPC::ContiguousEnumSerializerInclusive<
+ Enum, ContiguousEnumValues<Enum>::min, ContiguousEnumValues<Enum>::max>;
+
+} // namespace mozilla::dom
+
namespace IPC {
template <>
struct ParamTraits<mozilla::dom::CallerType>
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index df3c509ab7..dd7a42b670 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -24,6 +24,8 @@
#include "mozilla/Array.h"
#include "mozilla/Assertions.h"
#include "mozilla/DeferredFinalize.h"
+#include "mozilla/EnumTypeTraits.h"
+#include "mozilla/EnumeratedRange.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingDeclarations.h"
@@ -1343,26 +1345,27 @@ inline bool EnumValueNotFound<true>(BindingCallContext& cx,
deflated.get(), type);
}
+namespace binding_detail {
+
template <typename CharT>
inline int FindEnumStringIndexImpl(const CharT* chars, size_t length,
- const EnumEntry* values) {
- int i = 0;
- for (const EnumEntry* value = values; value->value; ++value, ++i) {
- if (length != value->length) {
+ const Span<const nsLiteralCString>& values) {
+ for (size_t i = 0; i < values.Length(); ++i) {
+ const nsLiteralCString& value = values[i];
+ if (length != value.Length()) {
continue;
}
bool equal = true;
- const char* val = value->value;
for (size_t j = 0; j != length; ++j) {
- if (unsigned(val[j]) != unsigned(chars[j])) {
+ if (unsigned(value.CharAt(j)) != unsigned(chars[j])) {
equal = false;
break;
}
}
if (equal) {
- return i;
+ return (int)i;
}
}
@@ -1371,8 +1374,9 @@ inline int FindEnumStringIndexImpl(const CharT* chars, size_t length,
template <bool InvalidValueFatal>
inline bool FindEnumStringIndex(BindingCallContext& cx, JS::Handle<JS::Value> v,
- const EnumEntry* values, const char* type,
- const char* sourceDescription, int* index) {
+ const Span<const nsLiteralCString>& values,
+ const char* type, const char* sourceDescription,
+ int* index) {
// JS_StringEqualsAscii is slow as molasses, so don't use it here.
JS::Rooted<JSString*> str(cx, JS::ToString(cx, v));
if (!str) {
@@ -1405,6 +1409,31 @@ inline bool FindEnumStringIndex(BindingCallContext& cx, JS::Handle<JS::Value> v,
return EnumValueNotFound<InvalidValueFatal>(cx, str, type, sourceDescription);
}
+} // namespace binding_detail
+
+template <typename Enum, class StringT>
+inline Maybe<Enum> StringToEnum(const StringT& aString) {
+ int index = binding_detail::FindEnumStringIndexImpl(
+ aString.BeginReading(), aString.Length(),
+ binding_detail::EnumStrings<Enum>::Values);
+ return index >= 0 ? Some(static_cast<Enum>(index)) : Nothing();
+}
+
+template <typename Enum>
+inline const nsCString& GetEnumString(Enum stringId) {
+ MOZ_RELEASE_ASSERT(
+ static_cast<size_t>(stringId) <
+ mozilla::ArrayLength(binding_detail::EnumStrings<Enum>::Values));
+ return binding_detail::EnumStrings<Enum>::Values[static_cast<size_t>(
+ stringId)];
+}
+
+template <typename Enum>
+constexpr mozilla::detail::EnumeratedRange<Enum> MakeWebIDLEnumeratedRange() {
+ return MakeInclusiveEnumeratedRange(ContiguousEnumValues<Enum>::min,
+ ContiguousEnumValues<Enum>::max);
+}
+
inline nsWrapperCache* GetWrapperCache(const ParentObject& aParentObject) {
return aParentObject.mWrapperCache;
}
@@ -3255,6 +3284,7 @@ already_AddRefed<Promise> CreateRejectedPromiseFromThrownException(
} // namespace binding_detail
} // namespace dom
+
} // namespace mozilla
#endif /* mozilla_dom_BindingUtils_h__ */
diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
index bf736e9ac2..7eed2593aa 100644
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1006,6 +1006,18 @@ DOMInterfaces = {
'wrapperCache': False,
},
+'TrustedHTML': {
+ 'wrapperCache': False,
+},
+
+'TrustedScript': {
+ 'wrapperCache': False,
+},
+
+'TrustedScriptURL': {
+ 'wrapperCache': False,
+},
+
'UserInteraction': {
'nativeType': 'mozilla::telemetry::UserInteractionStopwatch',
'headerFile': 'mozilla/telemetry/Stopwatch.h',
@@ -1527,6 +1539,10 @@ DOMInterfaces = {
'nativeType': 'mozilla::glean::GleanText',
'headerFile': 'mozilla/glean/bindings/Text.h',
},
+'GleanObject': {
+ 'nativeType': 'mozilla::glean::GleanObject',
+ 'headerFile': 'mozilla/glean/bindings/Object.h',
+},
'Window': {
'nativeType': 'nsGlobalWindowInner',
@@ -1962,6 +1978,11 @@ if buildconfig.substs.get("ENABLE_TESTS", False):
'register': False,
},
+ 'TestCallbackDictUnionOverload' : {
+ 'headerFile': 'TestBindingHeader.h',
+ 'register': False,
+ },
+
})
if buildconfig.substs.get("MOZ_DEBUG", False):
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 80efa81ec5..7a6a28bffc 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -11,7 +11,6 @@ import re
import string
import textwrap
-import six
from Configuration import (
Descriptor,
MemberIsLegacyUnforgeable,
@@ -51,7 +50,6 @@ LEGACYCALLER_HOOK_NAME = "_legacycaller"
RESOLVE_HOOK_NAME = "_resolve"
MAY_RESOLVE_HOOK_NAME = "_mayResolve"
NEW_ENUMERATE_HOOK_NAME = "_newEnumerate"
-ENUM_ENTRY_VARIABLE_NAME = "strings"
INSTANCE_RESERVED_SLOTS = 1
# This size is arbitrary. It is a power of 2 to make using it as a modulo
@@ -247,12 +245,6 @@ def wantsGetWrapperCache(desc):
)
-# We'll want to insert the indent at the beginnings of lines, but we
-# don't want to indent empty lines. So only indent lines that have a
-# non-newline character on them.
-lineStartDetector = re.compile("^(?=[^\n#])", re.MULTILINE)
-
-
def indent(s, indentLevel=2):
"""
Indent C++ code.
@@ -260,9 +252,16 @@ def indent(s, indentLevel=2):
Weird secret feature: this doesn't indent lines that start with # (such as
#include lines or #ifdef/#endif).
"""
- if s == "":
- return s
- return re.sub(lineStartDetector, indentLevel * " ", s)
+
+ # We'll want to insert the indent at the beginnings of lines, but we
+ # don't want to indent empty lines.
+ padding = indentLevel * " "
+ return "\n".join(
+ [
+ (padding + line) if line and line[0] != "#" else line
+ for line in s.split("\n")
+ ]
+ )
# dedent() and fill() are often called on the same string multiple
@@ -1600,7 +1599,7 @@ class CGHeaders(CGWrapper):
def getDeclarationFilename(decl):
# Use our local version of the header, not the exported one, so that
# test bindings, which don't export, will work correctly.
- basename = os.path.basename(decl.filename())
+ basename = os.path.basename(decl.filename)
return basename.replace(".webidl", "Binding.h")
@staticmethod
@@ -7046,7 +7045,10 @@ def getJSToNativeConversionInfo(
"""
{
int index;
- if (!FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val}, ${values}, "${enumtype}", "${sourceDescription}", &index)) {
+ if (!binding_detail::FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val},
+ binding_detail::EnumStrings<${enumtype}>::Values,
+ "${enumtype}", "${sourceDescription}",
+ &index)) {
$*{exceptionCode}
}
$*{handleInvalidEnumValueCode}
@@ -7054,7 +7056,6 @@ def getJSToNativeConversionInfo(
}
""",
enumtype=enumName,
- values=enumName + "Values::" + ENUM_ENTRY_VARIABLE_NAME,
invalidEnumValueFatal=toStringBool(invalidEnumValueFatal),
handleInvalidEnumValueCode=handleInvalidEnumValueCode,
exceptionCode=exceptionCode,
@@ -12330,20 +12331,13 @@ def getEnumValueName(value):
raise SyntaxError('"_empty" is not an IDL enum value we support yet')
if value == "":
return "_empty"
- nativeName = MakeNativeName(value)
- if nativeName == "EndGuard_":
- raise SyntaxError(
- 'Enum value "' + value + '" cannot be used because it'
- " collides with our internal EndGuard_ value. Please"
- " rename our internal EndGuard_ to something else"
- )
- return nativeName
+ return MakeNativeName(value)
class CGEnumToJSValue(CGAbstractMethod):
def __init__(self, enum):
enumType = enum.identifier.name
- self.stringsArray = enumType + "Values::" + ENUM_ENTRY_VARIABLE_NAME
+ self.stringsArray = "binding_detail::EnumStrings<" + enumType + ">::Values"
CGAbstractMethod.__init__(
self,
None,
@@ -12361,8 +12355,8 @@ class CGEnumToJSValue(CGAbstractMethod):
"""
MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(${strings}));
JSString* resultStr =
- JS_NewStringCopyN(aCx, ${strings}[uint32_t(aArgument)].value,
- ${strings}[uint32_t(aArgument)].length);
+ JS_NewStringCopyN(aCx, ${strings}[uint32_t(aArgument)].BeginReading(),
+ ${strings}[uint32_t(aArgument)].Length());
if (!resultStr) {
return false;
}
@@ -12377,80 +12371,54 @@ class CGEnum(CGThing):
def __init__(self, enum):
CGThing.__init__(self)
self.enum = enum
- entryDecl = fill(
- """
- extern const EnumEntry ${entry_array}[${entry_count}];
-
- static constexpr size_t Count = ${real_entry_count};
-
- // Our "${entry_array}" contains an extra entry with a null string.
- static_assert(mozilla::ArrayLength(${entry_array}) - 1 == Count,
- "Mismatch between enum strings and enum count");
-
- static_assert(static_cast<size_t>(${name}::EndGuard_) == Count,
- "Mismatch between enum value and enum count");
-
- inline auto GetString(${name} stringId) {
- MOZ_ASSERT(static_cast<${type}>(stringId) < Count);
- const EnumEntry& entry = ${entry_array}[static_cast<${type}>(stringId)];
- return Span<const char>{entry.value, entry.length};
- }
- """,
- entry_array=ENUM_ENTRY_VARIABLE_NAME,
- entry_count=self.nEnumStrings(),
- # -1 because nEnumStrings() includes a string for EndGuard_
- real_entry_count=self.nEnumStrings() - 1,
- name=self.enum.identifier.name,
- type=self.underlyingType(),
- )
strings = CGNamespace(
- self.stringsNamespace(),
+ "binding_detail",
CGGeneric(
- declare=entryDecl,
+ declare=fill(
+ """
+ template <> struct EnumStrings<${name}> {
+ static const nsLiteralCString Values[${count}];
+ };
+ """,
+ name=self.enum.identifier.name,
+ count=self.nEnumStrings(),
+ ),
define=fill(
"""
- extern const EnumEntry ${name}[${count}] = {
- $*{entries}
- { nullptr, 0 }
- };
- """,
- name=ENUM_ENTRY_VARIABLE_NAME,
+ const nsLiteralCString EnumStrings<${name}>::Values[${count}] = {
+ $*{entries}
+ };
+ """,
+ name=self.enum.identifier.name,
count=self.nEnumStrings(),
- entries="".join(
- '{"%s", %d},\n' % (val, len(val)) for val in self.enum.values()
- ),
+ entries="".join('"%s"_ns,\n' % val for val in self.enum.values()),
),
),
)
toJSValue = CGEnumToJSValue(enum)
self.cgThings = CGList([strings, toJSValue], "\n")
- def stringsNamespace(self):
- return self.enum.identifier.name + "Values"
-
def nEnumStrings(self):
- return len(self.enum.values()) + 1
+ return len(self.enum.values())
- def underlyingType(self):
- count = self.nEnumStrings()
+ @staticmethod
+ def underlyingType(enum):
+ count = len(enum.values())
if count <= 256:
return "uint8_t"
if count <= 65536:
return "uint16_t"
- raise ValueError(
- "Enum " + self.enum.identifier.name + " has more than 65536 values"
- )
+ raise ValueError("Enum " + enum.identifier.name + " has more than 65536 values")
def declare(self):
decl = fill(
"""
enum class ${name} : ${ty} {
$*{enums}
- EndGuard_
};
""",
name=self.enum.identifier.name,
- ty=self.underlyingType(),
+ ty=CGEnum.underlyingType(self.enum),
enums=",\n".join(map(getEnumValueName, self.enum.values())) + ",\n",
)
@@ -12463,6 +12431,39 @@ class CGEnum(CGThing):
return self.enum.getDeps()
+class CGMaxContiguousEnumValue(CGThing):
+ def __init__(self, enum):
+ CGThing.__init__(self)
+ self.enum = enum
+
+ def declare(self):
+ enumValues = self.enum.values()
+ return fill(
+ """
+ template <>
+ struct MaxContiguousEnumValue<dom::${name}>
+ {
+ static constexpr dom::${name} value = dom::${name}::${maxValue};
+
+ static_assert(static_cast<${ty}>(dom::${name}::${minValue}) == 0,
+ "We rely on this in ContiguousEnumValues");
+ static_assert(mozilla::ArrayLength(dom::binding_detail::EnumStrings<dom::${name}>::Values) - 1 == UnderlyingValue(value),
+ "Mismatch between enum strings and enum count");
+ };
+ """,
+ name=self.enum.identifier.name,
+ ty=CGEnum.underlyingType(self.enum),
+ maxValue=getEnumValueName(enumValues[-1]),
+ minValue=getEnumValueName(enumValues[0]),
+ )
+
+ def define(self):
+ return ""
+
+ def deps(self):
+ return self.enum.getDeps()
+
+
def getUnionAccessorSignatureType(type, descriptorProvider):
"""
Returns the types that are used in the getter and setter signatures for
@@ -14867,7 +14868,7 @@ class CGCountMaybeMissingProperty(CGAbstractMethod):
generate nested switches) or strings to use for case bodies.
"""
cases = []
- for label, body in sorted(six.iteritems(switchDecriptor["cases"])):
+ for label, body in sorted(switchDecriptor["cases"].items()):
if isinstance(body, dict):
body = self.gen_switch(body)
cases.append(
@@ -18412,7 +18413,7 @@ class CGGlobalNames(CGGeneric):
),
)
- entries.append((name, nativeEntry))
+ entries.append((name.encode(), nativeEntry))
# Unfortunately, when running tests, we may have no entries.
# PerfectHash will assert if we give it an empty set of entries, so we
@@ -18569,7 +18570,7 @@ class ForwardDeclarationBuilder:
]
)
)
- for namespace, child in sorted(six.iteritems(self.children)):
+ for namespace, child in sorted(self.children.items()):
decls.append(CGNamespace(namespace, child._build(atTopLevel=False)))
cg = CGList(decls, "\n")
@@ -19073,9 +19074,11 @@ class CGBindingRoot(CGThing):
# Do codegen for all the enums
enums = config.getEnums(webIDLFile)
cgthings.extend(CGEnum(e) for e in enums)
+ maxEnumValues = CGList([CGMaxContiguousEnumValue(e) for e in enums], "\n")
bindingDeclareHeaders["mozilla/Span.h"] = enums
bindingDeclareHeaders["mozilla/ArrayUtils.h"] = enums
+ bindingDeclareHeaders["mozilla/EnumTypeTraits.h"] = enums
hasCode = descriptors or callbackDescriptors or dictionaries or callbacks
bindingHeaders["mozilla/dom/BindingUtils.h"] = hasCode
@@ -19175,7 +19178,13 @@ class CGBindingRoot(CGThing):
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
# Wrap all of that in our namespaces.
- curr = CGNamespace.build(["mozilla", "dom"], CGWrapper(curr, pre="\n"))
+
+ if len(maxEnumValues) > 0:
+ curr = CGNamespace("dom", CGWrapper(curr, pre="\n"))
+ curr = CGWrapper(CGList([curr, maxEnumValues], "\n\n"), post="\n\n")
+ curr = CGNamespace("mozilla", CGWrapper(curr, pre="\n"))
+ else:
+ curr = CGNamespace.build(["mozilla", "dom"], CGWrapper(curr, pre="\n"))
curr = CGList(
[
@@ -19194,12 +19203,10 @@ class CGBindingRoot(CGThing):
# Add header includes.
bindingHeaders = [
- header for header, include in six.iteritems(bindingHeaders) if include
+ header for header, include in bindingHeaders.items() if include
]
bindingDeclareHeaders = [
- header
- for header, include in six.iteritems(bindingDeclareHeaders)
- if include
+ header for header, include in bindingDeclareHeaders.items() if include
]
curr = CGHeaders(
@@ -24681,7 +24688,7 @@ class CGEventRoot(CGThing):
self.root,
pre=(
AUTOGENERATED_WITH_SOURCE_WARNING_COMMENT
- % os.path.basename(descriptor.interface.filename())
+ % os.path.basename(descriptor.interface.filename)
),
)
diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py
index 266a8db34a..354a450de6 100644
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -7,7 +7,6 @@ import itertools
import os
from collections import defaultdict
-import six
from WebIDL import IDLIncludesStatement
autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
@@ -98,7 +97,7 @@ class Configuration(DescriptorProvider):
# different .webidl file than their LHS interface. Make sure we
# don't have any of those. See similar block below for partial
# interfaces!
- if thing.interface.filename() != thing.filename():
+ if thing.interface.filename != thing.filename:
raise TypeError(
"The binding build system doesn't really support "
"'includes' statements which don't appear in the "
@@ -124,7 +123,7 @@ class Configuration(DescriptorProvider):
# statements!
if not thing.isExternal():
for partial in thing.getPartials():
- if partial.filename() != thing.filename():
+ if partial.filename != thing.filename:
raise TypeError(
"The binding build system doesn't really support "
"partial interfaces/namespaces/mixins which don't "
@@ -146,7 +145,7 @@ class Configuration(DescriptorProvider):
or iface.getExtendedAttribute("Func")
== ["nsContentUtils::IsCallerChromeOrFuzzingEnabled"]
or not iface.hasInterfaceObject()
- or isInWebIDLRoot(iface.filename())
+ or isInWebIDLRoot(iface.filename)
):
raise TypeError(
"Interfaces which are exposed to the web may only be "
@@ -187,7 +186,7 @@ class Configuration(DescriptorProvider):
self.descriptorsByFile = {}
for d in self.descriptors:
- self.descriptorsByFile.setdefault(d.interface.filename(), []).append(d)
+ self.descriptorsByFile.setdefault(d.interface.filename, []).append(d)
self.enums = [e for e in parseData if e.isEnum()]
@@ -212,19 +211,19 @@ class Configuration(DescriptorProvider):
def addUnion(t):
filenamesForUnion = self.filenamesPerUnion[t.name]
- if t.filename() not in filenamesForUnion:
+ if t.filename not in filenamesForUnion:
# We have a to be a bit careful: some of our built-in
# typedefs are for unions, and those unions end up with
# "<unknown>" as the filename. If that happens, we don't
# want to try associating this union with one particular
# filename, since there isn't one to associate it with,
# really.
- if t.filename() == "<unknown>":
+ if t.filename == "<unknown>":
uniqueFilenameForUnion = None
elif len(filenamesForUnion) == 0:
# This is the first file that we found a union with this
# name in, record the union as part of the file.
- uniqueFilenameForUnion = t.filename()
+ uniqueFilenameForUnion = t.filename
else:
# We already found a file that contains a union with
# this name.
@@ -246,7 +245,7 @@ class Configuration(DescriptorProvider):
# the filename as None, so that we can detect that.
uniqueFilenameForUnion = None
self.unionsPerFilename[uniqueFilenameForUnion].append(t)
- filenamesForUnion.add(t.filename())
+ filenamesForUnion.add(t.filename)
def addUnions(t):
t = findInnermostType(t)
@@ -498,7 +497,7 @@ class Configuration(DescriptorProvider):
# Collect up our filters, because we may have a webIDLFile filter that
# we always want to apply first.
tofilter = [(lambda x: x.interface.isExternal(), False)]
- for key, val in six.iteritems(filters):
+ for key, val in filters.items():
if key == "webIDLFile":
# Special-case this part to make it fast, since most of our
# getDescriptors calls are conditioned on a webIDLFile. We may
@@ -571,13 +570,13 @@ class Configuration(DescriptorProvider):
return curr
def getEnums(self, webIDLFile):
- return [e for e in self.enums if e.filename() == webIDLFile]
+ return [e for e in self.enums if e.filename == webIDLFile]
def getDictionaries(self, webIDLFile):
- return [d for d in self.dictionaries if d.filename() == webIDLFile]
+ return [d for d in self.dictionaries if d.filename == webIDLFile]
def getCallbacks(self, webIDLFile):
- return [c for c in self.callbacks if c.filename() == webIDLFile]
+ return [c for c in self.callbacks if c.filename == webIDLFile]
def getDescriptor(self, interfaceName):
"""
@@ -704,7 +703,7 @@ class Descriptor(DescriptorProvider):
# import it here, sadly.
# Use our local version of the header, not the exported one, so that
# test bindings, which don't export, will work correctly.
- basename = os.path.basename(self.interface.filename())
+ basename = os.path.basename(self.interface.filename)
headerDefault = basename.replace(".webidl", "Binding.h")
else:
if not self.interface.isExternal() and self.interface.getExtendedAttribute(
diff --git a/dom/bindings/mozwebidlcodegen/__init__.py b/dom/bindings/mozwebidlcodegen/__init__.py
index 8b6e62f345..3e8c6aa420 100644
--- a/dom/bindings/mozwebidlcodegen/__init__.py
+++ b/dom/bindings/mozwebidlcodegen/__init__.py
@@ -14,7 +14,6 @@ import os
from copy import deepcopy
import mozpack.path as mozpath
-import six
from mach.mixin.logging import LoggingMixin
from mozbuild.makeutil import Makefile
from mozbuild.pythonutil import iter_modules_in_path
@@ -339,10 +338,8 @@ class WebIDLCodegenManager(LoggingMixin):
if self._make_deps_path:
mk = Makefile()
codegen_rule = mk.create_rule([self._make_deps_target])
- codegen_rule.add_dependencies(
- six.ensure_text(s) for s in global_hashes.keys()
- )
- codegen_rule.add_dependencies(six.ensure_text(p) for p in self._input_paths)
+ codegen_rule.add_dependencies(global_hashes.keys())
+ codegen_rule.add_dependencies(self._input_paths)
with FileAvoidWrite(self._make_deps_path) as fh:
mk.dump(fh)
@@ -359,7 +356,12 @@ class WebIDLCodegenManager(LoggingMixin):
example_paths = self._example_paths(interface)
for path in example_paths:
- print("Generating {}".format(path))
+ self.log(
+ logging.INFO,
+ "webidl_generate_example_files",
+ {"filename": path},
+ "Generating WebIDL example files derived from {filename}",
+ )
return self._maybe_write_codegen(root, *example_paths)
@@ -380,7 +382,7 @@ class WebIDLCodegenManager(LoggingMixin):
for path in sorted(self._input_paths):
with io.open(path, "r", encoding="utf-8") as fh:
data = fh.read()
- hashes[path] = hashlib.sha1(six.ensure_binary(data)).hexdigest()
+ hashes[path] = hashlib.sha1(data.encode()).hexdigest()
parser.parse(data, path)
# Only these directories may contain WebIDL files with interfaces
@@ -494,7 +496,7 @@ class WebIDLCodegenManager(LoggingMixin):
for name in changedDictionaryNames:
d = self._config.getDictionaryIfExists(name)
if d:
- changed_inputs.add(d.filename())
+ changed_inputs.add(d.filename)
# Only use paths that are known to our current state.
# This filters out files that were deleted or changed type (e.g. from
diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py
index 9101e14cf2..43f9ec12f1 100644
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -43,25 +43,22 @@ def parseInt(literal):
return value * sign
-def enum(*names, **kw):
- class Foo(object):
- attrs = OrderedDict()
+# This is surprisingly faster than using the enum.IntEnum type (which doesn't
+# support 'base' anyway)
+def enum(*names, base=None):
+ if base is not None:
+ names = base.attrs + names
- def __init__(self, names):
- for v, k in enumerate(names):
- self.attrs[k] = v
-
- def __getattr__(self, attr):
- if attr in self.attrs:
- return self.attrs[attr]
- raise AttributeError
+ class CustomEnumType(object):
+ attrs = names
def __setattr__(self, name, value): # this makes it read-only
raise NotImplementedError
- if "base" not in kw:
- return Foo(names)
- return Foo(chain(kw["base"].attrs.keys(), names))
+ for v, k in enumerate(names):
+ setattr(CustomEnumType, k, v)
+
+ return CustomEnumType()
class WebIDLError(Exception):
@@ -85,13 +82,10 @@ class Location(object):
self._lineno = lineno
self._lexpos = lexpos
self._lexdata = lexer.lexdata
- self._file = filename if filename else "<unknown>"
+ self.filename = filename if filename else "<unknown>"
def __eq__(self, other):
- return self._lexpos == other._lexpos and self._file == other._file
-
- def filename(self):
- return self._file
+ return self._lexpos == other._lexpos and self.filename == other.filename
def resolve(self):
if self._line:
@@ -110,7 +104,7 @@ class Location(object):
def get(self):
self.resolve()
- return "%s line %s:%s" % (self._file, self._lineno, self._colno)
+ return "%s line %s:%s" % (self.filename, self._lineno, self._colno)
def _pointerline(self):
return " " * self._colno + "^"
@@ -118,7 +112,7 @@ class Location(object):
def __str__(self):
self.resolve()
return "%s line %s:%s\n%s\n%s" % (
- self._file,
+ self.filename,
self._lineno,
self._colno,
self._line,
@@ -129,13 +123,11 @@ class Location(object):
class BuiltinLocation(object):
def __init__(self, text):
self.msg = text + "\n"
+ self.filename = "<builtin>"
def __eq__(self, other):
return isinstance(other, BuiltinLocation) and self.msg == other.msg
- def filename(self):
- return "<builtin>"
-
def resolve(self):
pass
@@ -153,9 +145,7 @@ class IDLObject(object):
def __init__(self, location):
self.location = location
self.userData = dict()
-
- def filename(self):
- return self.location.filename()
+ self.filename = location and location.filename
def isInterface(self):
return False
@@ -220,8 +210,8 @@ class IDLObject(object):
visited.add(self)
deps = set()
- if self.filename() != "<builtin>":
- deps.add(self.filename())
+ if self.filename != "<builtin>":
+ deps.add(self.filename)
for d in self._getDependentObjects():
deps.update(d.getDeps(visited))
@@ -3032,6 +3022,9 @@ class IDLRecordType(IDLParametrizedType):
if other.isUnion():
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
+ if other.isCallback():
+ # Let other determine if it's a LegacyTreatNonObjectAsNull callback
+ return other.isDistinguishableFrom(self)
return (
other.isPrimitive()
or other.isString()
@@ -3490,7 +3483,7 @@ class IDLWrapperType(IDLType):
or other.isSequence()
or other.isRecord()
)
- if self.isDictionary() and (other.nullable() or other.isUndefined()):
+ if self.isDictionary() and other.nullable():
return False
if (
other.isPrimitive()
@@ -3499,28 +3492,51 @@ class IDLWrapperType(IDLType):
or other.isSequence()
):
return True
- if self.isDictionary():
+
+ # If this needs to handle other dictionary-like types we probably need
+ # some additional checks first.
+ assert self.isDictionaryLike() == (
+ self.isDictionary() or self.isCallbackInterface()
+ )
+ if self.isDictionaryLike():
+ if other.isCallback():
+ # Let other determine if it's a LegacyTreatNonObjectAsNull callback
+ return other.isDistinguishableFrom(self)
+
+ assert (
+ other.isNonCallbackInterface()
+ or other.isAny()
+ or other.isUndefined()
+ or other.isObject()
+ or other.isDictionaryLike()
+ )
+ # At this point, dictionary-like (for 'self') and interface-like
+ # (for 'other') are the only two that are distinguishable.
+ # any is the union of all non-union types, so it's not distinguishable
+ # from other unions (because it is a union itself), or from all
+ # non-union types (because it has all of them as its members).
return other.isNonCallbackInterface()
- assert self.isInterface()
- if other.isInterface():
+ assert self.isNonCallbackInterface()
+
+ if other.isUndefined() or other.isDictionaryLike() or other.isCallback():
+ return True
+
+ if other.isNonCallbackInterface():
if other.isSpiderMonkeyInterface():
# Just let |other| handle things
return other.isDistinguishableFrom(self)
+
assert self.isGeckoInterface() and other.isGeckoInterface()
if self.inner.isExternal() or other.unroll().inner.isExternal():
return self != other
- return len(
- self.inner.interfacesBasedOnSelf
- & other.unroll().inner.interfacesBasedOnSelf
- ) == 0 and (self.isNonCallbackInterface() or other.isNonCallbackInterface())
- if (
- other.isUndefined()
- or other.isDictionary()
- or other.isCallback()
- or other.isRecord()
- ):
- return self.isNonCallbackInterface()
+ return (
+ len(
+ self.inner.interfacesBasedOnSelf
+ & other.unroll().inner.interfacesBasedOnSelf
+ )
+ == 0
+ )
# Not much else |other| can be.
# any is the union of all non-union types, so it's not distinguishable
@@ -6067,6 +6083,9 @@ class IDLCallbackType(IDLType):
if other.isUnion():
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
+ # Callbacks without `LegacyTreatNonObjectAsNull` are distinguishable from Dictionary likes
+ if other.isDictionaryLike():
+ return not self.callback._treatNonObjectAsNull
return (
other.isUndefined()
or other.isPrimitive()
@@ -6943,7 +6962,7 @@ class IDLExtendedAttribute(IDLObject):
class Tokenizer(object):
- tokens = ["INTEGER", "FLOATLITERAL", "IDENTIFIER", "STRING", "WHITESPACE", "OTHER"]
+ tokens = ["INTEGER", "FLOATLITERAL", "IDENTIFIER", "STRING", "COMMENTS", "OTHER"]
def t_FLOATLITERAL(self, t):
r"(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN"
@@ -6979,17 +6998,19 @@ class Tokenizer(object):
t.value = t.value[1:-1]
return t
- def t_WHITESPACE(self, t):
- r"[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+"
+ t_ignore = "\t\n\r "
+
+ def t_COMMENTS(self, t):
+ r"//[^\n]*|/\*(?s:.)*?\*/"
pass
def t_ELLIPSIS(self, t):
r"\.\.\."
- t.type = self.keywords.get(t.value)
+ t.type = "ELLIPSIS"
return t
def t_OTHER(self, t):
- r"[^\t\n\r 0-9A-Z_a-z]"
+ r"[^0-9A-Z_a-z]"
t.type = self.keywords.get(t.value, "OTHER")
return t
@@ -7086,14 +7107,14 @@ class Tokenizer(object):
if lexer:
self.lexer = lexer
else:
- self.lexer = lex.lex(object=self, reflags=re.DOTALL)
+ self.lexer = lex.lex(object=self)
class SqueakyCleanLogger(object):
errorWhitelist = [
- # Web IDL defines the WHITESPACE token, but doesn't actually
+ # Web IDL defines the COMMENTS token, but doesn't actually
# use it ... so far.
- "Token 'WHITESPACE' defined, but not used",
+ "Token 'COMMENTS' defined, but not used",
# And that means we have an unused token
"There is 1 unused token",
# Web IDL defines a OtherOrComma rule that's only used in
@@ -9097,13 +9118,8 @@ class Parser(Tokenizer):
production.validate()
# De-duplicate self._productions, without modifying its order.
- seen = set()
- result = []
- for p in self._productions:
- if p not in seen:
- seen.add(p)
- result.append(p)
- return result
+ result = dict.fromkeys(self._productions)
+ return list(result.keys())
def reset(self):
return Parser(lexer=self.lexer)
diff --git a/dom/bindings/parser/tests/test_builtin_filename.py b/dom/bindings/parser/tests/test_builtin_filename.py
index 25ed32befc..97e8cb061f 100644
--- a/dom/bindings/parser/tests/test_builtin_filename.py
+++ b/dom/bindings/parser/tests/test_builtin_filename.py
@@ -8,4 +8,4 @@ def WebIDLTest(parser, harness):
)
attr = parser.finish()[0].members[0]
- harness.check(attr.type.filename(), "<builtin>", "Filename on builtin type")
+ harness.check(attr.type.filename, "<builtin>", "Filename on builtin type")
diff --git a/dom/bindings/parser/tests/test_distinguishability.py b/dom/bindings/parser/tests/test_distinguishability.py
index 8497490b1f..caf726c16b 100644
--- a/dom/bindings/parser/tests/test_distinguishability.py
+++ b/dom/bindings/parser/tests/test_distinguishability.py
@@ -228,7 +228,9 @@ def WebIDLTest(parser, harness):
and (a != "any" and a != "Promise<any>" and a != "Promise<any>?")
]
- unions = ["(long or Callback)", "(long or Dict)"]
+ unionsWithCallback = ["(long or Callback)"]
+ unionsNoCallback = ["(long or Dict)"]
+ unions = unionsWithCallback + unionsNoCallback
numerics = ["long", "short", "long?", "short?"]
booleans = ["boolean", "boolean?"]
undefineds = ["undefined", "undefined?"]
@@ -265,7 +267,7 @@ def WebIDLTest(parser, harness):
"Date?",
"any",
"Promise<any>?",
- ] + allBut(unions, ["(long or Callback)"])
+ ] + unionsNoCallback
sequences = ["sequence<long>", "sequence<short>"]
nonUserObjects = nonObjects + interfaces + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"])
@@ -282,17 +284,14 @@ def WebIDLTest(parser, harness):
"record<ByteString, long>",
"record<UTF8String, long>",
] # JSString not supported in records
- dictionaryLike = (
- [
- "Dict",
- "Dict2",
- "CallbackInterface",
- "CallbackInterface?",
- "CallbackInterface2",
- ]
- + records
- + allBut(unions, ["(long or Callback)"])
- )
+ dicts = ["Dict", "Dict2"]
+ callbacks = ["Callback", "Callback2"]
+ callbackInterfaces = [
+ "CallbackInterface",
+ "CallbackInterface?",
+ "CallbackInterface2",
+ ]
+ dictionaryLike = dicts + callbackInterfaces + records + unionsNoCallback
# Build a representation of the distinguishability table as a dict
# of dicts, holding True values where needed, holes elsewhere.
@@ -327,23 +326,60 @@ def WebIDLTest(parser, harness):
setDistinguishable(
"UnrelatedInterface", allBut(argTypes, ["object", "UnrelatedInterface"])
)
- setDistinguishable("CallbackInterface", allBut(nonUserObjects, undefineds))
setDistinguishable(
- "CallbackInterface?", allBut(nonUserObjects, nullables + undefineds)
+ "CallbackInterface",
+ allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
+ )
+ setDistinguishable(
+ "CallbackInterface?",
+ allBut(nonUserObjects + callbacks + unionsWithCallback, nullables + undefineds),
+ )
+ setDistinguishable(
+ "CallbackInterface2",
+ allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
)
- setDistinguishable("CallbackInterface2", allBut(nonUserObjects, undefineds))
setDistinguishable("object", nonObjects)
- setDistinguishable("Callback", nonUserObjects)
- setDistinguishable("Callback2", nonUserObjects)
- setDistinguishable("Dict", allBut(nonUserObjects, nullables + undefineds))
- setDistinguishable("Dict2", allBut(nonUserObjects, nullables + undefineds))
- setDistinguishable("sequence<long>", allBut(argTypes, sequences + ["object"]))
- setDistinguishable("sequence<short>", allBut(argTypes, sequences + ["object"]))
- setDistinguishable("record<DOMString, object>", allBut(nonUserObjects, undefineds))
- setDistinguishable("record<USVString, Dict>", allBut(nonUserObjects, undefineds))
+ setDistinguishable(
+ "Callback",
+ nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
+ )
+ setDistinguishable(
+ "Callback2",
+ nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
+ )
+ setDistinguishable(
+ "Dict",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
+ )
+ setDistinguishable(
+ "Dict2",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
+ )
+ setDistinguishable(
+ "sequence<long>",
+ allBut(argTypes, sequences + ["object"]),
+ )
+ setDistinguishable(
+ "sequence<short>",
+ allBut(argTypes, sequences + ["object"]),
+ )
+ setDistinguishable(
+ "record<DOMString, object>",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
+ )
+ setDistinguishable(
+ "record<USVString, Dict>",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
+ )
# JSString not supported in records
- setDistinguishable("record<ByteString, long>", allBut(nonUserObjects, undefineds))
- setDistinguishable("record<UTF8String, long>", allBut(nonUserObjects, undefineds))
+ setDistinguishable(
+ "record<ByteString, long>",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
+ )
+ setDistinguishable(
+ "record<UTF8String, long>",
+ allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
+ )
setDistinguishable("any", [])
setDistinguishable("Promise<any>", [])
setDistinguishable("Promise<any>?", [])
@@ -358,9 +394,13 @@ def WebIDLTest(parser, harness):
setDistinguishable(
"Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])
)
- setDistinguishable("(long or Callback)", allBut(nonUserObjects, numerics))
setDistinguishable(
- "(long or Dict)", allBut(nonUserObjects, numerics + nullables + undefineds)
+ "(long or Callback)",
+ allBut(nonUserObjects + dicts + records + callbackInterfaces, numerics),
+ )
+ setDistinguishable(
+ "(long or Dict)",
+ allBut(nonUserObjects + callbacks, numerics + nullables + undefineds),
)
def areDistinguishable(type1, type2):
@@ -377,6 +417,7 @@ def WebIDLTest(parser, harness):
callback interface CallbackInterface2 {};
callback Callback = any();
callback Callback2 = long(short arg);
+ [LegacyTreatNonObjectAsNull] callback LegacyCallback1 = any();
// Give our dictionaries required members so we don't need to
// mess with optional and default values.
dictionary Dict { required long member; };
diff --git a/dom/bindings/parser/tests/test_legacyTreatNonObjectAsNull.py b/dom/bindings/parser/tests/test_legacyTreatNonObjectAsNull.py
new file mode 100644
index 0000000000..380ccdc4e7
--- /dev/null
+++ b/dom/bindings/parser/tests/test_legacyTreatNonObjectAsNull.py
@@ -0,0 +1,11 @@
+def WebIDLTest(parser, harness):
+ parser.parse(
+ """
+ [LegacyTreatNonObjectAsNull] callback Function = any(any... arguments);
+ """
+ )
+
+ results = parser.finish()
+
+ callback = results[0]
+ harness.check(callback._treatNonObjectAsNull, True, "Got the expected value")
diff --git a/dom/bindings/parser/tests/test_union_callback_dict.py b/dom/bindings/parser/tests/test_union_callback_dict.py
new file mode 100644
index 0000000000..3e87e16ad4
--- /dev/null
+++ b/dom/bindings/parser/tests/test_union_callback_dict.py
@@ -0,0 +1,132 @@
+import WebIDL
+
+
+def WebIDLTest(parser, harness):
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ dictionary TestDict {
+ DOMString member;
+ };
+ [LegacyTreatNonObjectAsNull] callback TestCallback = undefined ();
+ typedef (TestCallback or TestDict) TestUnionCallbackDict;
+ """
+ )
+ results = parser.finish()
+ except WebIDL.WebIDLError:
+ threw = True
+ harness.ok(
+ threw,
+ "Should not allow Dict/Callback union where callback is [LegacyTreatNonObjectAsNull]",
+ )
+
+ parser = parser.reset()
+
+ threw = False
+ try:
+ parser.parse(
+ """
+ dictionary TestDict {
+ DOMString member;
+ };
+ [LegacyTreatNonObjectAsNull] callback TestCallback = undefined ();
+ typedef (TestDict or TestCallback) TestUnionCallbackDict;
+ """
+ )
+ results = parser.finish()
+ except WebIDL.WebIDLError:
+ threw = True
+ harness.ok(
+ threw,
+ "Should not allow Dict/Callback union where callback is [LegacyTreatNonObjectAsNull]",
+ )
+
+ parser = parser.reset()
+
+ parser.parse(
+ """
+ dictionary TestDict {
+ DOMString member;
+ };
+ callback TestCallback = undefined ();
+ typedef (TestCallback or TestDict) TestUnionCallbackDict;
+ """
+ )
+ results = parser.finish()
+
+ harness.ok(True, "TestUnionCallbackDict interface parsed without error")
+ harness.check(len(results), 3, "Document should have 3 types")
+
+ myDict = results[0]
+ harness.ok(isinstance(myDict, WebIDL.IDLDictionary), "Expect an IDLDictionary")
+
+ myCallback = results[1]
+ harness.ok(isinstance(myCallback, WebIDL.IDLCallback), "Expect an IDLCallback")
+
+ myUnion = results[2]
+ harness.ok(isinstance(myUnion, WebIDL.IDLTypedef), "Expect a IDLTypedef")
+ harness.ok(
+ isinstance(myUnion.innerType, WebIDL.IDLUnionType), "Expect a IDLUnionType"
+ )
+ harness.ok(
+ isinstance(myUnion.innerType.memberTypes[0], WebIDL.IDLCallbackType),
+ "Expect a IDLCallbackType",
+ )
+ harness.ok(
+ isinstance(myUnion.innerType.memberTypes[1], WebIDL.IDLWrapperType),
+ "Expect a IDLDictionary",
+ )
+ harness.ok(
+ (myUnion.innerType.memberTypes[0].callback == myCallback),
+ "Expect left Union member to be MyCallback",
+ )
+ harness.ok(
+ (myUnion.innerType.memberTypes[1].inner == myDict),
+ "Expect right Union member to be MyDict",
+ )
+
+ parser = parser.reset()
+
+ parser.parse(
+ """
+ dictionary TestDict {
+ DOMString member;
+ };
+ callback TestCallback = undefined ();
+ typedef (TestDict or TestCallback) TestUnionCallbackDict;
+ """
+ )
+ results = parser.finish()
+
+ harness.ok(True, "TestUnionCallbackDict interface parsed without error")
+ harness.check(len(results), 3, "Document should have 3 types")
+
+ myDict = results[0]
+ harness.ok(isinstance(myDict, WebIDL.IDLDictionary), "Expect an IDLDictionary")
+
+ myCallback = results[1]
+ harness.ok(isinstance(myCallback, WebIDL.IDLCallback), "Expect an IDLCallback")
+
+ myUnion = results[2]
+ harness.ok(isinstance(myUnion, WebIDL.IDLTypedef), "Expect a IDLTypedef")
+ harness.ok(
+ isinstance(myUnion.innerType, WebIDL.IDLUnionType), "Expect a IDLUnionType"
+ )
+ harness.ok(
+ isinstance(myUnion.innerType.memberTypes[0], WebIDL.IDLWrapperType),
+ "Expect a IDLDictionary",
+ )
+ harness.ok(
+ isinstance(myUnion.innerType.memberTypes[1], WebIDL.IDLCallbackType),
+ "Expect a IDLCallbackType",
+ )
+ harness.ok(
+ (myUnion.innerType.memberTypes[0].inner == myDict),
+ "Expect right Union member to be MyDict",
+ )
+ harness.ok(
+ (myUnion.innerType.memberTypes[1].callback == myCallback),
+ "Expect left Union member to be MyCallback",
+ )
diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h
index 4a7ea91ee8..77053d9ba6 100644
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -1798,6 +1798,20 @@ class TestPrefChromeOnlySCFuncConstructorForInterface : public nsISupports,
Constructor(const GlobalObject&);
};
+class TestCallbackDictUnionOverload : public nsISupports,
+ public nsWrapperCache {
+ public:
+ NS_DECL_ISUPPORTS
+ virtual nsISupports* GetParentObject();
+
+ void Overload1(bool);
+ void Overload1(TestCallback&);
+ void Overload1(const GrandparentDict&);
+ void Overload2(bool);
+ void Overload2(const GrandparentDict&);
+ void Overload2(TestCallback&);
+};
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl
index 577be05920..827d9c35a7 100644
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -1535,3 +1535,16 @@ interface TestPrefChromeOnlySCFuncConstructorForInterface {
// in the generated constructor.
constructor();
};
+
+typedef (TestCallback or GrandparentDict) TestCallbackDictUnion;
+typedef (GrandparentDict or TestCallback) TestDictCallbackUnion;
+
+[Exposed=Window]
+interface TestCallbackDictUnionOverload {
+ undefined overload1(boolean arg);
+ undefined overload1(TestCallback arg);
+ undefined overload1(optional GrandparentDict arg = {});
+ undefined overload2(boolean arg);
+ undefined overload2(optional GrandparentDict arg = {});
+ undefined overload2(TestCallback arg);
+};
diff --git a/dom/bindings/test/TestInterfaceJS.sys.mjs b/dom/bindings/test/TestInterfaceJS.sys.mjs
index 53ce9d107d..ea229eda49 100644
--- a/dom/bindings/test/TestInterfaceJS.sys.mjs
+++ b/dom/bindings/test/TestInterfaceJS.sys.mjs
@@ -93,12 +93,12 @@ TestInterfaceJS.prototype = {
pingPongNullableUnion(x) {
return x;
},
- returnBadUnion(x) {
+ returnBadUnion() {
return 3;
},
- testSequenceOverload(arg) {},
- testSequenceUnion(arg) {},
+ testSequenceOverload() {},
+ testSequenceUnion() {},
testThrowError() {
throw new this._win.Error("We are an Error");
@@ -121,7 +121,7 @@ TestInterfaceJS.prototype = {
throw Cr.NS_BINDING_ABORTED;
},
- testThrowNsresultFromNative(x) {
+ testThrowNsresultFromNative() {
// We want to throw an exception that we generate from an nsresult thrown
// by a C++ component.
Services.io.notImplemented();
diff --git a/dom/bindings/test/test_async_iterable.html b/dom/bindings/test/test_async_iterable.html
index 8f1f04aea7..ed47ef4c9d 100644
--- a/dom/bindings/test/test_async_iterable.html
+++ b/dom/bindings/test/test_async_iterable.html
@@ -88,7 +88,7 @@ async function test_data_single() {
let blockingPromises = [];
for (let i = 0; i < 10; ++i) {
let unblocker;
- let promise = new Promise((resolve, reject) => {
+ let promise = new Promise((resolve) => {
unblocker = resolve;
});
unblockers.push(unblocker);
diff --git a/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml
index 724c40cbd3..be188b8fbe 100644
--- a/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml
+++ b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml
@@ -50,9 +50,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1123516
ok(true, "Calling iterators via xrays should fail");
}
- setlike.forEach((v,k,t) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
+ setlike.forEach((v) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
TestInterfaceSetlikeNode.prototype.forEach.call(setlike,
- (v,k,t) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
+ (v) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
is(TestInterfaceSetlikeNode.prototype.delete.call(setlike, win.document.documentElement), true,
"Cross-compartment unwrapping/comparison delete works");
/* eslint-disable-next-line no-shadow */
diff --git a/dom/bindings/test/test_observablearray.html b/dom/bindings/test/test_observablearray.html
index 313fb67622..56e35eeca5 100644
--- a/dom/bindings/test/test_observablearray.html
+++ b/dom/bindings/test/test_observablearray.html
@@ -21,7 +21,7 @@ add_task(function testObservableArray_length() {
let deleteCallbackTests = null;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
deleteBooleanCallback(value, index) {
@@ -82,10 +82,10 @@ add_task(function testObservableArray_length_callback_throw() {
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback(value) {
deleteCallbackCount++;
if (value) {
throw new Error("deleteBooleanCallback");
@@ -268,7 +268,7 @@ add_task(function testObservableArray_setter_callback_throw() {
throw new Error("setBooleanCallback");
}
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback(value) {
deleteCallbackCount++;
if (value) {
throw new Error("deleteBooleanCallback");
@@ -437,7 +437,7 @@ add_task(function testObservableArray_indexed_setter_callback_throw() {
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback(value) {
setCallbackCount++;
if (value) {
throw new Error("setBooleanCallback");
@@ -501,7 +501,7 @@ add_task(function testObservableArray_object() {
is(index, callbackIndex++, "setCallbackTests: test index argument");
isDeeply(values[index], value, "setCallbackTests: test value argument");
},
- deleteObjectCallback(value, index) {
+ deleteObjectCallback() {
deleteCallbackCount++;
},
});
@@ -521,10 +521,10 @@ add_task(function testObservableArray_object() {
add_task(function testObservableArray_xrays() {
let m = new TestInterfaceObservableArray({
- setObjectCallback(value, index) {
+ setObjectCallback() {
ok(false, "Shouldn't reach setObjectCallback");
},
- deleteObjectCallback(value, index) {
+ deleteObjectCallback() {
ok(false, "Shouldn't reach deleteObjectCallback");
},
});
diff --git a/dom/bindings/test/test_observablearray_helper.html b/dom/bindings/test/test_observablearray_helper.html
index d2b4897cac..e2f3e42c45 100644
--- a/dom/bindings/test/test_observablearray_helper.html
+++ b/dom/bindings/test/test_observablearray_helper.html
@@ -110,7 +110,7 @@ add_task(function testObservableArray_helper_replaceElementAt_callback_throw() {
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback(value) {
setCallbackCount++;
if (value) {
throw new Error("setBooleanCallback");
@@ -170,7 +170,7 @@ add_task(function testObservableArray_helper_appendElement() {
setCallbackTests(value, index);
}
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback() {
deleteCallbackCount++;
},
});
@@ -211,13 +211,13 @@ add_task(function testObservableArray_helper_appendElement_callback_throw() {
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback(value) {
setCallbackCount++;
if (value) {
throw new Error("setBooleanCallback");
}
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback() {
deleteCallbackCount++;
},
});
@@ -257,7 +257,7 @@ add_task(function testObservableArray_helper_removeLastElement() {
let deleteCallbackTests = null;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
deleteBooleanCallback(value, index) {
@@ -316,10 +316,10 @@ add_task(function testObservableArray_helper_removeLastElement_callback_throw()
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback(value) {
deleteCallbackCount++;
if (value) {
throw new Error("deleteBooleanCallback");
diff --git a/dom/bindings/test/test_observablearray_proxyhandler.html b/dom/bindings/test/test_observablearray_proxyhandler.html
index d7d8810981..00ef7c26b4 100644
--- a/dom/bindings/test/test_observablearray_proxyhandler.html
+++ b/dom/bindings/test/test_observablearray_proxyhandler.html
@@ -184,7 +184,7 @@ add_task(function testObservableArrayExoticObjects_defineProperty_callback_throw
const minLen = 3;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback(value) {
setCallbackCount++;
if (value) {
throw new Error("setBooleanCallback");
@@ -300,7 +300,7 @@ add_task(function testObservableArrayExoticObjects_deleteProperty() {
let deleteCallbackTests = null;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
deleteBooleanCallback(value, index) {
@@ -384,10 +384,10 @@ add_task(function testObservableArrayExoticObjects_deleteProperty_callback_throw
let deleteCallbackCount = 0;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback() {
setCallbackCount++;
},
- deleteBooleanCallback(value, index) {
+ deleteBooleanCallback(value) {
deleteCallbackCount++;
if (value) {
throw new Error("deleteBooleanCallback");
@@ -731,7 +731,7 @@ add_task(function testObservableArrayExoticObjects_set_callback_throw() {
const minLen = 3;
let m = new TestInterfaceObservableArray({
- setBooleanCallback(value, index) {
+ setBooleanCallback(value) {
setCallbackCount++;
if (value) {
throw new Error("setBooleanCallback");
diff --git a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
index ab7e15dc57..aba129dc3e 100644
--- a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
+++ b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
@@ -31,7 +31,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107592
is(exn.stack, stack, "Should have the right stack in test " + testNumber);
}
- function ensurePromiseFail(testNumber, value) {
+ function ensurePromiseFail(testNumber) {
ok(false, "Test " + testNumber + " should not have a fulfilled promise");
}
diff --git a/dom/bindings/test/test_sequence_wrapping.html b/dom/bindings/test/test_sequence_wrapping.html
index 34d901fb66..2b1d657b6c 100644
--- a/dom/bindings/test/test_sequence_wrapping.html
+++ b/dom/bindings/test/test_sequence_wrapping.html
@@ -37,7 +37,7 @@ function doTest() {
win.Object.defineProperty(win.Array.prototype, "0",
{
- set(val) {
+ set() {
setterCalled = true;
},
});