Bug 1366738: Implement [LegacyWindowAlias] r=bzbarsky

Add [LegacyWindowAlias] extended attribute support for WebKitCSSMatrix and webkitURL.

Differential Revision: https://phabricator.services.mozilla.com/D35601

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kagami Sascha Rosylight 2019-07-03 02:37:11 +00:00
Родитель 11712bd3ce
Коммит 8dd328fee0
14 изменённых файлов: 149 добавлений и 293 удалений

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

@ -1,167 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "mozilla/dom/WebKitCSSMatrix.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/WebKitCSSMatrixBinding.h"
#include "mozilla/StaticPrefs.h"
#include "nsPresContext.h"
#include "nsGlobalWindowInner.h"
namespace mozilla {
namespace dom {
static const double sRadPerDegree = 2.0 * M_PI / 360.0;
bool WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj) {
return StaticPrefs::layout_css_DOMMatrix_enabled();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Constructor(
const GlobalObject& aGlobal, ErrorResult& aRv) {
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
return obj.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Constructor(
const GlobalObject& aGlobal, const nsAString& aTransformList,
ErrorResult& aRv) {
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
obj = obj->SetMatrixValue(aTransformList, aRv);
return obj.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Constructor(
const GlobalObject& aGlobal, const DOMMatrixReadOnly& aOther,
ErrorResult& aRv) {
RefPtr<WebKitCSSMatrix> obj =
new WebKitCSSMatrix(aGlobal.GetAsSupports(), aOther);
return obj.forget();
}
JSObject* WebKitCSSMatrix::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return WebKitCSSMatrix_Binding::Wrap(aCx, this, aGivenProto);
}
WebKitCSSMatrix* WebKitCSSMatrix::SetMatrixValue(
const nsAString& aTransformList, ErrorResult& aRv) {
DOMMatrix::SetMatrixValue(aTransformList, aRv);
return this;
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Multiply(
const DOMMatrixInit& aOtherInit, ErrorResult& aRv) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->MultiplySelf(aOtherInit, aRv);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Inverse(
ErrorResult& aRv) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->InvertSelfThrow(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return retval.forget();
}
WebKitCSSMatrix* WebKitCSSMatrix::InvertSelfThrow(ErrorResult& aRv) {
if (mMatrix3D) {
if (!mMatrix3D->Invert()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
} else if (!mMatrix2D->Invert()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
return this;
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Translate(double aTx,
double aTy,
double aTz) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->TranslateSelf(aTx, aTy, aTz);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::Rotate(
double aRotX, const Optional<double>& aRotY,
const Optional<double>& aRotZ) const {
double rotX = aRotX;
double rotY;
double rotZ;
if (!aRotY.WasPassed() && !aRotZ.WasPassed()) {
rotZ = rotX;
rotX = 0;
rotY = 0;
} else {
rotY = aRotY.WasPassed() ? aRotY.Value() : 0;
rotZ = aRotZ.WasPassed() ? aRotZ.Value() : 0;
}
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->Rotate3dSelf(rotX, rotY, rotZ);
return retval.forget();
}
WebKitCSSMatrix* WebKitCSSMatrix::Rotate3dSelf(double aRotX, double aRotY,
double aRotZ) {
if (aRotX != 0 || aRotY != 0) {
Ensure3DMatrix();
}
if (mMatrix3D) {
if (fmod(aRotZ, 360) != 0) {
mMatrix3D->RotateZ(aRotZ * sRadPerDegree);
}
if (fmod(aRotY, 360) != 0) {
mMatrix3D->RotateY(aRotY * sRadPerDegree);
}
if (fmod(aRotX, 360) != 0) {
mMatrix3D->RotateX(aRotX * sRadPerDegree);
}
} else if (fmod(aRotZ, 360) != 0) {
mMatrix2D->PreRotate(aRotZ * sRadPerDegree);
}
return this;
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::RotateAxisAngle(
double aX, double aY, double aZ, double aAngle) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::SkewX(double aSx) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->SkewXSelf(aSx);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix> WebKitCSSMatrix::SkewY(double aSy) const {
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->SkewYSelf(aSy);
return retval.forget();
}
} // namespace dom
} // namespace mozilla

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

@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_webkitcssmatrix_h__
#define mozilla_dom_webkitcssmatrix_h__
#include "mozilla/dom/DOMMatrix.h"
namespace mozilla {
namespace dom {
class WebKitCSSMatrix final : public DOMMatrix {
public:
explicit WebKitCSSMatrix(nsISupports* aParent) : DOMMatrix(aParent) {}
WebKitCSSMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other)
: DOMMatrix(aParent, other) {}
static bool FeatureEnabled(JSContext* aCx, JSObject* aObj);
static already_AddRefed<WebKitCSSMatrix> Constructor(
const GlobalObject& aGlobal, ErrorResult& aRv);
static already_AddRefed<WebKitCSSMatrix> Constructor(
const GlobalObject& aGlobal, const nsAString& aTransformList,
ErrorResult& aRv);
static already_AddRefed<WebKitCSSMatrix> Constructor(
const GlobalObject& aGlobal, const DOMMatrixReadOnly& aOther,
ErrorResult& aRv);
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
WebKitCSSMatrix* SetMatrixValue(const nsAString& aTransformList,
ErrorResult& aRv);
already_AddRefed<WebKitCSSMatrix> Multiply(const DOMMatrixInit& aOtherInit,
ErrorResult& aRv) const;
already_AddRefed<WebKitCSSMatrix> Inverse(ErrorResult& aRv) const;
already_AddRefed<WebKitCSSMatrix> Translate(double aTx, double aTy,
double aTz) const;
already_AddRefed<WebKitCSSMatrix> Rotate(double aRotX,
const Optional<double>& aRotY,
const Optional<double>& aRotZ) const;
already_AddRefed<WebKitCSSMatrix> RotateAxisAngle(double aX, double aY,
double aZ,
double aAngle) const;
already_AddRefed<WebKitCSSMatrix> SkewX(double aSx) const;
already_AddRefed<WebKitCSSMatrix> SkewY(double aSy) const;
protected:
WebKitCSSMatrix* Rotate3dSelf(double aRotX, double aRotY, double aRotZ);
WebKitCSSMatrix* InvertSelfThrow(ErrorResult& aRv);
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_webkitcssmatrix_h__ */

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

@ -245,7 +245,6 @@ EXPORTS.mozilla.dom += [
'TreeWalker.h',
'UIDirectionManager.h',
'VisualViewport.h',
'WebKitCSSMatrix.h',
'WindowOrientationObserver.h',
'WindowProxyHolder.h',
]
@ -416,7 +415,6 @@ UNIFIED_SOURCES += [
'TreeWalker.cpp',
'UIDirectionManager.cpp',
'VisualViewport.cpp',
'WebKitCSSMatrix.cpp',
'WindowDestroyedEvent.cpp',
'WindowNamedPropertiesHandler.cpp',
'WindowOrientationObserver.cpp',

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

@ -730,7 +730,8 @@ static JSObject* CreateInterfaceObject(
unsigned ctorNargs, const NamedConstructor* namedConstructors,
JS::Handle<JSObject*> proto, const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties, const char* name,
bool isChrome, bool defineOnGlobal) {
bool isChrome, bool defineOnGlobal,
const char* const* legacyWindowAliases) {
JS::Rooted<JSObject*> constructor(cx);
MOZ_ASSERT(constructorProto);
MOZ_ASSERT(constructorClass);
@ -820,6 +821,14 @@ static JSObject* CreateInterfaceObject(
return nullptr;
}
if (legacyWindowAliases && NS_IsMainThread()) {
for (; *legacyWindowAliases; ++legacyWindowAliases) {
if (!DefineConstructor(cx, global, *legacyWindowAliases, constructor)) {
return nullptr;
}
}
}
if (namedConstructors) {
int namedConstructorSlot = DOM_INTERFACE_SLOTS_BASE;
while (namedConstructors->mName) {
@ -950,7 +959,8 @@ void CreateInterfaceObjects(
unsigned ctorNargs, const NamedConstructor* namedConstructors,
JS::Heap<JSObject*>* constructorCache, const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties, const char* name,
bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal) {
bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal,
const char* const* legacyWindowAliases) {
MOZ_ASSERT(protoClass || constructorClass, "Need at least one class!");
MOZ_ASSERT(
!((properties &&
@ -1002,7 +1012,7 @@ void CreateInterfaceObjects(
interface = CreateInterfaceObject(
cx, global, constructorProto, constructorClass, ctorNargs,
namedConstructors, proto, properties, chromeOnlyProperties, name,
isChrome, defineOnGlobal);
isChrome, defineOnGlobal, legacyWindowAliases);
if (!interface) {
if (protoCache) {
// If we fail we need to make sure to clear the value of protoCache we

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

@ -720,6 +720,9 @@ struct NamedConstructor {
* isGlobal if true, we're creating interface objects for a [Global] or
* [PrimaryGlobal] interface, and hence shouldn't define properties on
* the prototype object.
* legacyWindowAliases if not null it points to a null-terminated list of const
* char* names of the legacy window aliases for this
* interface.
*
* At least one of protoClass, constructorClass or constructor should be
* non-null. If constructorClass or constructor are non-null, the resulting
@ -736,7 +739,8 @@ void CreateInterfaceObjects(
JS::Heap<JSObject*>* constructorCache,
const NativeProperties* regularProperties,
const NativeProperties* chromeOnlyProperties, const char* name,
bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal);
bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal,
const char* const* legacyWindowAliases);
/**
* Define the properties (regular and chrome-only) on obj.

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

@ -3048,7 +3048,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
properties should be a PropertyArrays instance.
"""
def __init__(self, descriptor, properties, haveUnscopables):
def __init__(self, descriptor, properties, haveUnscopables, haveLegacyWindowAliases):
args = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal'),
Argument('ProtoAndIfaceCache&', 'aProtoAndIfaceCache'),
@ -3056,6 +3056,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties
self.haveUnscopables = haveUnscopables
self.haveLegacyWindowAliases = haveLegacyWindowAliases
def definition_body(self):
(protoGetter, protoHandleGetter) = InterfacePrototypeObjectProtoGetter(self.descriptor)
@ -3184,7 +3185,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
${chromeProperties},
${name}, aDefineOnGlobal,
${unscopableNames},
${isGlobal});
${isGlobal},
${legacyWindowAliases});
""",
protoClass=protoClass,
parentProto=parentProto,
@ -3199,7 +3201,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
chromeProperties=chromeProperties,
name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr",
unscopableNames="unscopableNames" if self.haveUnscopables else "nullptr",
isGlobal=toStringBool(isGlobal))
isGlobal=toStringBool(isGlobal),
legacyWindowAliases="legacyWindowAliases" if self.haveLegacyWindowAliases else "nullptr")
# If we fail after here, we must clear interface and prototype caches
# using this code: intermediate failure must not expose the interface in
@ -13359,10 +13362,20 @@ class CGDescriptor(CGThing):
[CGGeneric("nullptr")], ",\n")),
CGGeneric("};\n")], "\n"))
legacyWindowAliases = descriptor.interface.legacyWindowAliases
haveLegacyWindowAliases = len(legacyWindowAliases) != 0
if haveLegacyWindowAliases:
cgThings.append(
CGList([CGGeneric("static const char* const legacyWindowAliases[] = {"),
CGIndenter(CGList([CGGeneric('"%s"' % name) for
name in legacyWindowAliases] +
[CGGeneric("nullptr")], ",\n")),
CGGeneric("};\n")], "\n"))
# CGCreateInterfaceObjectsMethod needs to come after our
# CGDOMJSClass and unscopables, if any.
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties,
haveUnscopables))
haveUnscopables, haveLegacyWindowAliases))
# CGGetProtoObjectMethod and CGGetConstructorObjectMethod need
# to come after CGCreateInterfaceObjectsMethod.
@ -14328,6 +14341,7 @@ def getGlobalNames(config):
for desc in config.getDescriptors(registersGlobalNamesOnWindow=True):
names.append((desc.name, desc))
names.extend((n.identifier.name, desc) for n in desc.interface.namedConstructors)
names.extend((n, desc) for n in desc.interface.legacyWindowAliases)
return names
class CGGlobalNames(CGGeneric):

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

@ -704,6 +704,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# outputs the constructs in the order that namedConstructors enumerates
# them.
self.namedConstructors = list()
self.legacyWindowAliases = []
self.implementedInterfaces = set()
self._consequential = False
self._isKnownNonPartial = False
@ -774,6 +775,16 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
IDLExposureMixins.finish(self, scope)
if len(self.legacyWindowAliases) > 0:
if not self.hasInterfaceObject():
raise WebIDLError("Interface %s unexpectedly has [LegacyWindowAlias] "
"and [NoInterfaceObject] together" % self.identifier.name,
[self.location])
if not self.isExposedInWindow():
raise WebIDLError("Interface %s has [LegacyWindowAlias] "
"but not exposed in Window" % self.identifier.name,
[self.location])
# Now go ahead and merge in our partial interfaces.
for partial in self._partialInterfaces:
partial.finish(scope)
@ -1733,6 +1744,18 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.parentScope.addIfaceGlobalNames(self.identifier.name,
[self.identifier.name])
self._isOnGlobalProtoChain = True
elif identifier == "LegacyWindowAlias":
if attr.hasValue():
self.legacyWindowAliases = [attr.value()]
elif attr.hasArgs():
self.legacyWindowAliases = attr.args()
else:
raise WebIDLError("[%s] must either take an identifier "
"or take an identifier list" % identifier,
[attr.location])
for alias in self.legacyWindowAliases:
unresolved = IDLUnresolvedIdentifier(attr.location, alias)
IDLObjectWithIdentifier(attr.location, self.parentScope, unresolved)
elif identifier == "SecureContext":
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,

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

@ -374,3 +374,89 @@ def WebIDLTest(parser, harness):
threw = True
harness.ok(threw,
"Should not allow unknown extended attributes on interfaces")
parser = parser.reset()
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
[Exposed=Window, LegacyWindowAlias=(C, D)]
interface E {};
""");
results = parser.finish();
harness.check(results[1].legacyWindowAliases, ["A"],
"Should support a single identifier")
harness.check(results[2].legacyWindowAliases, ["C", "D"],
"Should support an identifier list")
parser = parser.reset()
threw = False
try:
parser.parse("""
[LegacyWindowAlias]
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] with no value")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Exposed=Worker, LegacyWindowAlias=B]
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] without Window exposure")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
interface A {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
[Exposed=Window, LegacyWindowAlias=A]
interface C {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")

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

@ -95,7 +95,8 @@ interface DOMMatrixReadOnly {
Constructor(Float64Array array64),
Constructor(sequence<unrestricted double> numberSequence),
Exposed=(Window,Worker),
Serializable]
Serializable,
LegacyWindowAlias=WebKitCSSMatrix]
interface DOMMatrix : DOMMatrixReadOnly {
[NewObject, Throws] static DOMMatrix fromMatrix(optional DOMMatrixInit other);
[NewObject, Throws] static DOMMatrixReadOnly fromFloat32Array(Float32Array array32);

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

@ -12,7 +12,8 @@
*/
[Constructor(USVString url, optional USVString base),
Exposed=(Window,Worker,WorkerDebugger)]
Exposed=(Window,Worker,WorkerDebugger),
LegacyWindowAlias=webkitURL]
interface URL {
// Bug 824857: no support for stringifier attributes yet.
// stringifier attribute USVString href;

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

@ -1,37 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://compat.spec.whatwg.org/#webkitcssmatrix-interface
*/
[Constructor,
Constructor(DOMString transformList),
Constructor(WebKitCSSMatrix other),
Exposed=Window,
Func="mozilla::dom::WebKitCSSMatrix::FeatureEnabled"]
interface WebKitCSSMatrix : DOMMatrix {
// Mutable transform methods
[Throws]
WebKitCSSMatrix setMatrixValue(DOMString transformList);
// Immutable transform methods
[Throws]
WebKitCSSMatrix multiply(optional DOMMatrixInit other);
[Throws]
WebKitCSSMatrix inverse();
WebKitCSSMatrix translate(optional unrestricted double tx = 0,
optional unrestricted double ty = 0,
optional unrestricted double tz = 0);
WebKitCSSMatrix rotate(optional unrestricted double rotX = 0,
optional unrestricted double rotY,
optional unrestricted double rotZ);
WebKitCSSMatrix rotateAxisAngle(optional unrestricted double x = 0,
optional unrestricted double y = 0,
optional unrestricted double z = 0,
optional unrestricted double angle = 0);
WebKitCSSMatrix skewX(optional unrestricted double sx = 0);
WebKitCSSMatrix skewY(optional unrestricted double sy = 0);
};

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

@ -331,9 +331,6 @@ with Files("WebGL*"):
with Files("WebGPU*"):
BUG_COMPONENT = ("Core", "Canvas: WebGL")
with Files("WebKitCSSMatrix.webidl"):
BUG_COMPONENT = ("Core", "DOM: CSS Object Model")
with Files("Webrtc*"):
BUG_COMPONENT = ("Core", "WebRTC")
@ -935,7 +932,6 @@ WEBIDL_FILES = [
'WebGLRenderingContext.webidl',
'WebGPU.webidl',
'WebGPUExtras.webidl',
'WebKitCSSMatrix.webidl',
'WebSocket.webidl',
'WheelEvent.webidl',
'WidevineCDMManifest.webidl',

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

@ -1,4 +0,0 @@
[WebKitCSSMatrix.html]
[Equivalence test]
expected: FAIL

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

@ -1,6 +0,0 @@
[idlharness.any.html]
[URL interface: legacy window alias]
expected: FAIL
[idlharness.any.worker.html]