Bug 1708660 - Remove support for map/setLike in JS-implemented WebIDL. r=edgar

Differential Revision: https://phabricator.services.mozilla.com/D113949
This commit is contained in:
Peter Van der Beken 2021-05-06 05:12:03 +00:00
Родитель 67b390b0dc
Коммит 2ec947a685
11 изменённых файлов: 14 добавлений и 317 удалений

Просмотреть файл

@ -218,7 +218,6 @@
#if defined(ENABLE_TESTS) && defined(MOZ_DEBUG) #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
@RESPATH@/components/TestInterfaceJS.js @RESPATH@/components/TestInterfaceJS.js
@RESPATH@/components/TestInterfaceJS.manifest @RESPATH@/components/TestInterfaceJS.manifest
@RESPATH@/components/TestInterfaceJSMaplike.js
#endif #endif
#if defined(MOZ_DEBUG) || defined(MOZ_DEV_EDITION) || defined(NIGHTLY_BUILD) #if defined(MOZ_DEBUG) || defined(MOZ_DEV_EDITION) || defined(NIGHTLY_BUILD)

Просмотреть файл

@ -19805,24 +19805,6 @@ class CGJSImplClass(CGBindingImplClass):
) )
) )
if (
descriptor.interface.isJSImplemented()
and descriptor.interface.maplikeOrSetlikeOrIterable
and descriptor.interface.maplikeOrSetlikeOrIterable.isMaplike()
):
self.methodDecls.append(
ClassMethod(
"__OnGet",
"void",
[
Argument("JS::Handle<JS::Value>", "aKey"),
Argument("JS::Handle<JS::Value>", "aValue"),
Argument("ErrorResult&", "aRv"),
],
body="mImpl->__OnGet(aKey, aValue, aRv);\n",
)
)
CGClass.__init__( CGClass.__init__(
self, self,
descriptor.name, descriptor.name,
@ -20327,15 +20309,6 @@ class CGCallbackInterface(CGCallback):
methods.append(CGJSImplInitOperation(sigs[0], descriptor)) methods.append(CGJSImplInitOperation(sigs[0], descriptor))
needInitId = True needInitId = True
needOnGetId = False
if (
iface.isJSImplemented()
and iface.maplikeOrSetlikeOrIterable
and iface.maplikeOrSetlikeOrIterable.isMaplike()
):
methods.append(CGJSImplOnGetOperation(descriptor))
needOnGetId = True
idlist = [ idlist = [
descriptor.binaryNameFor(m.identifier.name) descriptor.binaryNameFor(m.identifier.name)
for m in iface.members for m in iface.members
@ -20343,8 +20316,6 @@ class CGCallbackInterface(CGCallback):
] ]
if needInitId: if needInitId:
idlist.append("__init") idlist.append("__init")
if needOnGetId:
idlist.append("__onget")
if iface.isJSImplemented() and iface.getExtendedAttribute( if iface.isJSImplemented() and iface.getExtendedAttribute(
"WantsEventListenerHooks" "WantsEventListenerHooks"
@ -21058,35 +21029,6 @@ class CGJSImplInitOperation(CallbackOperationBase):
return "__init" return "__init"
class CGJSImplOnGetOperation(CallbackOperationBase):
"""
Codegen the __OnGet() method used to notify the JS impl that a get() is
happening on a JS-implemented maplike. This method takes two arguments
(key and value) and returns nothing.
"""
def __init__(self, descriptor):
CallbackOperationBase.__init__(
self,
(
BuiltinTypes[IDLBuiltinType.Types.void],
[
FakeArgument(BuiltinTypes[IDLBuiltinType.Types.any], None, "key"),
FakeArgument(BuiltinTypes[IDLBuiltinType.Types.any], None, "value"),
],
),
"__onget",
"__OnGet",
descriptor,
singleOperation=False,
rethrowContentException=True,
spiderMonkeyInterfacesAreStructs=True,
)
def getPrettyName(self):
return "__onget"
class CGJSImplEventHookOperation(CallbackOperationBase): class CGJSImplEventHookOperation(CallbackOperationBase):
""" """
Codegen the hooks on a JS impl for adding/removing event listeners. Codegen the hooks on a JS impl for adding/removing event listeners.
@ -21467,28 +21409,7 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
] ]
arguments = ["&result"] arguments = ["&result"]
callOnGet = [] return self.mergeTuples(r, (code, arguments, []))
if (
self.descriptor.interface.isJSImplemented()
and not self.helperImpl # For C++ MaplikeHelper Get method, we don't notify underlying js implementation
):
callOnGet = [
CGGeneric(
dedent(
"""
{
JS::ExposeValueToActiveJS(result);
ErrorResult onGetResult;
self->__OnGet(arg0Val, result, onGetResult);
if (onGetResult.MaybeSetPendingException(cx)) {
return false;
}
}
"""
)
)
]
return self.mergeTuples(r, (code, arguments, callOnGet))
def has(self): def has(self):
""" """
@ -21933,13 +21854,6 @@ class GlobalGenRoots:
if d.interface.isJSImplemented() and d.interface.ctor(): if d.interface.isJSImplemented() and d.interface.ctor():
# We'll have an __init() method. # We'll have an __init() method.
members.append(FakeMember("__init")) members.append(FakeMember("__init"))
if (
d.interface.isJSImplemented()
and d.interface.maplikeOrSetlikeOrIterable
and d.interface.maplikeOrSetlikeOrIterable.isMaplike()
):
# We'll have an __onget() method.
members.append(FakeMember("__onget"))
if d.interface.isJSImplemented() and d.interface.getExtendedAttribute( if d.interface.isJSImplemented() and d.interface.getExtendedAttribute(
"WantsEventListenerHooks" "WantsEventListenerHooks"
): ):

Просмотреть файл

@ -1021,6 +1021,13 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
# things like exposure setting. # things like exposure setting.
for member in self.members: for member in self.members:
if member.isMaplikeOrSetlikeOrIterable(): if member.isMaplikeOrSetlikeOrIterable():
if self.isJSImplemented():
raise WebIDLError(
"%s declaration used on "
"interface that is implemented in JS"
% (member.maplikeOrSetlikeOrIterableType),
[member.location],
)
# Check that we only have one interface declaration (currently # Check that we only have one interface declaration (currently
# there can only be one maplike/setlike declaration per # there can only be one maplike/setlike declaration per
# interface) # interface)
@ -1038,9 +1045,7 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
self.maplikeOrSetlikeOrIterable = member self.maplikeOrSetlikeOrIterable = member
# If we've got a maplike or setlike declaration, we'll be building all of # If we've got a maplike or setlike declaration, we'll be building all of
# our required methods in Codegen. Generate members now. # our required methods in Codegen. Generate members now.
self.maplikeOrSetlikeOrIterable.expand( self.maplikeOrSetlikeOrIterable.expand(self.members)
self.members, self.isJSImplemented()
)
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder) assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
parent = self.parent.finish(scope) if self.parent else None parent = self.parent.finish(scope) if self.parent else None
@ -4605,7 +4610,7 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
self.valueType, self.valueType,
) )
def expand(self, members, isJSImplemented): def expand(self, members):
""" """
In order to take advantage of all of the method machinery in Codegen, In order to take advantage of all of the method machinery in Codegen,
we generate our functions as if they were part of the interface we generate our functions as if they were part of the interface
@ -4691,7 +4696,7 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
self.keyType, self.keyType,
) )
def expand(self, members, isJSImplemented): def expand(self, members):
""" """
In order to take advantage of all of the method machinery in Codegen, In order to take advantage of all of the method machinery in Codegen,
we generate our functions as if they were part of the interface we generate our functions as if they were part of the interface
@ -4782,28 +4787,6 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
[getKeyArg()], [getKeyArg()],
) )
# Always generate underscored functions (e.g. __add, __clear) for js
# implemented interfaces as convenience functions.
if isJSImplemented:
# void clear()
self.addMethod(
"clear",
members,
True,
BuiltinTypes[IDLBuiltinType.Types.void],
[],
chromeOnly=True,
)
# boolean delete(keyType key)
self.addMethod(
"delete",
members,
True,
BuiltinTypes[IDLBuiltinType.Types.boolean],
[getKeyArg()],
chromeOnly=True,
)
if self.isSetlike(): if self.isSetlike():
if not self.readonly: if not self.readonly:
# Add returns the set object it just added to. # Add returns the set object it just added to.
@ -4816,15 +4799,6 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
BuiltinTypes[IDLBuiltinType.Types.object], BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg()], [getKeyArg()],
) )
if isJSImplemented:
self.addMethod(
"add",
members,
True,
BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg()],
chromeOnly=True,
)
return return
# If we get this far, we're a maplike declaration. # If we get this far, we're a maplike declaration.
@ -4861,15 +4835,6 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
BuiltinTypes[IDLBuiltinType.Types.object], BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()], [getKeyArg(), getValueArg()],
) )
if isJSImplemented:
self.addMethod(
"set",
members,
True,
BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()],
chromeOnly=True,
)
class IDLConst(IDLInterfaceMember): class IDLConst(IDLInterfaceMember):

Просмотреть файл

@ -317,7 +317,7 @@ def WebIDLTest(parser, harness):
numProductions=2, numProductions=2,
) )
shouldPass( shouldFail(
"JS Implemented maplike interface", "JS Implemented maplike interface",
""" """
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"] [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
@ -326,10 +326,9 @@ def WebIDLTest(parser, harness):
setlike<long>; setlike<long>;
}; };
""", """,
setRWChromeMembers,
) )
shouldPass( shouldFail(
"JS Implemented maplike interface", "JS Implemented maplike interface",
""" """
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"] [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
@ -338,7 +337,6 @@ def WebIDLTest(parser, harness):
maplike<long, long>; maplike<long, long>;
}; };
""", """,
mapRWChromeMembers,
) )
# #
@ -746,31 +744,6 @@ def WebIDLTest(parser, harness):
setROMembers + [("clear", WebIDL.IDLAttribute)], setROMembers + [("clear", WebIDL.IDLAttribute)],
) )
shouldPass(
"JS Implemented read-only interface with readonly allowable overrides",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
readonly setlike<long>;
readonly attribute boolean clear;
};
""",
setROChromeMembers + [("clear", WebIDL.IDLAttribute)],
)
shouldFail(
"JS Implemented read-write interface with non-readwrite allowable overrides",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
setlike<long>;
readonly attribute boolean clear;
};
""",
)
r = shouldPass( r = shouldPass(
"Check proper override of clear/delete/set", "Check proper override of clear/delete/set",
""" """

Просмотреть файл

@ -1,4 +1,2 @@
component {2ac4e026-cf25-47d5-b067-78d553c3cad8} TestInterfaceJS.js component {2ac4e026-cf25-47d5-b067-78d553c3cad8} TestInterfaceJS.js
contract @mozilla.org/dom/test-interface-js;1 {2ac4e026-cf25-47d5-b067-78d553c3cad8} contract @mozilla.org/dom/test-interface-js;1 {2ac4e026-cf25-47d5-b067-78d553c3cad8}
component {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a} TestInterfaceJSMaplike.js
contract @mozilla.org/dom/test-interface-js-maplike;1 {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a}

Просмотреть файл

@ -1,44 +0,0 @@
/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { ComponentUtils } = ChromeUtils.import(
"resource://gre/modules/ComponentUtils.jsm"
);
function TestInterfaceJSMaplike() {}
TestInterfaceJSMaplike.prototype = {
classID: Components.ID("{4bc6f6f3-e005-4f0a-b42d-4d1663a9013a}"),
contractID: "@mozilla.org/dom/test-interface-js-maplike;1",
QueryInterface: ChromeUtils.generateQI(["nsIDOMGlobalPropertyInitializer"]),
init(win) {
this._win = win;
},
__init() {},
setInternal(aKey, aValue) {
return this.__DOM_IMPL__.__set(aKey, aValue);
},
deleteInternal(aKey) {
return this.__DOM_IMPL__.__delete(aKey);
},
clearInternal() {
return this.__DOM_IMPL__.__clear();
},
__onget(key, value) {
/* no-op */
},
};
this.NSGetFactory = ComponentUtils.generateNSGetFactory([
TestInterfaceJSMaplike,
]);

Просмотреть файл

@ -15,7 +15,6 @@ Library("dombindings_test_s")
EXTRA_COMPONENTS += [ EXTRA_COMPONENTS += [
"TestInterfaceJS.js", "TestInterfaceJS.js",
"TestInterfaceJS.manifest", "TestInterfaceJS.manifest",
"TestInterfaceJSMaplike.js",
] ]
MOCHITEST_MANIFESTS += ["mochitest.ini"] MOCHITEST_MANIFESTS += ["mochitest.ini"]

Просмотреть файл

@ -9,7 +9,7 @@
</head> </head>
<body> <body>
<script class="testbody" type="application/javascript"> <script class="testbody" type="application/javascript">
/* global TestInterfaceMaplike, TestInterfaceSetlike, TestInterfaceMaplikeObject, TestInterfaceJSMaplike, TestInterfaceMaplikeJSObject*/ /* global TestInterfaceMaplike, TestInterfaceSetlike, TestInterfaceMaplikeObject, TestInterfaceMaplikeJSObject*/
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() {
var base_properties = [["has", "function", 1], var base_properties = [["has", "function", 1],
@ -233,34 +233,6 @@
is(m.size, 0, "JSObjectMapConvenience: size should be 0 after clearInternal"); is(m.size, 0, "JSObjectMapConvenience: size should be 0 after clearInternal");
// JS implemented map creation convenience function test // JS implemented map creation convenience function test
info("JSMapConvenience: Testing JS implemented map creation convenience functions");
m = new TestInterfaceJSMaplike();
ok(m, "JSMapConvenience: got a TestInterfaceJSMaplike object");
is(m.size, 0, "JSMapConvenience: size should be zero");
ok(!m.has("test"), "JSMapConvenience: maplike has should return false");
m.setInternal("test", 1);
is(m.size, 1, "JSMapConvenience: size should be 1");
ok(m.has("test"), "JSMapConvenience: maplike has should return true");
is(m.get("test"), 1, "JSMapConvenience: maplike get should return value entered");
m.setInternal("test2", 2);
is(m.size, 2, "JSMapConvenience: size should be 2");
ok(m.has("test2"), "JSMapConvenience: maplike has should return true");
is(m.get("test2"), 2, "JSMapConvenience: maplike get should return value entered");
is(m.deleteInternal("test2"), true, "JSMapConvenience: maplike deleteInternal should return true");
is(m.size, 1, "JSMapConvenience: size should be 1");
for (let k of m.keys()) {
is(k, "test", "JSMapConvenience: first keys element should be 'test'");
}
for (let v of m.values()) {
is(v, 1, "JSMapConvenience: first values elements should be 1");
}
for (let e of m.entries()) {
is(e[0], "test", "JSMapConvenience: entries first array element should be 'test'");
is(e[1], 1, "JSMapConvenience: entries second array element should be 1");
}
m.clearInternal();
is(m.size, 0, "JSMapConvenience: size should be 0 after clearInternal");
// Test this override for forEach // Test this override for forEach
info("ForEachThisOverride: Testing this override for forEach"); info("ForEachThisOverride: Testing this override for forEach");
m = new TestInterfaceMaplike(); m = new TestInterfaceMaplike();

Просмотреть файл

@ -2646,71 +2646,6 @@ the chrome implementation object. This property only appears after the
content-side object has been created. So it is available in ``__init`` content-side object has been created. So it is available in ``__init``
but not in ``init``. but not in ``init``.
.. _MaplikeSetlike_declaration_helpers_in_Javascript_implementations:
Maplike/Setlike declaration helpers in Javascript implementations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to manipulate the storage for maplike and setlike declarations
on WebIDL interfaces from javascript implementations, certain functions
are generated that can be used by the implementation. Retrieval from
storage can happen via the publicly exposed maplike functions for the
interface, but these helpers guarantee that access is available to
manipulate storage from chrome JS, even in the case of the interface
declaration being readonly.
.. _Maplike_2:
Maplike
^^^^^^^
The following interface:
.. code:: notranslate
[JSImplementation="@mozilla.org/dom/string-to-long-js-maplike;1",
Constructor()]
interface StringToLongMaplike {
readonly maplike<DOMString, long>;
};
Has these JS functions available to it:
.. code:: brush:
// Sets a certain key with a certain value. Exception thrown on wrong types.
this.__DOM_IMPL__.__set(aKey, aValue);
// Deletes a key. Returns a boolean, true if key exists and was deleted, false otherwise.
this.__DOM_IMPL__.__delete(aKey);
// Completely clear all values from maplike storage
this.__DOM_IMPL__.__clear();
.. _Setlike_2:
Setlike
^^^^^^^
The following interface:
.. code:: notranslate
[JSImplementation="@mozilla.org/dom/string-js-setlike;1",
Constructor()]
interface StringSetlike {
readonly setlike<DOMString>;
};
Has these JS functions available to it:
.. code:: brush:
// Adds a key to a set. Exception thrown on wrong types.
this.__DOM_IMPL__.__add(aKey);
// Deletes a key. Returns a boolean, true if key exists and was deleted, false otherwise.
this.__DOM_IMPL__.__delete(aKey)
// Completely clear all values from maplike storage
this.__DOM_IMPL__.__clear();
.. _Determining_the_principal_of_the_caller_that_invoked_the_WebIDL_API: .. _Determining_the_principal_of_the_caller_that_invoked_the_WebIDL_API:
Determining the principal of the caller that invoked the WebIDL API Determining the principal of the caller that invoked the WebIDL API

Просмотреть файл

@ -49,19 +49,6 @@ interface TestInterfaceMaplikeJSObject {
object? getInternal(DOMString aKey); object? getInternal(DOMString aKey);
}; };
[Pref="dom.expose_test_interfaces",
JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
Exposed=Window]
interface TestInterfaceJSMaplike {
[Throws]
constructor();
readonly maplike<DOMString, long>;
void setInternal(DOMString aKey, long aValue);
void clearInternal();
boolean deleteInternal(DOMString aKey);
};
[Pref="dom.expose_test_interfaces", [Pref="dom.expose_test_interfaces",
Exposed=Window] Exposed=Window]
interface TestInterfaceSetlike { interface TestInterfaceSetlike {

Просмотреть файл

@ -110,7 +110,6 @@
#if defined(ENABLE_TESTS) && defined(MOZ_DEBUG) #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
@BINPATH@/components/TestInterfaceJS.js @BINPATH@/components/TestInterfaceJS.js
@BINPATH@/components/TestInterfaceJS.manifest @BINPATH@/components/TestInterfaceJS.manifest
@BINPATH@/components/TestInterfaceJSMaplike.js
#endif #endif
; Modules ; Modules