diff options
Diffstat (limited to 'dom/bindings/test')
133 files changed, 15175 insertions, 0 deletions
diff --git a/dom/bindings/test/Makefile.in b/dom/bindings/test/Makefile.in new file mode 100644 index 0000000000..e338cc30d0 --- /dev/null +++ b/dom/bindings/test/Makefile.in @@ -0,0 +1,17 @@ +# 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/. + +ifdef COMPILE_ENVIRONMENT + +include ../webidlsrcs.mk + +# $(test_sources) comes from webidlsrcs.mk. +# TODO Update this variable in backend.mk. +CPPSRCS += $(addprefix ../,$(test_sources)) + +# Include rules.mk before any of our targets so our first target is coming from +# rules.mk and running make with no target in this dir does the right thing. +include $(topsrcdir)/config/rules.mk + +endif diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h new file mode 100644 index 0000000000..cdd2c57bdd --- /dev/null +++ b/dom/bindings/test/TestBindingHeader.h @@ -0,0 +1,1765 @@ +/* -*- 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 TestBindingHeader_h +#define TestBindingHeader_h + +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/Record.h" +#include "mozilla/dom/TypedArray.h" +#include "mozilla/ErrorResult.h" +#include "nsCOMPtr.h" +#include "nsGenericHTMLElement.h" +#include "nsWrapperCache.h" +#include "js/Object.h" // JS::GetClass + +// Forward declare this before we include TestCodeGenBinding.h, because that +// header relies on including this one for it, for ParentDict. Hopefully it +// won't begin to rely on it in more fundamental ways. +namespace mozilla { +namespace dom { +class DocGroup; +class TestExternalInterface; +class Promise; +} // namespace dom +} // namespace mozilla + +// We don't export TestCodeGenBinding.h, but it's right in our parent dir. +#include "../TestCodeGenBinding.h" + +extern bool TestFuncControlledMember(JSContext*, JSObject*); + +namespace mozilla { +namespace dom { + +// IID for nsRenamedInterface +#define NS_RENAMED_INTERFACE_IID \ + { \ + 0xd4b19ef3, 0xe68b, 0x4e3f, { \ + 0x94, 0xbc, 0xc9, 0xde, 0x3a, 0x69, 0xb0, 0xe8 \ + } \ + } + +class nsRenamedInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_RENAMED_INTERFACE_IID) + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsRenamedInterface, NS_RENAMED_INTERFACE_IID) + +// IID for the TestExternalInterface +#define NS_TEST_EXTERNAL_INTERFACE_IID \ + { \ + 0xd5ba0c99, 0x9b1d, 0x4e71, { \ + 0x8a, 0x94, 0x56, 0x38, 0x6c, 0xa3, 0xda, 0x3d \ + } \ + } +class TestExternalInterface : public nsISupports { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_EXTERNAL_INTERFACE_IID) + NS_DECL_ISUPPORTS +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(TestExternalInterface, + NS_TEST_EXTERNAL_INTERFACE_IID) + +class TestNonWrapperCacheInterface : public nsISupports { + public: + NS_DECL_ISUPPORTS + + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector); +}; + +class OnlyForUseInConstructor : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); +}; + +class TestInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject and GetDocGroup to make binding codegen happy + virtual nsISupports* GetParentObject(); + DocGroup* GetDocGroup() const; + + // And now our actual WebIDL API + // Constructors + static already_AddRefed<TestInterface> Constructor(const GlobalObject&); + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + const nsAString&); + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + uint32_t, + const Nullable<bool>&); + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + TestInterface*); + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + uint32_t, TestInterface&); + + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + const ArrayBuffer&); + static already_AddRefed<TestInterface> Constructor(const GlobalObject&, + const Uint8Array&); + /* static + already_AddRefed<TestInterface> + Constructor(const GlobalObject&, uint32_t, uint32_t, + const TestInterfaceOrOnlyForUseInConstructor&); + */ + + static already_AddRefed<TestInterface> Test(const GlobalObject&, + ErrorResult&); + static already_AddRefed<TestInterface> Test(const GlobalObject&, + const nsAString&, ErrorResult&); + static already_AddRefed<TestInterface> Test(const GlobalObject&, + const nsACString&, ErrorResult&); + + static already_AddRefed<TestInterface> Test2( + const GlobalObject&, const DictForConstructor&, JS::Handle<JS::Value>, + JS::Handle<JSObject*>, JS::Handle<JSObject*>, const Sequence<Dict>&, + JS::Handle<JS::Value>, const Optional<JS::Handle<JSObject*>>&, + const Optional<JS::Handle<JSObject*>>&, ErrorResult&); + + static already_AddRefed<TestInterface> Test3(const GlobalObject&, + const LongOrStringAnyRecord&, + ErrorResult&); + + static already_AddRefed<TestInterface> Test4( + const GlobalObject&, const Record<nsString, Record<nsString, JS::Value>>&, + ErrorResult&); + + static already_AddRefed<TestInterface> Test5( + const GlobalObject&, + const Record< + nsString, + Sequence<Record<nsString, + Record<nsString, Sequence<Sequence<JS::Value>>>>>>&, + ErrorResult&); + + static already_AddRefed<TestInterface> Test6( + const GlobalObject&, + const Sequence<Record< + nsCString, + Sequence<Sequence<Record<nsCString, Record<nsString, JS::Value>>>>>>&, + ErrorResult&); + + // Integer types + int8_t ReadonlyByte(); + int8_t WritableByte(); + void SetWritableByte(int8_t); + void PassByte(int8_t); + int8_t ReceiveByte(); + void PassOptionalByte(const Optional<int8_t>&); + void PassOptionalByteBeforeRequired(const Optional<int8_t>&, int8_t); + void PassOptionalByteWithDefault(int8_t); + void PassOptionalByteWithDefaultBeforeRequired(int8_t, int8_t); + void PassNullableByte(const Nullable<int8_t>&); + void PassOptionalNullableByte(const Optional<Nullable<int8_t>>&); + void PassVariadicByte(const Sequence<int8_t>&); + int8_t CachedByte(); + int8_t CachedConstantByte(); + int8_t CachedWritableByte(); + void SetCachedWritableByte(int8_t); + int8_t SideEffectFreeByte(); + void SetSideEffectFreeByte(int8_t); + int8_t DomDependentByte(); + void SetDomDependentByte(int8_t); + int8_t ConstantByte(); + int8_t DeviceStateDependentByte(); + int8_t ReturnByteSideEffectFree(); + int8_t ReturnDOMDependentByte(); + int8_t ReturnConstantByte(); + int8_t ReturnDeviceStateDependentByte(); + + void UnsafePrerenderMethod(); + int32_t UnsafePrerenderWritable(); + void SetUnsafePrerenderWritable(int32_t); + int32_t UnsafePrerenderReadonly(); + int16_t ReadonlyShort(); + int16_t WritableShort(); + void SetWritableShort(int16_t); + void PassShort(int16_t); + int16_t ReceiveShort(); + void PassOptionalShort(const Optional<int16_t>&); + void PassOptionalShortWithDefault(int16_t); + + int32_t ReadonlyLong(); + int32_t WritableLong(); + void SetWritableLong(int32_t); + void PassLong(int32_t); + int16_t ReceiveLong(); + void PassOptionalLong(const Optional<int32_t>&); + void PassOptionalLongWithDefault(int32_t); + + int64_t ReadonlyLongLong(); + int64_t WritableLongLong(); + void SetWritableLongLong(int64_t); + void PassLongLong(int64_t); + int64_t ReceiveLongLong(); + void PassOptionalLongLong(const Optional<int64_t>&); + void PassOptionalLongLongWithDefault(int64_t); + + uint8_t ReadonlyOctet(); + uint8_t WritableOctet(); + void SetWritableOctet(uint8_t); + void PassOctet(uint8_t); + uint8_t ReceiveOctet(); + void PassOptionalOctet(const Optional<uint8_t>&); + void PassOptionalOctetWithDefault(uint8_t); + + uint16_t ReadonlyUnsignedShort(); + uint16_t WritableUnsignedShort(); + void SetWritableUnsignedShort(uint16_t); + void PassUnsignedShort(uint16_t); + uint16_t ReceiveUnsignedShort(); + void PassOptionalUnsignedShort(const Optional<uint16_t>&); + void PassOptionalUnsignedShortWithDefault(uint16_t); + + uint32_t ReadonlyUnsignedLong(); + uint32_t WritableUnsignedLong(); + void SetWritableUnsignedLong(uint32_t); + void PassUnsignedLong(uint32_t); + uint32_t ReceiveUnsignedLong(); + void PassOptionalUnsignedLong(const Optional<uint32_t>&); + void PassOptionalUnsignedLongWithDefault(uint32_t); + + uint64_t ReadonlyUnsignedLongLong(); + uint64_t WritableUnsignedLongLong(); + void SetWritableUnsignedLongLong(uint64_t); + void PassUnsignedLongLong(uint64_t); + uint64_t ReceiveUnsignedLongLong(); + void PassOptionalUnsignedLongLong(const Optional<uint64_t>&); + void PassOptionalUnsignedLongLongWithDefault(uint64_t); + + float WritableFloat() const; + void SetWritableFloat(float); + float WritableUnrestrictedFloat() const; + void SetWritableUnrestrictedFloat(float); + Nullable<float> GetWritableNullableFloat() const; + void SetWritableNullableFloat(const Nullable<float>&); + Nullable<float> GetWritableNullableUnrestrictedFloat() const; + void SetWritableNullableUnrestrictedFloat(const Nullable<float>&); + double WritableDouble() const; + void SetWritableDouble(double); + double WritableUnrestrictedDouble() const; + void SetWritableUnrestrictedDouble(double); + Nullable<double> GetWritableNullableDouble() const; + void SetWritableNullableDouble(const Nullable<double>&); + Nullable<double> GetWritableNullableUnrestrictedDouble() const; + void SetWritableNullableUnrestrictedDouble(const Nullable<double>&); + void PassFloat(float, float, const Nullable<float>&, const Nullable<float>&, + double, double, const Nullable<double>&, + const Nullable<double>&, const Sequence<float>&, + const Sequence<float>&, const Sequence<Nullable<float>>&, + const Sequence<Nullable<float>>&, const Sequence<double>&, + const Sequence<double>&, const Sequence<Nullable<double>>&, + const Sequence<Nullable<double>>&); + void PassLenientFloat(float, float, const Nullable<float>&, + const Nullable<float>&, double, double, + const Nullable<double>&, const Nullable<double>&, + const Sequence<float>&, const Sequence<float>&, + const Sequence<Nullable<float>>&, + const Sequence<Nullable<float>>&, + const Sequence<double>&, const Sequence<double>&, + const Sequence<Nullable<double>>&, + const Sequence<Nullable<double>>&); + float LenientFloatAttr() const; + void SetLenientFloatAttr(float); + double LenientDoubleAttr() const; + void SetLenientDoubleAttr(double); + + void PassUnrestricted(float arg1, float arg2, float arg3, float arg4, + double arg5, double arg6, double arg7, double arg8); + + // Interface types + already_AddRefed<TestInterface> ReceiveSelf(); + already_AddRefed<TestInterface> ReceiveNullableSelf(); + TestInterface* ReceiveWeakSelf(); + TestInterface* ReceiveWeakNullableSelf(); + void PassSelf(TestInterface&); + void PassNullableSelf(TestInterface*); + already_AddRefed<TestInterface> NonNullSelf(); + void SetNonNullSelf(TestInterface&); + already_AddRefed<TestInterface> GetNullableSelf(); + already_AddRefed<TestInterface> CachedSelf(); + void SetNullableSelf(TestInterface*); + void PassOptionalSelf(const Optional<TestInterface*>&); + void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface>>&); + void PassOptionalSelfWithDefault(TestInterface*); + + already_AddRefed<TestNonWrapperCacheInterface> + ReceiveNonWrapperCacheInterface(); + already_AddRefed<TestNonWrapperCacheInterface> + ReceiveNullableNonWrapperCacheInterface(); + void ReceiveNonWrapperCacheInterfaceSequence( + nsTArray<RefPtr<TestNonWrapperCacheInterface>>&); + void ReceiveNullableNonWrapperCacheInterfaceSequence( + nsTArray<RefPtr<TestNonWrapperCacheInterface>>&); + void ReceiveNonWrapperCacheInterfaceNullableSequence( + Nullable<nsTArray<RefPtr<TestNonWrapperCacheInterface>>>&); + void ReceiveNullableNonWrapperCacheInterfaceNullableSequence( + Nullable<nsTArray<RefPtr<TestNonWrapperCacheInterface>>>&); + + already_AddRefed<TestExternalInterface> ReceiveExternal(); + already_AddRefed<TestExternalInterface> ReceiveNullableExternal(); + TestExternalInterface* ReceiveWeakExternal(); + TestExternalInterface* ReceiveWeakNullableExternal(); + void PassExternal(TestExternalInterface*); + void PassNullableExternal(TestExternalInterface*); + already_AddRefed<TestExternalInterface> NonNullExternal(); + void SetNonNullExternal(TestExternalInterface*); + already_AddRefed<TestExternalInterface> GetNullableExternal(); + void SetNullableExternal(TestExternalInterface*); + void PassOptionalExternal(const Optional<TestExternalInterface*>&); + void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&); + void PassOptionalExternalWithDefault(TestExternalInterface*); + + already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface(); + already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface(); + TestCallbackInterface* ReceiveWeakCallbackInterface(); + TestCallbackInterface* ReceiveWeakNullableCallbackInterface(); + void PassCallbackInterface(TestCallbackInterface&); + void PassNullableCallbackInterface(TestCallbackInterface*); + already_AddRefed<TestCallbackInterface> NonNullCallbackInterface(); + void SetNonNullCallbackInterface(TestCallbackInterface&); + already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface(); + void SetNullableCallbackInterface(TestCallbackInterface*); + void PassOptionalCallbackInterface( + const Optional<RefPtr<TestCallbackInterface>>&); + void PassOptionalNonNullCallbackInterface( + const Optional<OwningNonNull<TestCallbackInterface>>&); + void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*); + + // Sequence types + void GetReadonlySequence(nsTArray<int32_t>&); + void GetReadonlySequenceOfDictionaries(JSContext*, nsTArray<Dict>&); + void GetReadonlyNullableSequenceOfDictionaries(JSContext*, + Nullable<nsTArray<Dict>>&); + void GetReadonlyFrozenSequence(JSContext*, nsTArray<Dict>&); + void GetReadonlyFrozenNullableSequence(JSContext*, Nullable<nsTArray<Dict>>&); + void ReceiveSequence(nsTArray<int32_t>&); + void ReceiveNullableSequence(Nullable<nsTArray<int32_t>>&); + void ReceiveSequenceOfNullableInts(nsTArray<Nullable<int32_t>>&); + void ReceiveNullableSequenceOfNullableInts( + Nullable<nsTArray<Nullable<int32_t>>>&); + void PassSequence(const Sequence<int32_t>&); + void PassNullableSequence(const Nullable<Sequence<int32_t>>&); + void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t>>&); + void PassOptionalSequenceOfNullableInts( + const Optional<Sequence<Nullable<int32_t>>>&); + void PassOptionalNullableSequenceOfNullableInts( + const Optional<Nullable<Sequence<Nullable<int32_t>>>>&); + void ReceiveCastableObjectSequence(nsTArray<RefPtr<TestInterface>>&); + void ReceiveCallbackObjectSequence(nsTArray<RefPtr<TestCallbackInterface>>&); + void ReceiveNullableCastableObjectSequence(nsTArray<RefPtr<TestInterface>>&); + void ReceiveNullableCallbackObjectSequence( + nsTArray<RefPtr<TestCallbackInterface>>&); + void ReceiveCastableObjectNullableSequence( + Nullable<nsTArray<RefPtr<TestInterface>>>&); + void ReceiveNullableCastableObjectNullableSequence( + Nullable<nsTArray<RefPtr<TestInterface>>>&); + void ReceiveWeakCastableObjectSequence(nsTArray<RefPtr<TestInterface>>&); + void ReceiveWeakNullableCastableObjectSequence( + nsTArray<RefPtr<TestInterface>>&); + void ReceiveWeakCastableObjectNullableSequence( + Nullable<nsTArray<RefPtr<TestInterface>>>&); + void ReceiveWeakNullableCastableObjectNullableSequence( + Nullable<nsTArray<RefPtr<TestInterface>>>&); + void PassCastableObjectSequence( + const Sequence<OwningNonNull<TestInterface>>&); + void PassNullableCastableObjectSequence( + const Sequence<RefPtr<TestInterface>>&); + void PassCastableObjectNullableSequence( + const Nullable<Sequence<OwningNonNull<TestInterface>>>&); + void PassNullableCastableObjectNullableSequence( + const Nullable<Sequence<RefPtr<TestInterface>>>&); + void PassOptionalSequence(const Optional<Sequence<int32_t>>&); + void PassOptionalSequenceWithDefaultValue(const Sequence<int32_t>&); + void PassOptionalNullableSequence( + const Optional<Nullable<Sequence<int32_t>>>&); + void PassOptionalNullableSequenceWithDefaultValue( + const Nullable<Sequence<int32_t>>&); + void PassOptionalNullableSequenceWithDefaultValue2( + const Nullable<Sequence<int32_t>>&); + void PassOptionalObjectSequence( + const Optional<Sequence<OwningNonNull<TestInterface>>>&); + void PassExternalInterfaceSequence( + const Sequence<RefPtr<TestExternalInterface>>&); + void PassNullableExternalInterfaceSequence( + const Sequence<RefPtr<TestExternalInterface>>&); + + void ReceiveStringSequence(nsTArray<nsString>&); + void PassStringSequence(const Sequence<nsString>&); + + void ReceiveByteStringSequence(nsTArray<nsCString>&); + void PassByteStringSequence(const Sequence<nsCString>&); + + void ReceiveUTF8StringSequence(nsTArray<nsCString>&); + void PassUTF8StringSequence(const Sequence<nsCString>&); + + void ReceiveAnySequence(JSContext*, nsTArray<JS::Value>&); + void ReceiveNullableAnySequence(JSContext*, Nullable<nsTArray<JS::Value>>&); + void ReceiveAnySequenceSequence(JSContext*, nsTArray<nsTArray<JS::Value>>&); + + void ReceiveObjectSequence(JSContext*, nsTArray<JSObject*>&); + void ReceiveNullableObjectSequence(JSContext*, nsTArray<JSObject*>&); + + void PassSequenceOfSequences(const Sequence<Sequence<int32_t>>&); + void PassSequenceOfSequencesOfSequences( + const Sequence<Sequence<Sequence<int32_t>>>&); + void ReceiveSequenceOfSequences(nsTArray<nsTArray<int32_t>>&); + void ReceiveSequenceOfSequencesOfSequences( + nsTArray<nsTArray<nsTArray<int32_t>>>&); + + // Record types + void PassRecord(const Record<nsString, int32_t>&); + void PassNullableRecord(const Nullable<Record<nsString, int32_t>>&); + void PassRecordOfNullableInts(const Record<nsString, Nullable<int32_t>>&); + void PassOptionalRecordOfNullableInts( + const Optional<Record<nsString, Nullable<int32_t>>>&); + void PassOptionalNullableRecordOfNullableInts( + const Optional<Nullable<Record<nsString, Nullable<int32_t>>>>&); + void PassCastableObjectRecord( + const Record<nsString, OwningNonNull<TestInterface>>&); + void PassNullableCastableObjectRecord( + const Record<nsString, RefPtr<TestInterface>>&); + void PassCastableObjectNullableRecord( + const Nullable<Record<nsString, OwningNonNull<TestInterface>>>&); + void PassNullableCastableObjectNullableRecord( + const Nullable<Record<nsString, RefPtr<TestInterface>>>&); + void PassOptionalRecord(const Optional<Record<nsString, int32_t>>&); + void PassOptionalNullableRecord( + const Optional<Nullable<Record<nsString, int32_t>>>&); + void PassOptionalNullableRecordWithDefaultValue( + const Nullable<Record<nsString, int32_t>>&); + void PassOptionalObjectRecord( + const Optional<Record<nsString, OwningNonNull<TestInterface>>>&); + void PassExternalInterfaceRecord( + const Record<nsString, RefPtr<TestExternalInterface>>&); + void PassNullableExternalInterfaceRecord( + const Record<nsString, RefPtr<TestExternalInterface>>&); + void PassStringRecord(const Record<nsString, nsString>&); + void PassByteStringRecord(const Record<nsString, nsCString>&); + void PassUTF8StringRecord(const Record<nsString, nsCString>&); + void PassRecordOfRecords(const Record<nsString, Record<nsString, int32_t>>&); + void ReceiveRecord(Record<nsString, int32_t>&); + void ReceiveNullableRecord(Nullable<Record<nsString, int32_t>>&); + void ReceiveRecordOfNullableInts(Record<nsString, Nullable<int32_t>>&); + void ReceiveNullableRecordOfNullableInts( + Nullable<Record<nsString, Nullable<int32_t>>>&); + void ReceiveRecordOfRecords(Record<nsString, Record<nsString, int32_t>>&); + void ReceiveAnyRecord(JSContext*, Record<nsString, JS::Value>&); + + // Typed array types + void PassArrayBuffer(const ArrayBuffer&); + void PassNullableArrayBuffer(const Nullable<ArrayBuffer>&); + void PassOptionalArrayBuffer(const Optional<ArrayBuffer>&); + void PassOptionalNullableArrayBuffer(const Optional<Nullable<ArrayBuffer>>&); + void PassOptionalNullableArrayBufferWithDefaultValue( + const Nullable<ArrayBuffer>&); + void PassArrayBufferView(const ArrayBufferView&); + void PassInt8Array(const Int8Array&); + void PassInt16Array(const Int16Array&); + void PassInt32Array(const Int32Array&); + void PassUint8Array(const Uint8Array&); + void PassUint16Array(const Uint16Array&); + void PassUint32Array(const Uint32Array&); + void PassUint8ClampedArray(const Uint8ClampedArray&); + void PassFloat32Array(const Float32Array&); + void PassFloat64Array(const Float64Array&); + void PassSequenceOfArrayBuffers(const Sequence<ArrayBuffer>&); + void PassSequenceOfNullableArrayBuffers( + const Sequence<Nullable<ArrayBuffer>>&); + void PassRecordOfArrayBuffers(const Record<nsString, ArrayBuffer>&); + void PassRecordOfNullableArrayBuffers( + const Record<nsString, Nullable<ArrayBuffer>>&); + void PassVariadicTypedArray(const Sequence<Float32Array>&); + void PassVariadicNullableTypedArray(const Sequence<Nullable<Float32Array>>&); + void ReceiveUint8Array(JSContext*, JS::MutableHandle<JSObject*>); + void SetUint8ArrayAttr(const Uint8Array&); + void GetUint8ArrayAttr(JSContext*, JS::MutableHandle<JSObject*>); + + // DOMString types + void PassString(const nsAString&); + void PassNullableString(const nsAString&); + void PassOptionalString(const Optional<nsAString>&); + void PassOptionalStringWithDefaultValue(const nsAString&); + void PassOptionalNullableString(const Optional<nsAString>&); + void PassOptionalNullableStringWithDefaultValue(const nsAString&); + void PassVariadicString(const Sequence<nsString>&); + void ReceiveString(DOMString&); + + // ByteString types + void PassByteString(const nsCString&); + void PassNullableByteString(const nsCString&); + void PassOptionalByteString(const Optional<nsCString>&); + void PassOptionalByteStringWithDefaultValue(const nsCString&); + void PassOptionalNullableByteString(const Optional<nsCString>&); + void PassOptionalNullableByteStringWithDefaultValue(const nsCString&); + void PassVariadicByteString(const Sequence<nsCString>&); + void PassOptionalUnionByteString(const Optional<ByteStringOrLong>&); + void PassOptionalUnionByteStringWithDefaultValue(const ByteStringOrLong&); + + // UTF8String types + void PassUTF8String(const nsACString&); + void PassNullableUTF8String(const nsACString&); + void PassOptionalUTF8String(const Optional<nsACString>&); + void PassOptionalUTF8StringWithDefaultValue(const nsACString&); + void PassOptionalNullableUTF8String(const Optional<nsACString>&); + void PassOptionalNullableUTF8StringWithDefaultValue(const nsACString&); + void PassVariadicUTF8String(const Sequence<nsCString>&); + void PassOptionalUnionUTF8String(const Optional<UTF8StringOrLong>&); + void PassOptionalUnionUTF8StringWithDefaultValue(const UTF8StringOrLong&); + + // USVString types + void PassUSVS(const nsAString&); + void PassNullableUSVS(const nsAString&); + void PassOptionalUSVS(const Optional<nsAString>&); + void PassOptionalUSVSWithDefaultValue(const nsAString&); + void PassOptionalNullableUSVS(const Optional<nsAString>&); + void PassOptionalNullableUSVSWithDefaultValue(const nsAString&); + void PassVariadicUSVS(const Sequence<nsString>&); + void ReceiveUSVS(DOMString&); + + // JSString types + void PassJSString(JSContext*, JS::Handle<JSString*>); + void PassOptionalJSStringWithDefaultValue(JSContext*, JS::Handle<JSString*>); + void ReceiveJSString(JSContext*, JS::MutableHandle<JSString*>); + void GetReadonlyJSStringAttr(JSContext*, JS::MutableHandle<JSString*>); + void GetJsStringAttr(JSContext*, JS::MutableHandle<JSString*>); + void SetJsStringAttr(JSContext*, JS::Handle<JSString*>); + + // Enumerated types + void PassEnum(TestEnum); + void PassNullableEnum(const Nullable<TestEnum>&); + void PassOptionalEnum(const Optional<TestEnum>&); + void PassEnumWithDefault(TestEnum); + void PassOptionalNullableEnum(const Optional<Nullable<TestEnum>>&); + void PassOptionalNullableEnumWithDefaultValue(const Nullable<TestEnum>&); + void PassOptionalNullableEnumWithDefaultValue2(const Nullable<TestEnum>&); + TestEnum ReceiveEnum(); + Nullable<TestEnum> ReceiveNullableEnum(); + TestEnum EnumAttribute(); + TestEnum ReadonlyEnumAttribute(); + void SetEnumAttribute(TestEnum); + + // Callback types + void PassCallback(TestCallback&); + void PassNullableCallback(TestCallback*); + void PassOptionalCallback(const Optional<OwningNonNull<TestCallback>>&); + void PassOptionalNullableCallback(const Optional<RefPtr<TestCallback>>&); + void PassOptionalNullableCallbackWithDefaultValue(TestCallback*); + already_AddRefed<TestCallback> ReceiveCallback(); + already_AddRefed<TestCallback> ReceiveNullableCallback(); + void PassNullableTreatAsNullCallback(TestTreatAsNullCallback*); + void PassOptionalNullableTreatAsNullCallback( + const Optional<RefPtr<TestTreatAsNullCallback>>&); + void PassOptionalNullableTreatAsNullCallbackWithDefaultValue( + TestTreatAsNullCallback*); + void SetTreatAsNullCallback(TestTreatAsNullCallback&); + already_AddRefed<TestTreatAsNullCallback> TreatAsNullCallback(); + void SetNullableTreatAsNullCallback(TestTreatAsNullCallback*); + already_AddRefed<TestTreatAsNullCallback> GetNullableTreatAsNullCallback(); + + void ForceCallbackGeneration( + TestIntegerReturn&, TestNullableIntegerReturn&, TestBooleanReturn&, + TestFloatReturn&, TestStringReturn&, TestEnumReturn&, + TestInterfaceReturn&, TestNullableInterfaceReturn&, + TestExternalInterfaceReturn&, TestNullableExternalInterfaceReturn&, + TestCallbackInterfaceReturn&, TestNullableCallbackInterfaceReturn&, + TestCallbackReturn&, TestNullableCallbackReturn&, TestObjectReturn&, + TestNullableObjectReturn&, TestTypedArrayReturn&, + TestNullableTypedArrayReturn&, TestSequenceReturn&, + TestNullableSequenceReturn&, TestIntegerArguments&, + TestInterfaceArguments&, TestStringEnumArguments&, TestObjectArguments&, + TestOptionalArguments&, TestUndefinedConstruction&, + TestIntegerConstruction&, TestBooleanConstruction&, + TestFloatConstruction&, TestStringConstruction&, TestEnumConstruction&, + TestInterfaceConstruction&, TestExternalInterfaceConstruction&, + TestCallbackInterfaceConstruction&, TestCallbackConstruction&, + TestObjectConstruction&, TestTypedArrayConstruction&, + TestSequenceConstruction&); + + // Any types + void PassAny(JSContext*, JS::Handle<JS::Value>); + void PassVariadicAny(JSContext*, const Sequence<JS::Value>&); + void PassOptionalAny(JSContext*, JS::Handle<JS::Value>); + void PassAnyDefaultNull(JSContext*, JS::Handle<JS::Value>); + void PassSequenceOfAny(JSContext*, const Sequence<JS::Value>&); + void PassNullableSequenceOfAny(JSContext*, + const Nullable<Sequence<JS::Value>>&); + void PassOptionalSequenceOfAny(JSContext*, + const Optional<Sequence<JS::Value>>&); + void PassOptionalNullableSequenceOfAny( + JSContext*, const Optional<Nullable<Sequence<JS::Value>>>&); + void PassOptionalSequenceOfAnyWithDefaultValue( + JSContext*, const Nullable<Sequence<JS::Value>>&); + void PassSequenceOfSequenceOfAny(JSContext*, + const Sequence<Sequence<JS::Value>>&); + void PassSequenceOfNullableSequenceOfAny( + JSContext*, const Sequence<Nullable<Sequence<JS::Value>>>&); + void PassNullableSequenceOfNullableSequenceOfAny( + JSContext*, const Nullable<Sequence<Nullable<Sequence<JS::Value>>>>&); + void PassOptionalNullableSequenceOfNullableSequenceOfAny( + JSContext*, + const Optional<Nullable<Sequence<Nullable<Sequence<JS::Value>>>>>&); + void PassRecordOfAny(JSContext*, const Record<nsString, JS::Value>&); + void PassNullableRecordOfAny(JSContext*, + const Nullable<Record<nsString, JS::Value>>&); + void PassOptionalRecordOfAny(JSContext*, + const Optional<Record<nsString, JS::Value>>&); + void PassOptionalNullableRecordOfAny( + JSContext*, const Optional<Nullable<Record<nsString, JS::Value>>>&); + void PassOptionalRecordOfAnyWithDefaultValue( + JSContext*, const Nullable<Record<nsString, JS::Value>>&); + void PassRecordOfRecordOfAny( + JSContext*, const Record<nsString, Record<nsString, JS::Value>>&); + void PassRecordOfNullableRecordOfAny( + JSContext*, + const Record<nsString, Nullable<Record<nsString, JS::Value>>>&); + void PassNullableRecordOfNullableRecordOfAny( + JSContext*, + const Nullable<Record<nsString, Nullable<Record<nsString, JS::Value>>>>&); + void PassOptionalNullableRecordOfNullableRecordOfAny( + JSContext*, + const Optional< + Nullable<Record<nsString, Nullable<Record<nsString, JS::Value>>>>>&); + void PassOptionalNullableRecordOfNullableSequenceOfAny( + JSContext*, + const Optional< + Nullable<Record<nsString, Nullable<Sequence<JS::Value>>>>>&); + void PassOptionalNullableSequenceOfNullableRecordOfAny( + JSContext*, + const Optional< + Nullable<Sequence<Nullable<Record<nsString, JS::Value>>>>>&); + void ReceiveAny(JSContext*, JS::MutableHandle<JS::Value>); + + // object types + void PassObject(JSContext*, JS::Handle<JSObject*>); + void PassVariadicObject(JSContext*, const Sequence<JSObject*>&); + void PassNullableObject(JSContext*, JS::Handle<JSObject*>); + void PassVariadicNullableObject(JSContext*, const Sequence<JSObject*>&); + void PassOptionalObject(JSContext*, const Optional<JS::Handle<JSObject*>>&); + void PassOptionalNullableObject(JSContext*, + const Optional<JS::Handle<JSObject*>>&); + void PassOptionalNullableObjectWithDefaultValue(JSContext*, + JS::Handle<JSObject*>); + void PassSequenceOfObject(JSContext*, const Sequence<JSObject*>&); + void PassSequenceOfNullableObject(JSContext*, const Sequence<JSObject*>&); + void PassNullableSequenceOfObject(JSContext*, + const Nullable<Sequence<JSObject*>>&); + void PassOptionalNullableSequenceOfNullableSequenceOfObject( + JSContext*, + const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*>>>>>&); + void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject( + JSContext*, + const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*>>>>>&); + void PassRecordOfObject(JSContext*, const Record<nsString, JSObject*>&); + void ReceiveObject(JSContext*, JS::MutableHandle<JSObject*>); + void ReceiveNullableObject(JSContext*, JS::MutableHandle<JSObject*>); + + // Union types + void PassUnion(JSContext*, const ObjectOrLong& arg); + void PassUnionWithNullable(JSContext* cx, const ObjectOrNullOrLong& arg) { + OwningObjectOrLong returnValue; + if (arg.IsNull()) { + } else if (arg.IsObject()) { + JS::Rooted<JSObject*> obj(cx, arg.GetAsObject()); + JS::GetClass(obj); + returnValue.SetAsObject() = obj; + } else { + int32_t i = arg.GetAsLong(); + i += 1; + returnValue.SetAsLong() = i; + } + } +#ifdef DEBUG + void PassUnion2(const LongOrBoolean& arg); + void PassUnion3(JSContext*, const ObjectOrLongOrBoolean& arg); + void PassUnion4(const NodeOrLongOrBoolean& arg); + void PassUnion5(JSContext*, const ObjectOrBoolean& arg); + void PassUnion6(JSContext*, const ObjectOrString& arg); + void PassUnion7(JSContext*, const ObjectOrStringOrLong& arg); + void PassUnion8(JSContext*, const ObjectOrStringOrBoolean& arg); + void PassUnion9(JSContext*, const ObjectOrStringOrLongOrBoolean& arg); + void PassUnion10(const EventInitOrLong& arg); + void PassUnion11(JSContext*, const CustomEventInitOrLong& arg); + void PassUnion12(const EventInitOrLong& arg); + void PassUnion13(JSContext*, const ObjectOrLongOrNull& arg); + void PassUnion14(JSContext*, const ObjectOrLongOrNull& arg); + void PassUnion15(const LongSequenceOrLong&); + void PassUnion16(const Optional<LongSequenceOrLong>&); + void PassUnion17(const LongSequenceOrNullOrLong&); + void PassUnion18(JSContext*, const ObjectSequenceOrLong&); + void PassUnion19(JSContext*, const Optional<ObjectSequenceOrLong>&); + void PassUnion20(JSContext*, const ObjectSequenceOrLong&); + void PassUnion21(const StringLongRecordOrLong&); + void PassUnion22(JSContext*, const StringObjectRecordOrLong&); + void PassUnion23(const ImageDataSequenceOrLong&); + void PassUnion24(const ImageDataOrNullSequenceOrLong&); + void PassUnion25(const ImageDataSequenceSequenceOrLong&); + void PassUnion26(const ImageDataOrNullSequenceSequenceOrLong&); + void PassUnion27(const StringSequenceOrEventInit&); + void PassUnion28(const EventInitOrStringSequence&); + void PassUnionWithCallback(const EventHandlerNonNullOrNullOrLong& arg); + void PassUnionWithByteString(const ByteStringOrLong&); + void PassUnionWithUTF8String(const UTF8StringOrLong&); + void PassUnionWithRecord(const StringStringRecordOrString&); + void PassUnionWithRecordAndSequence( + const StringStringRecordOrStringSequence&); + void PassUnionWithSequenceAndRecord( + const StringSequenceOrStringStringRecord&); + void PassUnionWithUSVS(const USVStringOrLong&); +#endif + void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&); + void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&); + void PassOptionalNullableUnion(JSContext*, + const Optional<Nullable<ObjectOrLong>>&); + void PassOptionalNullableUnionWithDefaultValue(JSContext*, + const Nullable<ObjectOrLong>&); + // void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& + // arg); void PassUnionWithInterfacesAndNullable(const + // TestInterfaceOrNullOrTestExternalInterface& arg); + void PassUnionWithArrayBuffer(const ArrayBufferOrLong&); + void PassUnionWithString(JSContext*, const StringOrObject&); + void PassUnionWithEnum(JSContext*, const SupportedTypeOrObject&); + // void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&); + void PassUnionWithObject(JSContext*, const ObjectOrLong&); + + void PassUnionWithDefaultValue1(const DoubleOrString& arg); + void PassUnionWithDefaultValue2(const DoubleOrString& arg); + void PassUnionWithDefaultValue3(const DoubleOrString& arg); + void PassUnionWithDefaultValue4(const FloatOrString& arg); + void PassUnionWithDefaultValue5(const FloatOrString& arg); + void PassUnionWithDefaultValue6(const FloatOrString& arg); + void PassUnionWithDefaultValue7(const UnrestrictedDoubleOrString& arg); + void PassUnionWithDefaultValue8(const UnrestrictedDoubleOrString& arg); + void PassUnionWithDefaultValue9(const UnrestrictedDoubleOrString& arg); + void PassUnionWithDefaultValue10(const UnrestrictedDoubleOrString& arg); + void PassUnionWithDefaultValue11(const UnrestrictedFloatOrString& arg); + void PassUnionWithDefaultValue12(const UnrestrictedFloatOrString& arg); + void PassUnionWithDefaultValue13(const UnrestrictedFloatOrString& arg); + void PassUnionWithDefaultValue14(const DoubleOrByteString& arg); + void PassUnionWithDefaultValue15(const DoubleOrByteString& arg); + void PassUnionWithDefaultValue16(const DoubleOrByteString& arg); + void PassUnionWithDefaultValue17(const DoubleOrSupportedType& arg); + void PassUnionWithDefaultValue18(const DoubleOrSupportedType& arg); + void PassUnionWithDefaultValue19(const DoubleOrSupportedType& arg); + void PassUnionWithDefaultValue20(const DoubleOrUSVString& arg); + void PassUnionWithDefaultValue21(const DoubleOrUSVString& arg); + void PassUnionWithDefaultValue22(const DoubleOrUSVString& arg); + void PassUnionWithDefaultValue23(const DoubleOrUTF8String& arg); + void PassUnionWithDefaultValue24(const DoubleOrUTF8String& arg); + void PassUnionWithDefaultValue25(const DoubleOrUTF8String& arg); + + void PassNullableUnionWithDefaultValue1(const Nullable<DoubleOrString>& arg); + void PassNullableUnionWithDefaultValue2(const Nullable<DoubleOrString>& arg); + void PassNullableUnionWithDefaultValue3(const Nullable<DoubleOrString>& arg); + void PassNullableUnionWithDefaultValue4(const Nullable<FloatOrString>& arg); + void PassNullableUnionWithDefaultValue5(const Nullable<FloatOrString>& arg); + void PassNullableUnionWithDefaultValue6(const Nullable<FloatOrString>& arg); + void PassNullableUnionWithDefaultValue7( + const Nullable<UnrestrictedDoubleOrString>& arg); + void PassNullableUnionWithDefaultValue8( + const Nullable<UnrestrictedDoubleOrString>& arg); + void PassNullableUnionWithDefaultValue9( + const Nullable<UnrestrictedDoubleOrString>& arg); + void PassNullableUnionWithDefaultValue10( + const Nullable<UnrestrictedFloatOrString>& arg); + void PassNullableUnionWithDefaultValue11( + const Nullable<UnrestrictedFloatOrString>& arg); + void PassNullableUnionWithDefaultValue12( + const Nullable<UnrestrictedFloatOrString>& arg); + void PassNullableUnionWithDefaultValue13( + const Nullable<DoubleOrByteString>& arg); + void PassNullableUnionWithDefaultValue14( + const Nullable<DoubleOrByteString>& arg); + void PassNullableUnionWithDefaultValue15( + const Nullable<DoubleOrByteString>& arg); + void PassNullableUnionWithDefaultValue16( + const Nullable<DoubleOrByteString>& arg); + void PassNullableUnionWithDefaultValue17( + const Nullable<DoubleOrSupportedType>& arg); + void PassNullableUnionWithDefaultValue18( + const Nullable<DoubleOrSupportedType>& arg); + void PassNullableUnionWithDefaultValue19( + const Nullable<DoubleOrSupportedType>& arg); + void PassNullableUnionWithDefaultValue20( + const Nullable<DoubleOrSupportedType>& arg); + void PassNullableUnionWithDefaultValue21( + const Nullable<DoubleOrUSVString>& arg); + void PassNullableUnionWithDefaultValue22( + const Nullable<DoubleOrUSVString>& arg); + void PassNullableUnionWithDefaultValue23( + const Nullable<DoubleOrUSVString>& arg); + void PassNullableUnionWithDefaultValue24( + const Nullable<DoubleOrUSVString>& arg); + void PassNullableUnionWithDefaultValue25( + const Nullable<DoubleOrUTF8String>& arg); + void PassNullableUnionWithDefaultValue26( + const Nullable<DoubleOrUTF8String>& arg); + void PassNullableUnionWithDefaultValue27( + const Nullable<DoubleOrUTF8String>& arg); + void PassNullableUnionWithDefaultValue28( + const Nullable<DoubleOrUTF8String>& arg); + + void PassSequenceOfUnions( + const Sequence<OwningCanvasPatternOrCanvasGradient>&); + void PassSequenceOfUnions2(JSContext*, const Sequence<OwningObjectOrLong>&); + void PassVariadicUnion(const Sequence<OwningCanvasPatternOrCanvasGradient>&); + + void PassSequenceOfNullableUnions( + const Sequence<Nullable<OwningCanvasPatternOrCanvasGradient>>&); + void PassVariadicNullableUnion( + const Sequence<Nullable<OwningCanvasPatternOrCanvasGradient>>&); + void PassRecordOfUnions( + const Record<nsString, OwningCanvasPatternOrCanvasGradient>&); + void PassRecordOfUnions2(JSContext*, + const Record<nsString, OwningObjectOrLong>&); + + void ReceiveUnion(OwningCanvasPatternOrCanvasGradient&); + void ReceiveUnion2(JSContext*, OwningObjectOrLong&); + void ReceiveUnionContainingNull(OwningCanvasPatternOrNullOrCanvasGradient&); + void ReceiveNullableUnion(Nullable<OwningCanvasPatternOrCanvasGradient>&); + void ReceiveNullableUnion2(JSContext*, Nullable<OwningObjectOrLong>&); + void ReceiveUnionWithUndefined(OwningUndefinedOrCanvasPattern&); + void ReceiveUnionWithNullableUndefined(OwningUndefinedOrNullOrCanvasPattern&); + void ReceiveUnionWithUndefinedAndNullable( + OwningUndefinedOrCanvasPatternOrNull&); + void ReceiveNullableUnionWithUndefined( + Nullable<OwningUndefinedOrCanvasPattern>&); + + void GetWritableUnion(OwningCanvasPatternOrCanvasGradient&); + void SetWritableUnion(const CanvasPatternOrCanvasGradient&); + void GetWritableUnionContainingNull( + OwningCanvasPatternOrNullOrCanvasGradient&); + void SetWritableUnionContainingNull( + const CanvasPatternOrNullOrCanvasGradient&); + void GetWritableNullableUnion(Nullable<OwningCanvasPatternOrCanvasGradient>&); + void SetWritableNullableUnion(const Nullable<CanvasPatternOrCanvasGradient>&); + void GetWritableUnionWithUndefined(OwningUndefinedOrCanvasPattern&); + void SetWritableUnionWithUndefined(const UndefinedOrCanvasPattern&); + void GetWritableUnionWithNullableUndefined( + OwningUndefinedOrNullOrCanvasPattern&); + void SetWritableUnionWithNullableUndefined( + const UndefinedOrNullOrCanvasPattern&); + void GetWritableUnionWithUndefinedAndNullable( + OwningUndefinedOrCanvasPatternOrNull&); + void SetWritableUnionWithUndefinedAndNullable( + const UndefinedOrCanvasPatternOrNull&); + void GetWritableNullableUnionWithUndefined( + Nullable<OwningUndefinedOrCanvasPattern>&); + void SetWritableNullableUnionWithUndefined( + const Nullable<UndefinedOrCanvasPattern>&); + + // Promise types + void PassPromise(Promise&); + void PassOptionalPromise(const Optional<OwningNonNull<Promise>>&); + void PassPromiseSequence(const Sequence<OwningNonNull<Promise>>&); + void PassPromiseRecord(const Record<nsString, RefPtr<Promise>>&); + Promise* ReceivePromise(); + already_AddRefed<Promise> ReceiveAddrefedPromise(); + + // ObservableArray types + void OnDeleteBooleanObservableArray(bool, uint32_t, ErrorResult&); + void OnSetBooleanObservableArray(bool, uint32_t, ErrorResult&); + void OnDeleteObjectObservableArray(JSContext*, JS::Handle<JSObject*>, + uint32_t, ErrorResult&); + void OnSetObjectObservableArray(JSContext*, JS::Handle<JSObject*>, uint32_t, + ErrorResult&); + void OnDeleteAnyObservableArray(JSContext*, JS::Handle<JS::Value>, uint32_t, + ErrorResult&); + void OnSetAnyObservableArray(JSContext*, JS::Handle<JS::Value>, uint32_t, + ErrorResult&); + void OnDeleteInterfaceObservableArray(TestInterface*, uint32_t, ErrorResult&); + void OnSetInterfaceObservableArray(TestInterface*, uint32_t, ErrorResult&); + void OnDeleteNullableObservableArray(const Nullable<int>&, uint32_t, + ErrorResult&); + void OnSetNullableObservableArray(const Nullable<int>&, uint32_t, + ErrorResult&); + + // binaryNames tests + void MethodRenamedTo(); + void MethodRenamedTo(int8_t); + int8_t AttributeGetterRenamedTo(); + int8_t AttributeRenamedTo(); + void SetAttributeRenamedTo(int8_t); + + // Dictionary tests + void PassDictionary(JSContext*, const Dict&); + void PassDictionary2(JSContext*, const Dict&); + void GetReadonlyDictionary(JSContext*, Dict&); + void GetReadonlyNullableDictionary(JSContext*, Nullable<Dict>&); + void GetWritableDictionary(JSContext*, Dict&); + void SetWritableDictionary(JSContext*, const Dict&); + void GetReadonlyFrozenDictionary(JSContext*, Dict&); + void GetReadonlyFrozenNullableDictionary(JSContext*, Nullable<Dict>&); + void GetWritableFrozenDictionary(JSContext*, Dict&); + void SetWritableFrozenDictionary(JSContext*, const Dict&); + void ReceiveDictionary(JSContext*, Dict&); + void ReceiveNullableDictionary(JSContext*, Nullable<Dict>&); + void PassOtherDictionary(const GrandparentDict&); + void PassSequenceOfDictionaries(JSContext*, const Sequence<Dict>&); + void PassRecordOfDictionaries(const Record<nsString, GrandparentDict>&); + void PassDictionaryOrLong(JSContext*, const Dict&); + void PassDictionaryOrLong(int32_t); + void PassDictContainingDict(JSContext*, const DictContainingDict&); + void PassDictContainingSequence(JSContext*, const DictContainingSequence&); + void ReceiveDictContainingSequence(JSContext*, DictContainingSequence&); + void PassVariadicDictionary(JSContext*, const Sequence<Dict>&); + + // Typedefs + void ExerciseTypedefInterfaces1(TestInterface&); + already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*); + void ExerciseTypedefInterfaces3(TestInterface&); + + // Deprecated methods and attributes + int8_t DeprecatedAttribute(); + void SetDeprecatedAttribute(int8_t); + int8_t DeprecatedMethod(); + int8_t DeprecatedMethodWithContext(JSContext*, const JS::Value&); + + // Static methods and attributes + static void StaticMethod(const GlobalObject&, bool); + static void StaticMethodWithContext(const GlobalObject&, const JS::Value&); + static bool StaticAttribute(const GlobalObject&); + static void SetStaticAttribute(const GlobalObject&, bool); + static void Assert(const GlobalObject&, bool); + + // Deprecated static methods and attributes + static int8_t StaticDeprecatedAttribute(const GlobalObject&); + static void SetStaticDeprecatedAttribute(const GlobalObject&, int8_t); + static void StaticDeprecatedMethod(const GlobalObject&); + static void StaticDeprecatedMethodWithContext(const GlobalObject&, + const JS::Value&); + + // Overload resolution tests + bool Overload1(TestInterface&); + TestInterface* Overload1(const nsAString&, TestInterface&); + void Overload2(TestInterface&); + void Overload2(JSContext*, const Dict&); + void Overload2(bool); + void Overload2(const nsAString&); + void Overload3(TestInterface&); + void Overload3(const TestCallback&); + void Overload3(bool); + void Overload4(TestInterface&); + void Overload4(TestCallbackInterface&); + void Overload4(const nsAString&); + void Overload5(int32_t); + void Overload5(TestEnum); + void Overload6(int32_t); + void Overload6(bool); + void Overload7(int32_t); + void Overload7(bool); + void Overload7(const nsCString&); + void Overload8(int32_t); + void Overload8(TestInterface&); + void Overload9(const Nullable<int32_t>&); + void Overload9(const nsAString&); + void Overload10(const Nullable<int32_t>&); + void Overload10(JSContext*, JS::Handle<JSObject*>); + void Overload11(int32_t); + void Overload11(const nsAString&); + void Overload12(int32_t); + void Overload12(const Nullable<bool>&); + void Overload13(const Nullable<int32_t>&); + void Overload13(bool); + void Overload14(const Optional<int32_t>&); + void Overload14(TestInterface&); + void Overload15(int32_t); + void Overload15(const Optional<NonNull<TestInterface>>&); + void Overload16(int32_t); + void Overload16(const Optional<TestInterface*>&); + void Overload17(const Sequence<int32_t>&); + void Overload17(const Record<nsString, int32_t>&); + void Overload18(const Record<nsString, nsString>&); + void Overload18(const Sequence<nsString>&); + void Overload19(const Sequence<int32_t>&); + void Overload19(JSContext*, const Dict&); + void Overload20(JSContext*, const Dict&); + void Overload20(const Sequence<int32_t>&); + + // Variadic handling + void PassVariadicThirdArg(const nsAString&, int32_t, + const Sequence<OwningNonNull<TestInterface>>&); + + // Conditionally exposed methods/attributes + bool Prefable1(); + bool Prefable2(); + bool Prefable3(); + bool Prefable4(); + bool Prefable5(); + bool Prefable6(); + bool Prefable7(); + bool Prefable8(); + bool Prefable9(); + void Prefable10(); + void Prefable11(); + bool Prefable12(); + void Prefable13(); + bool Prefable14(); + bool Prefable15(); + bool Prefable16(); + void Prefable17(); + void Prefable18(); + void Prefable19(); + void Prefable20(); + void Prefable21(); + void Prefable22(); + void Prefable23(); + void Prefable24(); + + // Conditionally exposed methods/attributes involving [SecureContext] + bool ConditionalOnSecureContext1(); + bool ConditionalOnSecureContext2(); + bool ConditionalOnSecureContext3(); + bool ConditionalOnSecureContext4(); + void ConditionalOnSecureContext5(); + void ConditionalOnSecureContext6(); + void ConditionalOnSecureContext7(); + void ConditionalOnSecureContext8(); + + bool ConditionalOnSecureContext9(); + void ConditionalOnSecureContext10(); + + // Miscellania + int32_t AttrWithLenientThis(); + void SetAttrWithLenientThis(int32_t); + uint32_t UnforgeableAttr(); + uint32_t UnforgeableAttr2(); + uint32_t UnforgeableMethod(); + uint32_t UnforgeableMethod2(); + void Stringify(nsString&); + void PassRenamedInterface(nsRenamedInterface&); + TestInterface* PutForwardsAttr(); + TestInterface* PutForwardsAttr2(); + TestInterface* PutForwardsAttr3(); + void GetToJSONShouldSkipThis(JSContext*, JS::MutableHandle<JS::Value>); + void SetToJSONShouldSkipThis(JSContext*, JS::Rooted<JS::Value>&); + TestParentInterface* ToJSONShouldSkipThis2(); + void SetToJSONShouldSkipThis2(TestParentInterface&); + TestCallbackInterface* ToJSONShouldSkipThis3(); + void SetToJSONShouldSkipThis3(TestCallbackInterface&); + void ThrowingMethod(ErrorResult& aRv); + bool GetThrowingAttr(ErrorResult& aRv) const; + void SetThrowingAttr(bool arg, ErrorResult& aRv); + bool GetThrowingGetterAttr(ErrorResult& aRv) const; + void SetThrowingGetterAttr(bool arg); + bool ThrowingSetterAttr() const; + void SetThrowingSetterAttr(bool arg, ErrorResult& aRv); + void CanOOMMethod(OOMReporter& aRv); + bool GetCanOOMAttr(OOMReporter& aRv) const; + void SetCanOOMAttr(bool arg, OOMReporter& aRv); + bool GetCanOOMGetterAttr(OOMReporter& aRv) const; + void SetCanOOMGetterAttr(bool arg); + bool CanOOMSetterAttr() const; + void SetCanOOMSetterAttr(bool arg, OOMReporter& aRv); + void NeedsSubjectPrincipalMethod(nsIPrincipal&); + bool NeedsSubjectPrincipalAttr(nsIPrincipal&); + void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&); + void NeedsCallerTypeMethod(CallerType); + bool NeedsCallerTypeAttr(CallerType); + void SetNeedsCallerTypeAttr(bool, CallerType); + void NeedsNonSystemSubjectPrincipalMethod(nsIPrincipal*); + bool NeedsNonSystemSubjectPrincipalAttr(nsIPrincipal*); + void SetNeedsNonSystemSubjectPrincipalAttr(bool, nsIPrincipal*); + void CeReactionsMethod(); + void CeReactionsMethodOverload(); + void CeReactionsMethodOverload(const nsAString&); + bool CeReactionsAttr() const; + void SetCeReactionsAttr(bool); + int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&); + void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&, + TestInterface*, const Dict&, double, + const Optional<float>&); + + void SetDashed_attribute(int8_t); + int8_t Dashed_attribute(); + void Dashed_method(); + + bool NonEnumerableAttr() const; + void SetNonEnumerableAttr(bool); + void NonEnumerableMethod(); + + // Methods and properties imported via "includes" + bool MixedInProperty(); + void SetMixedInProperty(bool); + void MixedInMethod(); + + // Test EnforceRange/Clamp + void DontEnforceRangeOrClamp(int8_t); + void DoEnforceRange(int8_t); + void DoEnforceRangeNullable(const Nullable<int8_t>&); + void DoClamp(int8_t); + void DoClampNullable(const Nullable<int8_t>&); + void SetEnforcedByte(int8_t); + int8_t EnforcedByte(); + void SetEnforcedNullableByte(const Nullable<int8_t>&); + Nullable<int8_t> GetEnforcedNullableByte() const; + void SetClampedNullableByte(const Nullable<int8_t>&); + Nullable<int8_t> GetClampedNullableByte() const; + void SetClampedByte(int8_t); + int8_t ClampedByte(); + + // Test AllowShared + void SetAllowSharedArrayBufferViewTypedef(const ArrayBufferView&); + void GetAllowSharedArrayBufferViewTypedef(JSContext*, + JS::MutableHandle<JSObject*>); + void SetAllowSharedArrayBufferView(const ArrayBufferView&); + void GetAllowSharedArrayBufferView(JSContext*, JS::MutableHandle<JSObject*>); + void SetAllowSharedNullableArrayBufferView(const Nullable<ArrayBufferView>&); + void GetAllowSharedNullableArrayBufferView(JSContext*, + JS::MutableHandle<JSObject*>); + void SetAllowSharedArrayBuffer(const ArrayBuffer&); + void GetAllowSharedArrayBuffer(JSContext*, JS::MutableHandle<JSObject*>); + void SetAllowSharedNullableArrayBuffer(const Nullable<ArrayBuffer>&); + void GetAllowSharedNullableArrayBuffer(JSContext*, + JS::MutableHandle<JSObject*>); + + void PassAllowSharedArrayBufferViewTypedef(const ArrayBufferView&); + void PassAllowSharedArrayBufferView(const ArrayBufferView&); + void PassAllowSharedNullableArrayBufferView(const Nullable<ArrayBufferView>&); + void PassAllowSharedArrayBuffer(const ArrayBuffer&); + void PassAllowSharedNullableArrayBuffer(const Nullable<ArrayBuffer>&); + void PassUnionArrayBuffer(const StringOrArrayBuffer& foo); + void PassUnionAllowSharedArrayBuffer( + const StringOrMaybeSharedArrayBuffer& foo); + + private: + // We add signatures here that _could_ start matching if the codegen + // got data types wrong. That way if it ever does we'll have a call + // to these private deleted methods and compilation will fail. + void SetReadonlyByte(int8_t) = delete; + template <typename T> + void SetWritableByte(T) = delete; + template <typename T> + void PassByte(T) = delete; + void PassNullableByte(Nullable<int8_t>&) = delete; + template <typename T> + void PassOptionalByte(const Optional<T>&) = delete; + template <typename T> + void PassOptionalByteWithDefault(T) = delete; + void PassVariadicByte(Sequence<int8_t>&) = delete; + + void SetReadonlyShort(int16_t) = delete; + template <typename T> + void SetWritableShort(T) = delete; + template <typename T> + void PassShort(T) = delete; + template <typename T> + void PassOptionalShort(const Optional<T>&) = delete; + template <typename T> + void PassOptionalShortWithDefault(T) = delete; + + void SetReadonlyLong(int32_t) = delete; + template <typename T> + void SetWritableLong(T) = delete; + template <typename T> + void PassLong(T) = delete; + template <typename T> + void PassOptionalLong(const Optional<T>&) = delete; + template <typename T> + void PassOptionalLongWithDefault(T) = delete; + + void SetReadonlyLongLong(int64_t) = delete; + template <typename T> + void SetWritableLongLong(T) = delete; + template <typename T> + void PassLongLong(T) = delete; + template <typename T> + void PassOptionalLongLong(const Optional<T>&) = delete; + template <typename T> + void PassOptionalLongLongWithDefault(T) = delete; + + void SetReadonlyOctet(uint8_t) = delete; + template <typename T> + void SetWritableOctet(T) = delete; + template <typename T> + void PassOctet(T) = delete; + template <typename T> + void PassOptionalOctet(const Optional<T>&) = delete; + template <typename T> + void PassOptionalOctetWithDefault(T) = delete; + + void SetReadonlyUnsignedShort(uint16_t) = delete; + template <typename T> + void SetWritableUnsignedShort(T) = delete; + template <typename T> + void PassUnsignedShort(T) = delete; + template <typename T> + void PassOptionalUnsignedShort(const Optional<T>&) = delete; + template <typename T> + void PassOptionalUnsignedShortWithDefault(T) = delete; + + void SetReadonlyUnsignedLong(uint32_t) = delete; + template <typename T> + void SetWritableUnsignedLong(T) = delete; + template <typename T> + void PassUnsignedLong(T) = delete; + template <typename T> + void PassOptionalUnsignedLong(const Optional<T>&) = delete; + template <typename T> + void PassOptionalUnsignedLongWithDefault(T) = delete; + + void SetReadonlyUnsignedLongLong(uint64_t) = delete; + template <typename T> + void SetWritableUnsignedLongLong(T) = delete; + template <typename T> + void PassUnsignedLongLong(T) = delete; + template <typename T> + void PassOptionalUnsignedLongLong(const Optional<T>&) = delete; + template <typename T> + void PassOptionalUnsignedLongLongWithDefault(T) = delete; + + // Enforce that only const things are passed for sequences + void PassSequence(Sequence<int32_t>&) = delete; + void PassNullableSequence(Nullable<Sequence<int32_t>>&) = delete; + void PassOptionalNullableSequenceWithDefaultValue( + Nullable<Sequence<int32_t>>&) = delete; + void PassSequenceOfAny(JSContext*, Sequence<JS::Value>&) = delete; + void PassNullableSequenceOfAny(JSContext*, + Nullable<Sequence<JS::Value>>&) = delete; + void PassOptionalSequenceOfAny(JSContext*, + Optional<Sequence<JS::Value>>&) = delete; + void PassOptionalNullableSequenceOfAny( + JSContext*, Optional<Nullable<Sequence<JS::Value>>>&) = delete; + void PassOptionalSequenceOfAnyWithDefaultValue( + JSContext*, Nullable<Sequence<JS::Value>>&) = delete; + void PassSequenceOfSequenceOfAny(JSContext*, + Sequence<Sequence<JS::Value>>&) = delete; + void PassSequenceOfNullableSequenceOfAny( + JSContext*, Sequence<Nullable<Sequence<JS::Value>>>&) = delete; + void PassNullableSequenceOfNullableSequenceOfAny( + JSContext*, Nullable<Sequence<Nullable<Sequence<JS::Value>>>>&) = delete; + void PassOptionalNullableSequenceOfNullableSequenceOfAny( + JSContext*, + Optional<Nullable<Sequence<Nullable<Sequence<JS::Value>>>>>&) = delete; + void PassSequenceOfObject(JSContext*, Sequence<JSObject*>&) = delete; + void PassSequenceOfNullableObject(JSContext*, Sequence<JSObject*>&) = delete; + void PassOptionalNullableSequenceOfNullableSequenceOfObject( + JSContext*, + Optional<Nullable<Sequence<Nullable<Sequence<JSObject*>>>>>&) = delete; + void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject( + JSContext*, + Optional<Nullable<Sequence<Nullable<Sequence<JSObject*>>>>>&) = delete; + + // Enforce that only const things are passed for optional + void PassOptionalByte(Optional<int8_t>&) = delete; + void PassOptionalNullableByte(Optional<Nullable<int8_t>>&) = delete; + void PassOptionalShort(Optional<int16_t>&) = delete; + void PassOptionalLong(Optional<int32_t>&) = delete; + void PassOptionalLongLong(Optional<int64_t>&) = delete; + void PassOptionalOctet(Optional<uint8_t>&) = delete; + void PassOptionalUnsignedShort(Optional<uint16_t>&) = delete; + void PassOptionalUnsignedLong(Optional<uint32_t>&) = delete; + void PassOptionalUnsignedLongLong(Optional<uint64_t>&) = delete; + void PassOptionalSelf(Optional<TestInterface*>&) = delete; + void PassOptionalNonNullSelf(Optional<NonNull<TestInterface>>&) = delete; + void PassOptionalExternal(Optional<TestExternalInterface*>&) = delete; + void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&) = delete; + void PassOptionalSequence(Optional<Sequence<int32_t>>&) = delete; + void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t>>>&) = + delete; + void PassOptionalObjectSequence( + Optional<Sequence<OwningNonNull<TestInterface>>>&) = delete; + void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) = delete; + void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) = delete; + void PassOptionalEnum(Optional<TestEnum>&) = delete; + void PassOptionalCallback(JSContext*, + Optional<OwningNonNull<TestCallback>>&) = delete; + void PassOptionalNullableCallback(JSContext*, + Optional<RefPtr<TestCallback>>&) = delete; + void PassOptionalAny(Optional<JS::Handle<JS::Value>>&) = delete; + + // And test that string stuff is always const + void PassString(nsAString&) = delete; + void PassNullableString(nsAString&) = delete; + void PassOptionalString(Optional<nsAString>&) = delete; + void PassOptionalStringWithDefaultValue(nsAString&) = delete; + void PassOptionalNullableString(Optional<nsAString>&) = delete; + void PassOptionalNullableStringWithDefaultValue(nsAString&) = delete; + void PassVariadicString(Sequence<nsString>&) = delete; + + // cstrings should be const as well + void PassByteString(nsCString&) = delete; + void PassNullableByteString(nsCString&) = delete; + void PassOptionalByteString(Optional<nsCString>&) = delete; + void PassOptionalByteStringWithDefaultValue(nsCString&) = delete; + void PassOptionalNullableByteString(Optional<nsCString>&) = delete; + void PassOptionalNullableByteStringWithDefaultValue(nsCString&) = delete; + void PassVariadicByteString(Sequence<nsCString>&) = delete; + + // cstrings should be const as well + void PassUTF8String(nsACString&) = delete; + void PassNullableUTF8String(nsACString&) = delete; + void PassOptionalUTF8String(Optional<nsACString>&) = delete; + void PassOptionalUTF8StringWithDefaultValue(nsACString&) = delete; + void PassOptionalNullableUTF8String(Optional<nsACString>&) = delete; + void PassOptionalNullableUTF8StringWithDefaultValue(nsACString&) = delete; + void PassVariadicUTF8String(Sequence<nsCString>&) = delete; + + // Make sure dictionary arguments are always const + void PassDictionary(JSContext*, Dict&) = delete; + void PassOtherDictionary(GrandparentDict&) = delete; + void PassSequenceOfDictionaries(JSContext*, Sequence<Dict>&) = delete; + void PassDictionaryOrLong(JSContext*, Dict&) = delete; + void PassDictContainingDict(JSContext*, DictContainingDict&) = delete; + void PassDictContainingSequence(DictContainingSequence&) = delete; + + // Make sure various nullable things are always const + void PassNullableEnum(Nullable<TestEnum>&) = delete; + + // Make sure unions are always const + void PassUnion(JSContext*, ObjectOrLong& arg) = delete; + void PassUnionWithNullable(JSContext*, ObjectOrNullOrLong& arg) = delete; + void PassNullableUnion(JSContext*, Nullable<ObjectOrLong>&) = delete; + void PassOptionalUnion(JSContext*, Optional<ObjectOrLong>&) = delete; + void PassOptionalNullableUnion(JSContext*, + Optional<Nullable<ObjectOrLong>>&) = delete; + void PassOptionalNullableUnionWithDefaultValue( + JSContext*, Nullable<ObjectOrLong>&) = delete; + + // Make sure variadics are const as needed + void PassVariadicAny(JSContext*, Sequence<JS::Value>&) = delete; + void PassVariadicObject(JSContext*, Sequence<JSObject*>&) = delete; + void PassVariadicNullableObject(JSContext*, Sequence<JSObject*>&) = delete; + + // Ensure NonNull does not leak in + void PassSelf(NonNull<TestInterface>&) = delete; + void PassSelf(OwningNonNull<TestInterface>&) = delete; + void PassSelf(const NonNull<TestInterface>&) = delete; + void PassSelf(const OwningNonNull<TestInterface>&) = delete; + void PassCallbackInterface(OwningNonNull<TestCallbackInterface>&) = delete; + void PassCallbackInterface(const OwningNonNull<TestCallbackInterface>&) = + delete; + void PassCallbackInterface(NonNull<TestCallbackInterface>&) = delete; + void PassCallbackInterface(const NonNull<TestCallbackInterface>&) = delete; + void PassCallback(OwningNonNull<TestCallback>&) = delete; + void PassCallback(const OwningNonNull<TestCallback>&) = delete; + void PassCallback(NonNull<TestCallback>&) = delete; + void PassCallback(const NonNull<TestCallback>&) = delete; + void PassString(const NonNull<nsAString>&) = delete; + void PassString(NonNull<nsAString>&) = delete; + void PassString(const OwningNonNull<nsAString>&) = delete; + void PassString(OwningNonNull<nsAString>&) = delete; +}; + +class TestIndexedGetterInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + uint32_t IndexedGetter(uint32_t, bool&); + uint32_t IndexedGetter(uint32_t&) = delete; + uint32_t Item(uint32_t&); + uint32_t Item(uint32_t, bool&) = delete; + uint32_t Length(); + void LegacyCall(JS::Handle<JS::Value>); + int32_t CachedAttr(); + int32_t StoreInSlotAttr(); +}; + +class TestNamedGetterInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void NamedGetter(const nsAString&, bool&, nsAString&); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestIndexedGetterAndSetterAndNamedGetterInterface + : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void NamedGetter(const nsAString&, bool&, nsAString&); + void GetSupportedNames(nsTArray<nsString>&); + int32_t IndexedGetter(uint32_t, bool&); + void IndexedSetter(uint32_t, int32_t); + uint32_t Length(); +}; + +class TestIndexedAndNamedGetterInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + uint32_t IndexedGetter(uint32_t, bool&); + void NamedGetter(const nsAString&, bool&, nsAString&); + void NamedItem(const nsAString&, nsAString&); + uint32_t Length(); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestIndexedSetterInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void IndexedSetter(uint32_t, const nsAString&); + void IndexedGetter(uint32_t, bool&, nsString&); + uint32_t Length(); + void SetItem(uint32_t, const nsAString&); +}; + +class TestNamedSetterInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void NamedSetter(const nsAString&, TestIndexedSetterInterface&); + TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestIndexedAndNamedSetterInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void IndexedSetter(uint32_t, TestIndexedSetterInterface&); + TestIndexedSetterInterface* IndexedGetter(uint32_t, bool&); + uint32_t Length(); + void NamedSetter(const nsAString&, TestIndexedSetterInterface&); + TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&); + void SetNamedItem(const nsAString&, TestIndexedSetterInterface&); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestIndexedAndNamedGetterAndSetterInterface + : public TestIndexedSetterInterface { + public: + uint32_t IndexedGetter(uint32_t, bool&); + uint32_t Item(uint32_t); + void NamedGetter(const nsAString&, bool&, nsAString&); + void NamedItem(const nsAString&, nsAString&); + void IndexedSetter(uint32_t, int32_t&); + void IndexedSetter(uint32_t, const nsAString&) = delete; + void NamedSetter(const nsAString&, const nsAString&); + void Stringify(nsAString&); + uint32_t Length(); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestCppKeywordNamedMethodsInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + bool Continue(); + bool Delete(); + int32_t Volatile(); +}; + +class TestNamedDeleterInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void NamedDeleter(const nsAString&, bool&); + long NamedGetter(const nsAString&, bool&); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestNamedDeleterWithRetvalInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); + + bool NamedDeleter(const nsAString&, bool&); + bool NamedDeleter(const nsAString&) = delete; + long NamedGetter(const nsAString&, bool&); + bool DelNamedItem(const nsAString&); + bool DelNamedItem(const nsAString&, bool&) = delete; + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestParentInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + virtual nsISupports* GetParentObject(); +}; + +class TestChildInterface : public TestParentInterface {}; + +class TestDeprecatedInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + static already_AddRefed<TestDeprecatedInterface> Constructor( + const GlobalObject&); + + static void AlsoDeprecated(const GlobalObject&); + + virtual nsISupports* GetParentObject(); +}; + +class TestInterfaceWithPromiseConstructorArg : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + static already_AddRefed<TestInterfaceWithPromiseConstructorArg> Constructor( + const GlobalObject&, Promise&); + + virtual nsISupports* GetParentObject(); +}; + +class TestSecureContextInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + static already_AddRefed<TestSecureContextInterface> Constructor( + const GlobalObject&, ErrorResult&); + + static void AlsoSecureContext(const GlobalObject&); + + virtual nsISupports* GetParentObject(); +}; + +class TestNamespace { + public: + static bool Foo(const GlobalObject&); + static int32_t Bar(const GlobalObject&); + static void Baz(const GlobalObject&); +}; + +class TestRenamedNamespace {}; + +class TestProtoObjectHackedNamespace {}; + +class TestWorkerExposedInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject to make binding codegen happy + nsISupports* GetParentObject(); + + void NeedsSubjectPrincipalMethod(Maybe<nsIPrincipal*>); + bool NeedsSubjectPrincipalAttr(Maybe<nsIPrincipal*>); + void SetNeedsSubjectPrincipalAttr(bool, Maybe<nsIPrincipal*>); + void NeedsCallerTypeMethod(CallerType); + bool NeedsCallerTypeAttr(CallerType); + void SetNeedsCallerTypeAttr(bool, CallerType); + void NeedsNonSystemSubjectPrincipalMethod(Maybe<nsIPrincipal*>); + bool NeedsNonSystemSubjectPrincipalAttr(Maybe<nsIPrincipal*>); + void SetNeedsNonSystemSubjectPrincipalAttr(bool, Maybe<nsIPrincipal*>); +}; + +class TestHTMLConstructorInterface : public nsGenericHTMLElement { + public: + virtual nsISupports* GetParentObject(); +}; + +class TestThrowingConstructorInterface : public nsISupports, + public nsWrapperCache { + public: + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, ErrorResult&); + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, const nsAString&, ErrorResult&); + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, uint32_t, const Nullable<bool>&, ErrorResult&); + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, TestInterface*, ErrorResult&); + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, uint32_t, TestInterface&, ErrorResult&); + + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, const ArrayBuffer&, ErrorResult&); + static already_AddRefed<TestThrowingConstructorInterface> Constructor( + const GlobalObject&, const Uint8Array&, ErrorResult&); + /* static + already_AddRefed<TestThrowingConstructorInterface> + Constructor(const GlobalObject&, uint32_t, uint32_t, + const TestInterfaceOrOnlyForUseInConstructor&, ErrorResult&); + */ + + virtual nsISupports* GetParentObject(); +}; + +class TestCEReactionsInterface : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject and GetDocGroup to make binding codegen happy + virtual nsISupports* GetParentObject(); + DocGroup* GetDocGroup() const; + + int32_t Item(uint32_t); + uint32_t Length() const; + int32_t IndexedGetter(uint32_t, bool&); + void IndexedSetter(uint32_t, int32_t); + void NamedDeleter(const nsAString&, bool&); + void NamedGetter(const nsAString&, bool&, nsString&); + void NamedSetter(const nsAString&, const nsAString&); + void GetSupportedNames(nsTArray<nsString>&); +}; + +class TestAttributesOnTypes : public nsISupports, public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + + // We need a GetParentObject and GetDocGroup to make binding codegen happy + virtual nsISupports* GetParentObject(); + + void Foo(uint8_t arg); + void Bar(uint8_t arg); + void Baz(const nsAString& arg); + uint8_t SomeAttr(); + void SetSomeAttr(uint8_t); + void ArgWithAttr(uint8_t arg1, const Optional<uint8_t>& arg2); +}; + +class TestPrefConstructorForInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since only the constructor is under a pref, + // the generated constructor should check for the pref. + static already_AddRefed<TestPrefConstructorForInterface> Constructor( + const GlobalObject&); +}; + +class TestConstructorForPrefInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the interface itself is under a Pref, there should be no + // check for the pref in the generated constructor. + static already_AddRefed<TestConstructorForPrefInterface> Constructor( + const GlobalObject&); +}; + +class TestPrefConstructorForDifferentPrefInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the constructor's pref is different than the interface pref + // there should still be a check for the pref in the generated constructor. + static already_AddRefed<TestPrefConstructorForDifferentPrefInterface> + Constructor(const GlobalObject&); +}; + +class TestConstructorForSCInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the interface itself is SecureContext, there should be no + // check for SecureContext in the constructor. + static already_AddRefed<TestConstructorForSCInterface> Constructor( + const GlobalObject&); +}; + +class TestSCConstructorForInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the interface context is unspecified but the constructor is + // SecureContext, the generated constructor should check for SecureContext. + static already_AddRefed<TestSCConstructorForInterface> Constructor( + const GlobalObject&); +}; + +class TestConstructorForFuncInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the interface has a Func attribute, but the constructor does not, + // the generated constructor should not check for the Func. + static already_AddRefed<TestConstructorForFuncInterface> Constructor( + const GlobalObject&); +}; + +class TestFuncConstructorForInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the constructor has a Func attribute, but the interface does not, + // the generated constructor should check for the Func. + static already_AddRefed<TestFuncConstructorForInterface> Constructor( + const GlobalObject&); +}; + +class TestFuncConstructorForDifferentFuncInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // Since the constructor has a different Func attribute from the interface, + // the generated constructor should still check for its conditional func. + static already_AddRefed<TestFuncConstructorForDifferentFuncInterface> + Constructor(const GlobalObject&); +}; + +class TestPrefChromeOnlySCFuncConstructorForInterface : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_ISUPPORTS + virtual nsISupports* GetParentObject(); + + // There should be checks for all Pref/ChromeOnly/SecureContext/Func + // in the generated constructor. + static already_AddRefed<TestPrefChromeOnlySCFuncConstructorForInterface> + Constructor(const GlobalObject&); +}; + +} // namespace dom +} // namespace mozilla + +#endif /* TestBindingHeader_h */ diff --git a/dom/bindings/test/TestCImplementedInterface.h b/dom/bindings/test/TestCImplementedInterface.h new file mode 100644 index 0000000000..6512911bd3 --- /dev/null +++ b/dom/bindings/test/TestCImplementedInterface.h @@ -0,0 +1,37 @@ +/* -*- 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 TestCImplementedInterface_h +#define TestCImplementedInterface_h + +#include "../TestJSImplGenBinding.h" + +namespace mozilla { +namespace dom { + +class TestCImplementedInterface : public TestJSImplInterface { + public: + TestCImplementedInterface(JS::Handle<JSObject*> aJSImpl, + JS::Handle<JSObject*> aJSImplGlobal, + nsIGlobalObject* aParent) + : TestJSImplInterface(aJSImpl, aJSImplGlobal, aParent) {} +}; + +class TestCImplementedInterface2 : public nsISupports, public nsWrapperCache { + public: + explicit TestCImplementedInterface2(nsIGlobalObject* aParent) {} + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestCImplementedInterface2) + + // We need a GetParentObject to make binding codegen happy + nsISupports* GetParentObject(); +}; + +} // namespace dom +} // namespace mozilla + +#endif // TestCImplementedInterface_h diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl new file mode 100644 index 0000000000..8f7c1727bc --- /dev/null +++ b/dom/bindings/test/TestCodeGen.webidl @@ -0,0 +1,1516 @@ +/* -*- 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/. + */ + +typedef long myLong; +typedef TestInterface AnotherNameForTestInterface; +typedef TestInterface? NullableTestInterface; +typedef CustomEventInit TestDictionaryTypedef; +typedef ArrayBufferView ArrayBufferViewTypedef; +typedef [AllowShared] ArrayBufferView AllowSharedArrayBufferViewTypedef; + +interface TestExternalInterface; + +// We need a pref name that's in StaticPrefList.h here. +[Pref="dom.webidl.test1", + Exposed=Window] +interface TestRenamedInterface { +}; + +[Exposed=Window] +callback interface TestCallbackInterface { + readonly attribute long foo; + attribute DOMString bar; + undefined doSomething(); + long doSomethingElse(DOMString arg, TestInterface otherArg); + undefined doSequenceLongArg(sequence<long> arg); + undefined doSequenceStringArg(sequence<DOMString> arg); + undefined doRecordLongArg(record<DOMString, long> arg); + sequence<long> getSequenceOfLong(); + sequence<TestInterface> getSequenceOfInterfaces(); + sequence<TestInterface>? getNullableSequenceOfInterfaces(); + sequence<TestInterface?> getSequenceOfNullableInterfaces(); + sequence<TestInterface?>? getNullableSequenceOfNullableInterfaces(); + sequence<TestCallbackInterface> getSequenceOfCallbackInterfaces(); + sequence<TestCallbackInterface>? getNullableSequenceOfCallbackInterfaces(); + sequence<TestCallbackInterface?> getSequenceOfNullableCallbackInterfaces(); + sequence<TestCallbackInterface?>? getNullableSequenceOfNullableCallbackInterfaces(); + record<DOMString, long> getRecordOfLong(); + Dict? getDictionary(); + undefined passArrayBuffer(ArrayBuffer arg); + undefined passNullableArrayBuffer(ArrayBuffer? arg); + undefined passOptionalArrayBuffer(optional ArrayBuffer arg); + undefined passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); + undefined passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); + undefined passArrayBufferView(ArrayBufferView arg); + undefined passInt8Array(Int8Array arg); + undefined passInt16Array(Int16Array arg); + undefined passInt32Array(Int32Array arg); + undefined passUint8Array(Uint8Array arg); + undefined passUint16Array(Uint16Array arg); + undefined passUint32Array(Uint32Array arg); + undefined passUint8ClampedArray(Uint8ClampedArray arg); + undefined passFloat32Array(Float32Array arg); + undefined passFloat64Array(Float64Array arg); + undefined passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg); + undefined passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg); + undefined passVariadicTypedArray(Float32Array... arg); + undefined passVariadicNullableTypedArray(Float32Array?... arg); + Uint8Array receiveUint8Array(); + attribute Uint8Array uint8ArrayAttr; + Promise<undefined> receivePromise(); +}; + +[Exposed=Window] +callback interface TestSingleOperationCallbackInterface { + TestInterface doSomething(short arg, sequence<double> anotherArg); +}; + +enum TestEnum { + "1", + "a", + "b", + "1-2", + "2d-array" +}; + +callback TestCallback = undefined(); +[TreatNonCallableAsNull] callback TestTreatAsNullCallback = undefined(); + +// Callback return value tests +callback TestIntegerReturn = long(); +callback TestNullableIntegerReturn = long?(); +callback TestBooleanReturn = boolean(); +callback TestFloatReturn = float(); +callback TestStringReturn = DOMString(long arg); +callback TestEnumReturn = TestEnum(); +callback TestInterfaceReturn = TestInterface(); +callback TestNullableInterfaceReturn = TestInterface?(); +callback TestExternalInterfaceReturn = TestExternalInterface(); +callback TestNullableExternalInterfaceReturn = TestExternalInterface?(); +callback TestCallbackInterfaceReturn = TestCallbackInterface(); +callback TestNullableCallbackInterfaceReturn = TestCallbackInterface?(); +callback TestCallbackReturn = TestCallback(); +callback TestNullableCallbackReturn = TestCallback?(); +callback TestObjectReturn = object(); +callback TestNullableObjectReturn = object?(); +callback TestTypedArrayReturn = ArrayBuffer(); +callback TestNullableTypedArrayReturn = ArrayBuffer?(); +callback TestSequenceReturn = sequence<boolean>(); +callback TestNullableSequenceReturn = sequence<boolean>?(); +// Callback argument tests +callback TestIntegerArguments = sequence<long>(long arg1, long? arg2, + sequence<long> arg3, + sequence<long?>? arg4); +callback TestInterfaceArguments = undefined(TestInterface arg1, + TestInterface? arg2, + TestExternalInterface arg3, + TestExternalInterface? arg4, + TestCallbackInterface arg5, + TestCallbackInterface? arg6, + sequence<TestInterface> arg7, + sequence<TestInterface?>? arg8, + sequence<TestExternalInterface> arg9, + sequence<TestExternalInterface?>? arg10, + sequence<TestCallbackInterface> arg11, + sequence<TestCallbackInterface?>? arg12); +callback TestStringEnumArguments = undefined(DOMString myString, DOMString? nullString, + TestEnum myEnum); +callback TestObjectArguments = undefined(object anObj, object? anotherObj, + ArrayBuffer buf, ArrayBuffer? buf2); +callback TestOptionalArguments = undefined(optional DOMString aString, + optional object something, + optional sequence<TestInterface> aSeq, + optional TestInterface? anInterface, + optional TestInterface anotherInterface, + optional long aLong); +// Callback constructor return value tests +callback constructor TestUndefinedConstruction = undefined(TestDictionaryTypedef arg); +callback constructor TestIntegerConstruction = unsigned long(); +callback constructor TestBooleanConstruction = boolean(any arg1, + optional any arg2); +callback constructor TestFloatConstruction = unrestricted float(optional object arg1, + optional TestDictionaryTypedef arg2); +callback constructor TestStringConstruction = DOMString(long? arg); +callback constructor TestEnumConstruction = TestEnum(any... arg); +callback constructor TestInterfaceConstruction = TestInterface(); +callback constructor TestExternalInterfaceConstruction = TestExternalInterface(); +callback constructor TestCallbackInterfaceConstruction = TestCallbackInterface(); +callback constructor TestCallbackConstruction = TestCallback(); +callback constructor TestObjectConstruction = object(); +callback constructor TestTypedArrayConstruction = ArrayBuffer(); +callback constructor TestSequenceConstruction = sequence<boolean>(); +// If you add a new test callback, add it to the forceCallbackGeneration +// method on TestInterface so it actually gets tested. + +TestInterface includes InterfaceMixin; + +// This interface is only for use in the constructor below +[Exposed=Window] +interface OnlyForUseInConstructor { +}; + +[LegacyFactoryFunction=Test, + LegacyFactoryFunction=Test(DOMString str), + LegacyFactoryFunction=Test2(DictForConstructor dict, any any1, object obj1, + object? obj2, sequence<Dict> seq, optional any any2, + optional object obj3, optional object? obj4), + LegacyFactoryFunction=Test3((long or record<DOMString, any>) arg1), + LegacyFactoryFunction=Test4(record<DOMString, record<DOMString, any>> arg1), + LegacyFactoryFunction=Test5(record<DOMString, sequence<record<DOMString, record<DOMString, sequence<sequence<any>>>>>> arg1), + LegacyFactoryFunction=Test6(sequence<record<ByteString, sequence<sequence<record<ByteString, record<USVString, any>>>>>> arg1), + Exposed=Window] +interface TestInterface { + constructor(); + constructor(DOMString str); + constructor(unsigned long num, boolean? boolArg); + constructor(TestInterface? iface); + constructor(unsigned long arg1, TestInterface iface); + constructor(ArrayBuffer arrayBuf); + constructor(Uint8Array typedArr); + // constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3); + + // Integer types + // XXXbz add tests for throwing versions of all the integer stuff + readonly attribute byte readonlyByte; + attribute byte writableByte; + undefined passByte(byte arg); + byte receiveByte(); + undefined passOptionalByte(optional byte arg); + undefined passOptionalByteBeforeRequired(optional byte arg1, byte arg2); + undefined passOptionalByteWithDefault(optional byte arg = 0); + undefined passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); + undefined passNullableByte(byte? arg); + undefined passOptionalNullableByte(optional byte? arg); + undefined passVariadicByte(byte... arg); + [StoreInSlot, Pure] + readonly attribute byte cachedByte; + [StoreInSlot, Constant] + readonly attribute byte cachedConstantByte; + [StoreInSlot, Pure] + attribute byte cachedWritableByte; + [Affects=Nothing] + attribute byte sideEffectFreeByte; + [Affects=Nothing, DependsOn=DOMState] + attribute byte domDependentByte; + [Affects=Nothing, DependsOn=Nothing] + readonly attribute byte constantByte; + [DependsOn=DeviceState, Affects=Nothing] + readonly attribute byte deviceStateDependentByte; + [Affects=Nothing] + byte returnByteSideEffectFree(); + [Affects=Nothing, DependsOn=DOMState] + byte returnDOMDependentByte(); + [Affects=Nothing, DependsOn=Nothing] + byte returnConstantByte(); + [DependsOn=DeviceState, Affects=Nothing] + byte returnDeviceStateDependentByte(); + + readonly attribute short readonlyShort; + attribute short writableShort; + undefined passShort(short arg); + short receiveShort(); + undefined passOptionalShort(optional short arg); + undefined passOptionalShortWithDefault(optional short arg = 5); + + readonly attribute long readonlyLong; + attribute long writableLong; + undefined passLong(long arg); + long receiveLong(); + undefined passOptionalLong(optional long arg); + undefined passOptionalLongWithDefault(optional long arg = 7); + + readonly attribute long long readonlyLongLong; + attribute long long writableLongLong; + undefined passLongLong(long long arg); + long long receiveLongLong(); + undefined passOptionalLongLong(optional long long arg); + undefined passOptionalLongLongWithDefault(optional long long arg = -12); + + readonly attribute octet readonlyOctet; + attribute octet writableOctet; + undefined passOctet(octet arg); + octet receiveOctet(); + undefined passOptionalOctet(optional octet arg); + undefined passOptionalOctetWithDefault(optional octet arg = 19); + + readonly attribute unsigned short readonlyUnsignedShort; + attribute unsigned short writableUnsignedShort; + undefined passUnsignedShort(unsigned short arg); + unsigned short receiveUnsignedShort(); + undefined passOptionalUnsignedShort(optional unsigned short arg); + undefined passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); + + readonly attribute unsigned long readonlyUnsignedLong; + attribute unsigned long writableUnsignedLong; + undefined passUnsignedLong(unsigned long arg); + unsigned long receiveUnsignedLong(); + undefined passOptionalUnsignedLong(optional unsigned long arg); + undefined passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); + + readonly attribute unsigned long long readonlyUnsignedLongLong; + attribute unsigned long long writableUnsignedLongLong; + undefined passUnsignedLongLong(unsigned long long arg); + unsigned long long receiveUnsignedLongLong(); + undefined passOptionalUnsignedLongLong(optional unsigned long long arg); + undefined passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); + + attribute float writableFloat; + attribute unrestricted float writableUnrestrictedFloat; + attribute float? writableNullableFloat; + attribute unrestricted float? writableNullableUnrestrictedFloat; + attribute double writableDouble; + attribute unrestricted double writableUnrestrictedDouble; + attribute double? writableNullableDouble; + attribute unrestricted double? writableNullableUnrestrictedDouble; + undefined passFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, sequence<unrestricted float> arg10, + sequence<float?> arg11, sequence<unrestricted float?> arg12, + sequence<double> arg13, sequence<unrestricted double> arg14, + sequence<double?> arg15, sequence<unrestricted double?> arg16); + [LenientFloat] + undefined passLenientFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, + sequence<unrestricted float> arg10, + sequence<float?> arg11, + sequence<unrestricted float?> arg12, + sequence<double> arg13, + sequence<unrestricted double> arg14, + sequence<double?> arg15, + sequence<unrestricted double?> arg16); + [LenientFloat] + attribute float lenientFloatAttr; + [LenientFloat] + attribute double lenientDoubleAttr; + + undefined passUnrestricted(optional unrestricted float arg1 = 0, + optional unrestricted float arg2 = Infinity, + optional unrestricted float arg3 = -Infinity, + optional unrestricted float arg4 = NaN, + optional unrestricted double arg5 = 0, + optional unrestricted double arg6 = Infinity, + optional unrestricted double arg7 = -Infinity, + optional unrestricted double arg8 = NaN); + + // Castable interface types + // XXXbz add tests for throwing versions of all the castable interface stuff + TestInterface receiveSelf(); + TestInterface? receiveNullableSelf(); + TestInterface receiveWeakSelf(); + TestInterface? receiveWeakNullableSelf(); + undefined passSelf(TestInterface arg); + undefined passNullableSelf(TestInterface? arg); + attribute TestInterface nonNullSelf; + attribute TestInterface? nullableSelf; + [Cached, Pure] + readonly attribute TestInterface cachedSelf; + // Optional arguments + undefined passOptionalSelf(optional TestInterface? arg); + undefined passOptionalNonNullSelf(optional TestInterface arg); + undefined passOptionalSelfWithDefault(optional TestInterface? arg = null); + + // Non-wrapper-cache interface types + [NewObject] + TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); + [NewObject] + TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); + [NewObject] + sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence(); + + // External interface types + TestExternalInterface receiveExternal(); + TestExternalInterface? receiveNullableExternal(); + TestExternalInterface receiveWeakExternal(); + TestExternalInterface? receiveWeakNullableExternal(); + undefined passExternal(TestExternalInterface arg); + undefined passNullableExternal(TestExternalInterface? arg); + attribute TestExternalInterface nonNullExternal; + attribute TestExternalInterface? nullableExternal; + // Optional arguments + undefined passOptionalExternal(optional TestExternalInterface? arg); + undefined passOptionalNonNullExternal(optional TestExternalInterface arg); + undefined passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); + + // Callback interface types + TestCallbackInterface receiveCallbackInterface(); + TestCallbackInterface? receiveNullableCallbackInterface(); + TestCallbackInterface receiveWeakCallbackInterface(); + TestCallbackInterface? receiveWeakNullableCallbackInterface(); + undefined passCallbackInterface(TestCallbackInterface arg); + undefined passNullableCallbackInterface(TestCallbackInterface? arg); + attribute TestCallbackInterface nonNullCallbackInterface; + attribute TestCallbackInterface? nullableCallbackInterface; + // Optional arguments + undefined passOptionalCallbackInterface(optional TestCallbackInterface? arg); + undefined passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); + undefined passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); + + // Sequence types + [Cached, Pure] + readonly attribute sequence<long> readonlySequence; + [Cached, Pure] + readonly attribute sequence<Dict> readonlySequenceOfDictionaries; + [Cached, Pure] + readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries; + [Cached, Pure, Frozen] + readonly attribute sequence<Dict> readonlyFrozenSequence; + [Cached, Pure, Frozen] + readonly attribute sequence<Dict>? readonlyFrozenNullableSequence; + sequence<long> receiveSequence(); + sequence<long>? receiveNullableSequence(); + sequence<long?> receiveSequenceOfNullableInts(); + sequence<long?>? receiveNullableSequenceOfNullableInts(); + undefined passSequence(sequence<long> arg); + undefined passNullableSequence(sequence<long>? arg); + undefined passSequenceOfNullableInts(sequence<long?> arg); + undefined passOptionalSequenceOfNullableInts(optional sequence<long?> arg); + undefined passOptionalNullableSequenceOfNullableInts(optional sequence<long?>? arg); + sequence<TestInterface> receiveCastableObjectSequence(); + sequence<TestCallbackInterface> receiveCallbackObjectSequence(); + sequence<TestInterface?> receiveNullableCastableObjectSequence(); + sequence<TestCallbackInterface?> receiveNullableCallbackObjectSequence(); + sequence<TestInterface>? receiveCastableObjectNullableSequence(); + sequence<TestInterface?>? receiveNullableCastableObjectNullableSequence(); + sequence<TestInterface> receiveWeakCastableObjectSequence(); + sequence<TestInterface?> receiveWeakNullableCastableObjectSequence(); + sequence<TestInterface>? receiveWeakCastableObjectNullableSequence(); + sequence<TestInterface?>? receiveWeakNullableCastableObjectNullableSequence(); + undefined passCastableObjectSequence(sequence<TestInterface> arg); + undefined passNullableCastableObjectSequence(sequence<TestInterface?> arg); + undefined passCastableObjectNullableSequence(sequence<TestInterface>? arg); + undefined passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg); + undefined passOptionalSequence(optional sequence<long> arg); + undefined passOptionalSequenceWithDefaultValue(optional sequence<long> arg = []); + undefined passOptionalNullableSequence(optional sequence<long>? arg); + undefined passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null); + undefined passOptionalNullableSequenceWithDefaultValue2(optional sequence<long>? arg = []); + undefined passOptionalObjectSequence(optional sequence<TestInterface> arg); + undefined passExternalInterfaceSequence(sequence<TestExternalInterface> arg); + undefined passNullableExternalInterfaceSequence(sequence<TestExternalInterface?> arg); + + sequence<DOMString> receiveStringSequence(); + undefined passStringSequence(sequence<DOMString> arg); + + sequence<ByteString> receiveByteStringSequence(); + undefined passByteStringSequence(sequence<ByteString> arg); + + sequence<UTF8String> receiveUTF8StringSequence(); + undefined passUTF8StringSequence(sequence<UTF8String> arg); + + sequence<any> receiveAnySequence(); + sequence<any>? receiveNullableAnySequence(); + sequence<sequence<any>> receiveAnySequenceSequence(); + + sequence<object> receiveObjectSequence(); + sequence<object?> receiveNullableObjectSequence(); + + undefined passSequenceOfSequences(sequence<sequence<long>> arg); + undefined passSequenceOfSequencesOfSequences(sequence<sequence<sequence<long>>> arg); + sequence<sequence<long>> receiveSequenceOfSequences(); + sequence<sequence<sequence<long>>> receiveSequenceOfSequencesOfSequences(); + + // record types + undefined passRecord(record<DOMString, long> arg); + undefined passNullableRecord(record<DOMString, long>? arg); + undefined passRecordOfNullableInts(record<DOMString, long?> arg); + undefined passOptionalRecordOfNullableInts(optional record<DOMString, long?> arg); + undefined passOptionalNullableRecordOfNullableInts(optional record<DOMString, long?>? arg); + undefined passCastableObjectRecord(record<DOMString, TestInterface> arg); + undefined passNullableCastableObjectRecord(record<DOMString, TestInterface?> arg); + undefined passCastableObjectNullableRecord(record<DOMString, TestInterface>? arg); + undefined passNullableCastableObjectNullableRecord(record<DOMString, TestInterface?>? arg); + undefined passOptionalRecord(optional record<DOMString, long> arg); + undefined passOptionalNullableRecord(optional record<DOMString, long>? arg); + undefined passOptionalNullableRecordWithDefaultValue(optional record<DOMString, long>? arg = null); + undefined passOptionalObjectRecord(optional record<DOMString, TestInterface> arg); + undefined passExternalInterfaceRecord(record<DOMString, TestExternalInterface> arg); + undefined passNullableExternalInterfaceRecord(record<DOMString, TestExternalInterface?> arg); + undefined passStringRecord(record<DOMString, DOMString> arg); + undefined passByteStringRecord(record<DOMString, ByteString> arg); + undefined passUTF8StringRecord(record<DOMString, UTF8String> arg); + undefined passRecordOfRecords(record<DOMString, record<DOMString, long>> arg); + record<DOMString, long> receiveRecord(); + record<DOMString, long>? receiveNullableRecord(); + record<DOMString, long?> receiveRecordOfNullableInts(); + record<DOMString, long?>? receiveNullableRecordOfNullableInts(); + record<DOMString, record<DOMString, long>> receiveRecordOfRecords(); + record<DOMString, any> receiveAnyRecord(); + + // Typed array types + undefined passArrayBuffer(ArrayBuffer arg); + undefined passNullableArrayBuffer(ArrayBuffer? arg); + undefined passOptionalArrayBuffer(optional ArrayBuffer arg); + undefined passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); + undefined passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); + undefined passArrayBufferView(ArrayBufferView arg); + undefined passInt8Array(Int8Array arg); + undefined passInt16Array(Int16Array arg); + undefined passInt32Array(Int32Array arg); + undefined passUint8Array(Uint8Array arg); + undefined passUint16Array(Uint16Array arg); + undefined passUint32Array(Uint32Array arg); + undefined passUint8ClampedArray(Uint8ClampedArray arg); + undefined passFloat32Array(Float32Array arg); + undefined passFloat64Array(Float64Array arg); + undefined passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg); + undefined passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg); + undefined passRecordOfArrayBuffers(record<DOMString, ArrayBuffer> arg); + undefined passRecordOfNullableArrayBuffers(record<DOMString, ArrayBuffer?> arg); + undefined passVariadicTypedArray(Float32Array... arg); + undefined passVariadicNullableTypedArray(Float32Array?... arg); + Uint8Array receiveUint8Array(); + attribute Uint8Array uint8ArrayAttr; + + // DOMString types + undefined passString(DOMString arg); + undefined passNullableString(DOMString? arg); + undefined passOptionalString(optional DOMString arg); + undefined passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); + undefined passOptionalNullableString(optional DOMString? arg); + undefined passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); + undefined passVariadicString(DOMString... arg); + DOMString receiveString(); + + // ByteString types + undefined passByteString(ByteString arg); + undefined passNullableByteString(ByteString? arg); + undefined passOptionalByteString(optional ByteString arg); + undefined passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); + undefined passOptionalNullableByteString(optional ByteString? arg); + undefined passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); + undefined passVariadicByteString(ByteString... arg); + undefined passOptionalUnionByteString(optional (ByteString or long) arg); + undefined passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); + + // UTF8String types + undefined passUTF8String(UTF8String arg); + undefined passNullableUTF8String(UTF8String? arg); + undefined passOptionalUTF8String(optional UTF8String arg); + undefined passOptionalUTF8StringWithDefaultValue(optional UTF8String arg = "abc"); + undefined passOptionalNullableUTF8String(optional UTF8String? arg); + undefined passOptionalNullableUTF8StringWithDefaultValue(optional UTF8String? arg = null); + undefined passVariadicUTF8String(UTF8String... arg); + undefined passOptionalUnionUTF8String(optional (UTF8String or long) arg); + undefined passOptionalUnionUTF8StringWithDefaultValue(optional (UTF8String or long) arg = "abc"); + + // USVString types + undefined passUSVS(USVString arg); + undefined passNullableUSVS(USVString? arg); + undefined passOptionalUSVS(optional USVString arg); + undefined passOptionalUSVSWithDefaultValue(optional USVString arg = "abc"); + undefined passOptionalNullableUSVS(optional USVString? arg); + undefined passOptionalNullableUSVSWithDefaultValue(optional USVString? arg = null); + undefined passVariadicUSVS(USVString... arg); + USVString receiveUSVS(); + + // JSString types + undefined passJSString(JSString arg); + // undefined passNullableJSString(JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalJSString(optional JSString arg); // NOT SUPPORTED YET + undefined passOptionalJSStringWithDefaultValue(optional JSString arg = "abc"); + // undefined passOptionalNullableJSString(optional JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalNullableJSStringWithDefaultValue(optional JSString? arg = null); // NOT SUPPORTED YET + // undefined passVariadicJSString(JSString... arg); // NOT SUPPORTED YET + // undefined passRecordOfJSString(record<DOMString, JSString> arg); // NOT SUPPORTED YET + // undefined passSequenceOfJSString(sequence<JSString> arg); // NOT SUPPORTED YET + // undefined passUnionJSString((JSString or long) arg); // NOT SUPPORTED YET + JSString receiveJSString(); + // sequence<JSString> receiveJSStringSequence(); // NOT SUPPORTED YET + // (JSString or long) receiveJSStringUnion(); // NOT SUPPORTED YET + // record<DOMString, JSString> receiveJSStringRecord(); // NOT SUPPORTED YET + readonly attribute JSString readonlyJSStringAttr; + attribute JSString jsStringAttr; + + // Enumerated types + undefined passEnum(TestEnum arg); + undefined passNullableEnum(TestEnum? arg); + undefined passOptionalEnum(optional TestEnum arg); + undefined passEnumWithDefault(optional TestEnum arg = "a"); + undefined passOptionalNullableEnum(optional TestEnum? arg); + undefined passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null); + undefined passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a"); + TestEnum receiveEnum(); + TestEnum? receiveNullableEnum(); + attribute TestEnum enumAttribute; + readonly attribute TestEnum readonlyEnumAttribute; + + // Callback types + undefined passCallback(TestCallback arg); + undefined passNullableCallback(TestCallback? arg); + undefined passOptionalCallback(optional TestCallback arg); + undefined passOptionalNullableCallback(optional TestCallback? arg); + undefined passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null); + TestCallback receiveCallback(); + TestCallback? receiveNullableCallback(); + undefined passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); + undefined passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); + undefined passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); + attribute TestTreatAsNullCallback treatAsNullCallback; + attribute TestTreatAsNullCallback? nullableTreatAsNullCallback; + + // Force code generation of the various test callbacks we have. + undefined forceCallbackGeneration(TestIntegerReturn arg1, + TestNullableIntegerReturn arg2, + TestBooleanReturn arg3, + TestFloatReturn arg4, + TestStringReturn arg5, + TestEnumReturn arg6, + TestInterfaceReturn arg7, + TestNullableInterfaceReturn arg8, + TestExternalInterfaceReturn arg9, + TestNullableExternalInterfaceReturn arg10, + TestCallbackInterfaceReturn arg11, + TestNullableCallbackInterfaceReturn arg12, + TestCallbackReturn arg13, + TestNullableCallbackReturn arg14, + TestObjectReturn arg15, + TestNullableObjectReturn arg16, + TestTypedArrayReturn arg17, + TestNullableTypedArrayReturn arg18, + TestSequenceReturn arg19, + TestNullableSequenceReturn arg20, + TestIntegerArguments arg21, + TestInterfaceArguments arg22, + TestStringEnumArguments arg23, + TestObjectArguments arg24, + TestOptionalArguments arg25, + TestUndefinedConstruction arg26, + TestIntegerConstruction arg27, + TestBooleanConstruction arg28, + TestFloatConstruction arg29, + TestStringConstruction arg30, + TestEnumConstruction arg31, + TestInterfaceConstruction arg32, + TestExternalInterfaceConstruction arg33, + TestCallbackInterfaceConstruction arg34, + TestCallbackConstruction arg35, + TestObjectConstruction arg36, + TestTypedArrayConstruction arg37, + TestSequenceConstruction arg38); + + // Any types + undefined passAny(any arg); + undefined passVariadicAny(any... arg); + undefined passOptionalAny(optional any arg); + undefined passAnyDefaultNull(optional any arg = null); + undefined passSequenceOfAny(sequence<any> arg); + undefined passNullableSequenceOfAny(sequence<any>? arg); + undefined passOptionalSequenceOfAny(optional sequence<any> arg); + undefined passOptionalNullableSequenceOfAny(optional sequence<any>? arg); + undefined passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null); + undefined passSequenceOfSequenceOfAny(sequence<sequence<any>> arg); + undefined passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg); + undefined passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg); + undefined passRecordOfAny(record<DOMString, any> arg); + undefined passNullableRecordOfAny(record<DOMString, any>? arg); + undefined passOptionalRecordOfAny(optional record<DOMString, any> arg); + undefined passOptionalNullableRecordOfAny(optional record<DOMString, any>? arg); + undefined passOptionalRecordOfAnyWithDefaultValue(optional record<DOMString, any>? arg = null); + undefined passRecordOfRecordOfAny(record<DOMString, record<DOMString, any>> arg); + undefined passRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?> arg); + undefined passNullableRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableRecordOfAny(optional record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableSequenceOfAny(optional record<DOMString, sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableRecordOfAny(optional sequence<record<DOMString, any>?>? arg); + any receiveAny(); + + // object types + undefined passObject(object arg); + undefined passVariadicObject(object... arg); + undefined passNullableObject(object? arg); + undefined passVariadicNullableObject(object... arg); + undefined passOptionalObject(optional object arg); + undefined passOptionalNullableObject(optional object? arg); + undefined passOptionalNullableObjectWithDefaultValue(optional object? arg = null); + undefined passSequenceOfObject(sequence<object> arg); + undefined passSequenceOfNullableObject(sequence<object?> arg); + undefined passNullableSequenceOfObject(sequence<object>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg); + undefined passRecordOfObject(record<DOMString, object> arg); + object receiveObject(); + object? receiveNullableObject(); + + // Union types + undefined passUnion((object or long) arg); + // Some union tests are debug-only to avoid creating all those + // unused union types in opt builds. +#ifdef DEBUG + undefined passUnion2((long or boolean) arg); + undefined passUnion3((object or long or boolean) arg); + undefined passUnion4((Node or long or boolean) arg); + undefined passUnion5((object or boolean) arg); + undefined passUnion6((object or DOMString) arg); + undefined passUnion7((object or DOMString or long) arg); + undefined passUnion8((object or DOMString or boolean) arg); + undefined passUnion9((object or DOMString or long or boolean) arg); + undefined passUnion10(optional (EventInit or long) arg = {}); + undefined passUnion11(optional (CustomEventInit or long) arg = {}); + undefined passUnion12(optional (EventInit or long) arg = 5); + undefined passUnion13(optional (object or long?) arg = null); + undefined passUnion14(optional (object or long?) arg = 5); + undefined passUnion15((sequence<long> or long) arg); + undefined passUnion16(optional (sequence<long> or long) arg); + undefined passUnion17(optional (sequence<long>? or long) arg = 5); + undefined passUnion18((sequence<object> or long) arg); + undefined passUnion19(optional (sequence<object> or long) arg); + undefined passUnion20(optional (sequence<object> or long) arg = []); + undefined passUnion21((record<DOMString, long> or long) arg); + undefined passUnion22((record<DOMString, object> or long) arg); + undefined passUnion23((sequence<ImageData> or long) arg); + undefined passUnion24((sequence<ImageData?> or long) arg); + undefined passUnion25((sequence<sequence<ImageData>> or long) arg); + undefined passUnion26((sequence<sequence<ImageData?>> or long) arg); + undefined passUnion27(optional (sequence<DOMString> or EventInit) arg = {}); + undefined passUnion28(optional (EventInit or sequence<DOMString>) arg = {}); + undefined passUnionWithCallback((EventHandler or long) arg); + undefined passUnionWithByteString((ByteString or long) arg); + undefined passUnionWithUTF8String((UTF8String or long) arg); + undefined passUnionWithRecord((record<DOMString, DOMString> or DOMString) arg); + undefined passUnionWithRecordAndSequence((record<DOMString, DOMString> or sequence<DOMString>) arg); + undefined passUnionWithSequenceAndRecord((sequence<DOMString> or record<DOMString, DOMString>) arg); + undefined passUnionWithUSVS((USVString or long) arg); +#endif + undefined passUnionWithNullable((object? or long) arg); + undefined passNullableUnion((object or long)? arg); + undefined passOptionalUnion(optional (object or long) arg); + undefined passOptionalNullableUnion(optional (object or long)? arg); + undefined passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); + //undefined passUnionWithInterfaces((TestInterface or TestExternalInterface) arg); + //undefined passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg); + //undefined passUnionWithSequence((sequence<object> or long) arg); + undefined passUnionWithArrayBuffer((ArrayBuffer or long) arg); + undefined passUnionWithString((DOMString or object) arg); + // Using an enum in a union. Note that we use some enum not declared in our + // binding file, because UnionTypes.h will need to include the binding header + // for this enum. Pick an enum from an interface that won't drag in too much + // stuff. + undefined passUnionWithEnum((SupportedType or object) arg); + + // Trying to use a callback in a union won't include the test + // headers, unfortunately, so won't compile. + //undefined passUnionWithCallback((TestCallback or long) arg); + undefined passUnionWithObject((object or long) arg); + //undefined passUnionWithDict((Dict or long) arg); + + undefined passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); + undefined passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); + undefined passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); + undefined passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); + undefined passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); + undefined passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); + undefined passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); + undefined passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); + undefined passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); + undefined passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); + undefined passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); + undefined passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); + undefined passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); + undefined passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); + undefined passUnionWithDefaultValue20(optional (double or USVString) arg = "abc"); + undefined passUnionWithDefaultValue21(optional (double or USVString) arg = 1); + undefined passUnionWithDefaultValue22(optional (double or USVString) arg = 1.5); + undefined passUnionWithDefaultValue23(optional (double or UTF8String) arg = ""); + undefined passUnionWithDefaultValue24(optional (double or UTF8String) arg = 1); + undefined passUnionWithDefaultValue25(optional (double or UTF8String) arg = 1.5); + + undefined passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); + undefined passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); + undefined passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); + undefined passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); + undefined passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); + undefined passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); + undefined passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); + undefined passNullableUnionWithDefaultValue21(optional (double or USVString)? arg = "abc"); + undefined passNullableUnionWithDefaultValue22(optional (double or USVString)? arg = 1); + undefined passNullableUnionWithDefaultValue23(optional (double or USVString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue24(optional (double or USVString)? arg = null); + + undefined passNullableUnionWithDefaultValue25(optional (double or UTF8String)? arg = "abc"); + undefined passNullableUnionWithDefaultValue26(optional (double or UTF8String)? arg = 1); + undefined passNullableUnionWithDefaultValue27(optional (double or UTF8String)? arg = 1.5); + undefined passNullableUnionWithDefaultValue28(optional (double or UTF8String)? arg = null); + + undefined passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); + undefined passSequenceOfUnions2(sequence<(object or long)> arg); + undefined passVariadicUnion((CanvasPattern or CanvasGradient)... arg); + + undefined passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); + undefined passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); + undefined passRecordOfUnions(record<DOMString, (CanvasPattern or CanvasGradient)> arg); + // XXXbz no move constructor on some unions + // undefined passRecordOfUnions2(record<DOMString, (object or long)> arg); + + (CanvasPattern or CanvasGradient) receiveUnion(); + (object or long) receiveUnion2(); + (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); + (CanvasPattern or CanvasGradient)? receiveNullableUnion(); + (object or long)? receiveNullableUnion2(); + (undefined or CanvasPattern) receiveUnionWithUndefined(); + (undefined? or CanvasPattern) receiveUnionWithNullableUndefined(); + (undefined or CanvasPattern?) receiveUnionWithUndefinedAndNullable(); + (undefined or CanvasPattern)? receiveNullableUnionWithUndefined(); + + attribute (CanvasPattern or CanvasGradient) writableUnion; + attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; + attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; + attribute (undefined or CanvasPattern) writableUnionWithUndefined; + attribute (undefined? or CanvasPattern) writableUnionWithNullableUndefined; + attribute (undefined or CanvasPattern?) writableUnionWithUndefinedAndNullable; + attribute (undefined or CanvasPattern)? writableNullableUnionWithUndefined; + + // Promise types + undefined passPromise(Promise<any> arg); + undefined passOptionalPromise(optional Promise<any> arg); + undefined passPromiseSequence(sequence<Promise<any>> arg); + Promise<any> receivePromise(); + Promise<any> receiveAddrefedPromise(); + + // ObservableArray types + attribute ObservableArray<boolean> booleanObservableArray; + attribute ObservableArray<object> objectObservableArray; + attribute ObservableArray<any> anyObservableArray; + attribute ObservableArray<TestInterface> interfaceObservableArray; + attribute ObservableArray<long?> nullableObservableArray; + + // binaryNames tests + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(); + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(byte argument); + [BinaryName="attributeGetterRenamedTo"] + readonly attribute byte attributeGetterRenamedFrom; + [BinaryName="attributeRenamedTo"] + attribute byte attributeRenamedFrom; + + undefined passDictionary(optional Dict x = {}); + undefined passDictionary2(Dict x); + [Cached, Pure] + readonly attribute Dict readonlyDictionary; + [Cached, Pure] + readonly attribute Dict? readonlyNullableDictionary; + [Cached, Pure] + attribute Dict writableDictionary; + [Cached, Pure, Frozen] + readonly attribute Dict readonlyFrozenDictionary; + [Cached, Pure, Frozen] + readonly attribute Dict? readonlyFrozenNullableDictionary; + [Cached, Pure, Frozen] + attribute Dict writableFrozenDictionary; + Dict receiveDictionary(); + Dict? receiveNullableDictionary(); + undefined passOtherDictionary(optional GrandparentDict x = {}); + undefined passSequenceOfDictionaries(sequence<Dict> x); + undefined passRecordOfDictionaries(record<DOMString, GrandparentDict> x); + // No support for nullable dictionaries inside a sequence (nor should there be) + // undefined passSequenceOfNullableDictionaries(sequence<Dict?> x); + undefined passDictionaryOrLong(optional Dict x = {}); + undefined passDictionaryOrLong(long x); + + undefined passDictContainingDict(optional DictContainingDict arg = {}); + undefined passDictContainingSequence(optional DictContainingSequence arg = {}); + DictContainingSequence receiveDictContainingSequence(); + undefined passVariadicDictionary(Dict... arg); + + // EnforceRange/Clamp tests + undefined dontEnforceRangeOrClamp(byte arg); + undefined doEnforceRange([EnforceRange] byte arg); + undefined doEnforceRangeNullable([EnforceRange] byte? arg); + undefined doClamp([Clamp] byte arg); + undefined doClampNullable([Clamp] byte? arg); + attribute [EnforceRange] byte enforcedByte; + attribute [EnforceRange] byte? enforcedNullableByte; + attribute [Clamp] byte clampedByte; + attribute [Clamp] byte? clampedNullableByte; + + // Typedefs + const myLong myLongConstant = 5; + undefined exerciseTypedefInterfaces1(AnotherNameForTestInterface arg); + AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg); + undefined exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg); + + // Deprecated methods and attributes + [Deprecated="Components"] + attribute byte deprecatedAttribute; + [Deprecated="Components"] + byte deprecatedMethod(); + [Deprecated="Components"] + byte deprecatedMethodWithContext(any arg); + + // Static methods and attributes + static attribute boolean staticAttribute; + static undefined staticMethod(boolean arg); + static undefined staticMethodWithContext(any arg); + + // Testing static method with a reserved C++ keyword as the name + static undefined assert(boolean arg); + + // Deprecated static methods and attributes + [Deprecated="Components"] + static attribute byte staticDeprecatedAttribute; + [Deprecated="Components"] + static undefined staticDeprecatedMethod(); + [Deprecated="Components"] + static undefined staticDeprecatedMethodWithContext(any arg); + + // Overload resolution tests + //undefined overload1(DOMString... strs); + boolean overload1(TestInterface arg); + TestInterface overload1(DOMString strs, TestInterface arg); + undefined overload2(TestInterface arg); + undefined overload2(optional Dict arg = {}); + undefined overload2(boolean arg); + undefined overload2(DOMString arg); + undefined overload3(TestInterface arg); + undefined overload3(TestCallback arg); + undefined overload3(boolean arg); + undefined overload4(TestInterface arg); + undefined overload4(TestCallbackInterface arg); + undefined overload4(DOMString arg); + undefined overload5(long arg); + undefined overload5(TestEnum arg); + undefined overload6(long arg); + undefined overload6(boolean arg); + undefined overload7(long arg); + undefined overload7(boolean arg); + undefined overload7(ByteString arg); + undefined overload8(long arg); + undefined overload8(TestInterface arg); + undefined overload9(long? arg); + undefined overload9(DOMString arg); + undefined overload10(long? arg); + undefined overload10(object arg); + undefined overload11(long arg); + undefined overload11(DOMString? arg); + undefined overload12(long arg); + undefined overload12(boolean? arg); + undefined overload13(long? arg); + undefined overload13(boolean arg); + undefined overload14(optional long arg); + undefined overload14(TestInterface arg); + undefined overload15(long arg); + undefined overload15(optional TestInterface arg); + undefined overload16(long arg); + undefined overload16(optional TestInterface? arg); + undefined overload17(sequence<long> arg); + undefined overload17(record<DOMString, long> arg); + undefined overload18(record<DOMString, DOMString> arg); + undefined overload18(sequence<DOMString> arg); + undefined overload19(sequence<long> arg); + undefined overload19(optional Dict arg = {}); + undefined overload20(optional Dict arg = {}); + undefined overload20(sequence<long> arg); + + // Variadic handling + undefined passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); + + // Conditionally exposed methods/attributes + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable1; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable2; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable3; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable4; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable5; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable6; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable7; + [Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable8; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable9; + [Pref="dom.webidl.test1"] + undefined prefable10(); + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable11(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable12; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable13(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable14; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable15; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable16; + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined prefable17(); + [Func="TestFuncControlledMember"] + undefined prefable18(); + [Func="TestFuncControlledMember"] + undefined prefable19(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember", ChromeOnly] + undefined prefable20(); + [Trial="TestTrial"] + undefined prefable21(); + [Pref="dom.webidl.test1", Trial="TestTrial"] + undefined prefable22(); + + // Conditionally exposed methods/attributes involving [SecureContext] + [SecureContext] + readonly attribute boolean conditionalOnSecureContext1; + [SecureContext, Pref="dom.webidl.test1"] + readonly attribute boolean conditionalOnSecureContext2; + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean conditionalOnSecureContext3; + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean conditionalOnSecureContext4; + [SecureContext] + undefined conditionalOnSecureContext5(); + [SecureContext, Pref="dom.webidl.test1"] + undefined conditionalOnSecureContext6(); + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined conditionalOnSecureContext7(); + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined conditionalOnSecureContext8(); + [SecureContext, Trial="TestTrial"] + readonly attribute boolean conditionalOnSecureContext9; + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember", Trial="TestTrial"] + undefined conditionalOnSecureContext10(); + + // Miscellania + [LegacyLenientThis] attribute long attrWithLenientThis; + [LegacyUnforgeable] readonly attribute long unforgeableAttr; + [LegacyUnforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; + [LegacyUnforgeable] long unforgeableMethod(); + [LegacyUnforgeable, ChromeOnly] long unforgeableMethod2(); + stringifier; + undefined passRenamedInterface(TestRenamedInterface arg); + [PutForwards=writableByte] readonly attribute TestInterface putForwardsAttr; + [PutForwards=writableByte, LegacyLenientThis] readonly attribute TestInterface putForwardsAttr2; + [PutForwards=writableByte, ChromeOnly] readonly attribute TestInterface putForwardsAttr3; + [Throws] undefined throwingMethod(); + [Throws] attribute boolean throwingAttr; + [GetterThrows] attribute boolean throwingGetterAttr; + [SetterThrows] attribute boolean throwingSetterAttr; + [CanOOM] undefined canOOMMethod(); + [CanOOM] attribute boolean canOOMAttr; + [GetterCanOOM] attribute boolean canOOMGetterAttr; + [SetterCanOOM] attribute boolean canOOMSetterAttr; + [NeedsSubjectPrincipal] undefined needsSubjectPrincipalMethod(); + [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; + [NeedsCallerType] undefined needsCallerTypeMethod(); + [NeedsCallerType] attribute boolean needsCallerTypeAttr; + [NeedsSubjectPrincipal=NonSystem] undefined needsNonSystemSubjectPrincipalMethod(); + [NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr; + [CEReactions] undefined ceReactionsMethod(); + [CEReactions] undefined ceReactionsMethodOverload(); + [CEReactions] undefined ceReactionsMethodOverload(DOMString bar); + [CEReactions] attribute boolean ceReactionsAttr; + legacycaller short(unsigned long arg1, TestInterface arg2); + undefined passArgsWithDefaults(optional long arg1, + optional TestInterface? arg2 = null, + optional Dict arg3 = {}, optional double arg4 = 5.0, + optional float arg5); + + attribute any toJSONShouldSkipThis; + attribute TestParentInterface toJSONShouldSkipThis2; + attribute TestCallbackInterface toJSONShouldSkipThis3; + [Default] object toJSON(); + + attribute byte dashed-attribute; + undefined dashed-method(); + + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + undefined nonEnumerableMethod(); + + // [AllowShared] tests + attribute [AllowShared] ArrayBufferViewTypedef allowSharedArrayBufferViewTypedef; + attribute [AllowShared] ArrayBufferView allowSharedArrayBufferView; + attribute [AllowShared] ArrayBufferView? allowSharedNullableArrayBufferView; + attribute [AllowShared] ArrayBuffer allowSharedArrayBuffer; + attribute [AllowShared] ArrayBuffer? allowSharedNullableArrayBuffer; + + undefined passAllowSharedArrayBufferViewTypedef(AllowSharedArrayBufferViewTypedef foo); + undefined passAllowSharedArrayBufferView([AllowShared] ArrayBufferView foo); + undefined passAllowSharedNullableArrayBufferView([AllowShared] ArrayBufferView? foo); + undefined passAllowSharedArrayBuffer([AllowShared] ArrayBuffer foo); + undefined passAllowSharedNullableArrayBuffer([AllowShared] ArrayBuffer? foo); + undefined passUnionArrayBuffer((DOMString or ArrayBuffer) foo); + undefined passUnionAllowSharedArrayBuffer((DOMString or [AllowShared] ArrayBuffer) foo); + + // If you add things here, add them to TestExampleGen and TestJSImplGen as well +}; + +[Exposed=Window] +interface TestParentInterface { +}; + +[Exposed=Window] +interface TestChildInterface : TestParentInterface { +}; + +[Exposed=Window] +interface TestNonWrapperCacheInterface { +}; + +interface mixin InterfaceMixin { + undefined mixedInMethod(); + attribute boolean mixedInProperty; + + const long mixedInConstant = 5; +}; + +dictionary Dict : ParentDict { + TestEnum someEnum; + long x; + long a; + long b = 8; + long z = 9; + [EnforceRange] unsigned long enforcedUnsignedLong; + [Clamp] unsigned long clampedUnsignedLong; + DOMString str; + DOMString empty = ""; + TestEnum otherEnum = "b"; + DOMString otherStr = "def"; + DOMString? yetAnotherStr = null; + DOMString template; + ByteString byteStr; + ByteString emptyByteStr = ""; + ByteString otherByteStr = "def"; + // JSString jsStr; // NOT SUPPORTED YET + object someObj; + boolean prototype; + object? anotherObj = null; + TestCallback? someCallback = null; + any someAny; + any anotherAny = null; + + unrestricted float urFloat = 0; + unrestricted float urFloat2 = 1.1; + unrestricted float urFloat3 = -1.1; + unrestricted float? urFloat4 = null; + unrestricted float infUrFloat = Infinity; + unrestricted float negativeInfUrFloat = -Infinity; + unrestricted float nanUrFloat = NaN; + + unrestricted double urDouble = 0; + unrestricted double urDouble2 = 1.1; + unrestricted double urDouble3 = -1.1; + unrestricted double? urDouble4 = null; + unrestricted double infUrDouble = Infinity; + unrestricted double negativeInfUrDouble = -Infinity; + unrestricted double nanUrDouble = NaN; + + (float or DOMString) floatOrString = "str"; + (float or DOMString)? nullableFloatOrString = "str"; + (object or long) objectOrLong; +#ifdef DEBUG + (EventInit or long) eventInitOrLong; + (EventInit or long)? nullableEventInitOrLong; + (HTMLElement or long)? nullableHTMLElementOrLong; + // CustomEventInit is useful to test because it needs rooting. + (CustomEventInit or long) eventInitOrLong2; + (CustomEventInit or long)? nullableEventInitOrLong2; + (EventInit or long) eventInitOrLongWithDefaultValue = {}; + (CustomEventInit or long) eventInitOrLongWithDefaultValue2 = {}; + (EventInit or long) eventInitOrLongWithDefaultValue3 = 5; + (CustomEventInit or long) eventInitOrLongWithDefaultValue4 = 5; + (EventInit or long)? nullableEventInitOrLongWithDefaultValue = null; + (CustomEventInit or long)? nullableEventInitOrLongWithDefaultValue2 = null; + (EventInit or long)? nullableEventInitOrLongWithDefaultValue3 = 5; + (CustomEventInit or long)? nullableEventInitOrLongWithDefaultValue4 = 5; + (sequence<object> or long) objectSequenceOrLong; + (sequence<object> or long) objectSequenceOrLongWithDefaultValue1 = 1; + (sequence<object> or long) objectSequenceOrLongWithDefaultValue2 = []; + (sequence<object> or long)? nullableObjectSequenceOrLong; + (sequence<object> or long)? nullableObjectSequenceOrLongWithDefaultValue1 = 1; + (sequence<object> or long)? nullableObjectSequenceOrLongWithDefaultValue2 = []; +#endif + + ArrayBuffer arrayBuffer; + ArrayBuffer? nullableArrayBuffer; + Uint8Array uint8Array; + Float64Array? float64Array = null; + + sequence<long> seq1; + sequence<long> seq2 = []; + sequence<long>? seq3; + sequence<long>? seq4 = null; + sequence<long>? seq5 = []; + + long dashed-name; + + required long requiredLong; + required object requiredObject; + + CustomEventInit customEventInit; + TestDictionaryTypedef dictionaryTypedef; + + Promise<undefined> promise; + sequence<Promise<undefined>> promiseSequence; + + record<DOMString, long> recordMember; + record<DOMString, long>? nullableRecord; + record<DOMString, DOMString>? nullableRecordWithDefault = null; + record<USVString, long> usvStringRecord; + record<USVString, long>? nullableUSVStringRecordWithDefault = null; + record<ByteString, long> byteStringRecord; + record<ByteString, long>? nullableByteStringRecordWithDefault = null; + record<UTF8String, long> utf8StringRecord; + record<UTF8String, long>? nullableUTF8StringRecordWithDefault = null; + required record<DOMString, TestInterface> requiredRecord; + required record<USVString, TestInterface> requiredUSVRecord; + required record<ByteString, TestInterface> requiredByteRecord; + required record<UTF8String, TestInterface> requiredUTF8Record; +}; + +dictionary ParentDict : GrandparentDict { + long c = 5; + TestInterface someInterface; + TestInterface? someNullableInterface = null; + TestExternalInterface someExternalInterface; + any parentAny; +}; + +dictionary DictContainingDict { + Dict memberDict; +}; + +dictionary DictContainingSequence { + sequence<long> ourSequence; + sequence<TestInterface> ourSequence2; + sequence<any> ourSequence3; + sequence<object> ourSequence4; + sequence<object?> ourSequence5; + sequence<object>? ourSequence6; + sequence<object?>? ourSequence7; + sequence<object>? ourSequence8 = null; + sequence<object?>? ourSequence9 = null; + sequence<(float or DOMString)> ourSequence10; +}; + +dictionary DictForConstructor { + Dict dict; + DictContainingDict dict2; + sequence<Dict> seq1; + sequence<sequence<Dict>>? seq2; + sequence<sequence<Dict>?> seq3; + sequence<any> seq4; + sequence<any> seq5; + sequence<DictContainingSequence> seq6; + object obj1; + object? obj2; + any any1 = null; +}; + +dictionary DictWithConditionalMembers { + [ChromeOnly] + long chromeOnlyMember; + [Func="TestFuncControlledMember"] + long funcControlledMember; + [ChromeOnly, Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + long chromeOnlyFuncControlledMember; + // We need a pref name that's in StaticPrefList.h here. + [Pref="dom.webidl.test1"] + long prefControlledMember; + [Pref="dom.webidl.test1", ChromeOnly, Func="TestFuncControlledMember"] + long chromeOnlyFuncAndPrefControlledMember; +}; + +dictionary DictWithAllowSharedMembers { + [AllowShared] ArrayBufferView a; + [AllowShared] ArrayBufferView? b; + [AllowShared] ArrayBuffer c; + [AllowShared] ArrayBuffer? d; + [AllowShared] ArrayBufferViewTypedef e; + AllowSharedArrayBufferViewTypedef f; +}; + +[Exposed=Window] +interface TestIndexedGetterInterface { + getter long item(unsigned long idx); + readonly attribute unsigned long length; + legacycaller undefined(); + [Cached, Pure] readonly attribute long cachedAttr; + [StoreInSlot, Pure] readonly attribute long storeInSlotAttr; +}; + +[Exposed=Window] +interface TestNamedGetterInterface { + getter DOMString (DOMString name); +}; + +[Exposed=Window] +interface TestIndexedGetterAndSetterAndNamedGetterInterface { + getter DOMString (DOMString myName); + getter long (unsigned long index); + setter undefined (unsigned long index, long arg); + readonly attribute unsigned long length; +}; + +[Exposed=Window] +interface TestIndexedAndNamedGetterInterface { + getter long (unsigned long index); + getter DOMString namedItem(DOMString name); + readonly attribute unsigned long length; +}; + +[Exposed=Window] +interface TestIndexedSetterInterface { + setter undefined setItem(unsigned long idx, DOMString item); + getter DOMString (unsigned long idx); + readonly attribute unsigned long length; +}; + +[Exposed=Window] +interface TestNamedSetterInterface { + setter undefined (DOMString myName, TestIndexedSetterInterface item); + getter TestIndexedSetterInterface (DOMString name); +}; + +[Exposed=Window] +interface TestIndexedAndNamedSetterInterface { + setter undefined (unsigned long index, TestIndexedSetterInterface item); + getter TestIndexedSetterInterface (unsigned long index); + readonly attribute unsigned long length; + setter undefined setNamedItem(DOMString name, TestIndexedSetterInterface item); + getter TestIndexedSetterInterface (DOMString name); +}; + +[Exposed=Window] +interface TestIndexedAndNamedGetterAndSetterInterface : TestIndexedSetterInterface { + getter long item(unsigned long index); + getter DOMString namedItem(DOMString name); + setter undefined (unsigned long index, long item); + setter undefined (DOMString name, DOMString item); + stringifier DOMString (); + readonly attribute unsigned long length; +}; + +[Exposed=Window] +interface TestNamedDeleterInterface { + deleter undefined (DOMString name); + getter long (DOMString name); +}; + +[Exposed=Window] +interface TestNamedDeleterWithRetvalInterface { + deleter boolean delNamedItem(DOMString name); + getter long (DOMString name); +}; + +[Exposed=Window] +interface TestCppKeywordNamedMethodsInterface { + boolean continue(); + boolean delete(); + long volatile(); +}; + +[Deprecated="Components", + Exposed=Window] +interface TestDeprecatedInterface { + constructor(); + + static undefined alsoDeprecated(); +}; + + +[Exposed=Window] +interface TestInterfaceWithPromiseConstructorArg { + constructor(Promise<undefined> promise); +}; + +[Exposed=Window] +namespace TestNamespace { + readonly attribute boolean foo; + long bar(); +}; + +partial namespace TestNamespace { + undefined baz(); +}; + +[ClassString="RenamedNamespaceClassName", + Exposed=Window] +namespace TestRenamedNamespace { +}; + +[ProtoObjectHack, + Exposed=Window] +namespace TestProtoObjectHackedNamespace { +}; + +[SecureContext, + Exposed=Window] +interface TestSecureContextInterface { + static undefined alsoSecureContext(); +}; + +[Exposed=(Window,Worker)] +interface TestWorkerExposedInterface { + [NeedsSubjectPrincipal] undefined needsSubjectPrincipalMethod(); + [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; + [NeedsCallerType] undefined needsCallerTypeMethod(); + [NeedsCallerType] attribute boolean needsCallerTypeAttr; + [NeedsSubjectPrincipal=NonSystem] undefined needsNonSystemSubjectPrincipalMethod(); + [NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr; +}; + +[Exposed=Window] +interface TestHTMLConstructorInterface { + [HTMLConstructor] constructor(); +}; + +[Exposed=Window] +interface TestThrowingConstructorInterface { + [Throws] + constructor(); + [Throws] + constructor(DOMString str); + [Throws] + constructor(unsigned long num, boolean? boolArg); + [Throws] + constructor(TestInterface? iface); + [Throws] + constructor(unsigned long arg1, TestInterface iface); + [Throws] + constructor(ArrayBuffer arrayBuf); + [Throws] + constructor(Uint8Array typedArr); + // [Throws] constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3); +}; + +[Exposed=Window] +interface TestCEReactionsInterface { + [CEReactions] setter undefined (unsigned long index, long item); + [CEReactions] setter undefined (DOMString name, DOMString item); + [CEReactions] deleter undefined (DOMString name); + getter long item(unsigned long index); + getter DOMString (DOMString name); + readonly attribute unsigned long length; +}; + +typedef [EnforceRange] octet OctetRange; +typedef [Clamp] octet OctetClamp; +typedef [LegacyNullToEmptyString] DOMString NullEmptyString; +// typedef [TreatNullAs=EmptyString] JSString NullEmptyJSString; + +dictionary TestAttributesOnDictionaryMembers { + [Clamp] octet a; + [ChromeOnly, Clamp] octet b; + required [Clamp] octet c; + [ChromeOnly] octet d; + // ChromeOnly doesn't mix with required, so we can't + // test [ChromeOnly] required [Clamp] octet e +}; + +[Exposed=Window] +interface TestAttributesOnTypes { + undefined foo(OctetClamp thingy); + undefined bar(OctetRange thingy); + undefined baz(NullEmptyString thingy); + // undefined qux(NullEmptyJSString thingy); + attribute [Clamp] octet someAttr; + undefined argWithAttr([Clamp] octet arg0, optional [Clamp] octet arg1); + // There aren't any argument-only attributes that we can test here, + // TreatNonCallableAsNull isn't compatible with Clamp-able types +}; + +[Exposed=Window] +interface TestPrefConstructorForInterface { + // Since only the constructor is under a pref, + // the generated constructor should check for the pref. + [Pref="dom.webidl.test1"] constructor(); +}; + +[Exposed=Window, Pref="dom.webidl.test1"] +interface TestConstructorForPrefInterface { + // Since the interface itself is under a Pref, there should be no + // check for the pref in the generated constructor. + constructor(); +}; + +[Exposed=Window, Pref="dom.webidl.test1"] +interface TestPrefConstructorForDifferentPrefInterface { + // Since the constructor's pref is different than the interface pref + // there should still be a check for the pref in the generated constructor. + [Pref="dom.webidl.test2"] constructor(); +}; + +[Exposed=Window, SecureContext] +interface TestConstructorForSCInterface { + // Since the interface itself is SecureContext, there should be no + // runtime check for SecureContext in the generated constructor. + constructor(); +}; + +[Exposed=Window] +interface TestSCConstructorForInterface { + // Since the interface context is unspecified but the constructor is + // SecureContext, the generated constructor should check for SecureContext. + [SecureContext] constructor(); +}; + +[Exposed=Window, Func="Document::IsWebAnimationsEnabled"] +interface TestConstructorForFuncInterface { + // Since the interface has a Func attribute, but the constructor does not, + // the generated constructor should not check for the Func. + constructor(); +}; + +[Exposed=Window] +interface TestFuncConstructorForInterface { + // Since the constructor has a Func attribute, but the interface does not, + // the generated constructor should check for the Func. + [Func="Document::IsWebAnimationsEnabled"] + constructor(); +}; + +[Exposed=Window, Func="Document::AreWebAnimationsTimelinesEnabled"] +interface TestFuncConstructorForDifferentFuncInterface { + // Since the constructor has a different Func attribute from the interface, + // the generated constructor should still check for its conditional func. + [Func="Document::IsWebAnimationsEnabled"] + constructor(); +}; + +[Exposed=Window] +interface TestPrefChromeOnlySCFuncConstructorForInterface { + [Pref="dom.webidl.test1", ChromeOnly, SecureContext, Func="Document::IsWebAnimationsEnabled"] + // There should be checks for all Pref/ChromeOnly/SecureContext/Func + // in the generated constructor. + constructor(); +}; diff --git a/dom/bindings/test/TestDictionary.webidl b/dom/bindings/test/TestDictionary.webidl new file mode 100644 index 0000000000..37b7f5e84f --- /dev/null +++ b/dom/bindings/test/TestDictionary.webidl @@ -0,0 +1,9 @@ +/* -*- 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/. + */ + +dictionary GrandparentDict { + double someNum; +}; diff --git a/dom/bindings/test/TestExampleGen.webidl b/dom/bindings/test/TestExampleGen.webidl new file mode 100644 index 0000000000..1fbad8683e --- /dev/null +++ b/dom/bindings/test/TestExampleGen.webidl @@ -0,0 +1,911 @@ +/* -*- 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/. + */ +[LegacyFactoryFunction=Example, + LegacyFactoryFunction=Example(DOMString str), + LegacyFactoryFunction=Example2(DictForConstructor dict, any any1, object obj1, + object? obj2, sequence<Dict> seq, optional any any2, + optional object obj3, optional object? obj4), + LegacyFactoryFunction=Example2((long or record<DOMString, any>) arg1), + Exposed=Window] +interface TestExampleInterface { + constructor(); + constructor(DOMString str); + constructor(unsigned long num, boolean? boolArg); + constructor(TestInterface? iface); + constructor(unsigned long arg1, TestInterface iface); + constructor(ArrayBuffer arrayBuf); + constructor(Uint8Array typedArr); + // constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3); + + // Integer types + // XXXbz add tests for throwing versions of all the integer stuff + readonly attribute byte readonlyByte; + attribute byte writableByte; + undefined passByte(byte arg); + byte receiveByte(); + undefined passOptionalByte(optional byte arg); + undefined passOptionalByteBeforeRequired(optional byte arg1, byte arg2); + undefined passOptionalByteWithDefault(optional byte arg = 0); + undefined passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); + undefined passNullableByte(byte? arg); + undefined passOptionalNullableByte(optional byte? arg); + undefined passVariadicByte(byte... arg); + [Cached, Pure] + readonly attribute byte cachedByte; + [StoreInSlot, Constant] + readonly attribute byte cachedConstantByte; + [Cached, Pure] + attribute byte cachedWritableByte; + [Affects=Nothing] + attribute byte sideEffectFreeByte; + [Affects=Nothing, DependsOn=DOMState] + attribute byte domDependentByte; + [Affects=Nothing, DependsOn=Nothing] + readonly attribute byte constantByte; + [DependsOn=DeviceState, Affects=Nothing] + readonly attribute byte deviceStateDependentByte; + [Affects=Nothing] + byte returnByteSideEffectFree(); + [Affects=Nothing, DependsOn=DOMState] + byte returnDOMDependentByte(); + [Affects=Nothing, DependsOn=Nothing] + byte returnConstantByte(); + [DependsOn=DeviceState, Affects=Nothing] + byte returnDeviceStateDependentByte(); + + readonly attribute short readonlyShort; + attribute short writableShort; + undefined passShort(short arg); + short receiveShort(); + undefined passOptionalShort(optional short arg); + undefined passOptionalShortWithDefault(optional short arg = 5); + + readonly attribute long readonlyLong; + attribute long writableLong; + undefined passLong(long arg); + long receiveLong(); + undefined passOptionalLong(optional long arg); + undefined passOptionalLongWithDefault(optional long arg = 7); + + readonly attribute long long readonlyLongLong; + attribute long long writableLongLong; + undefined passLongLong(long long arg); + long long receiveLongLong(); + undefined passOptionalLongLong(optional long long arg); + undefined passOptionalLongLongWithDefault(optional long long arg = -12); + + readonly attribute octet readonlyOctet; + attribute octet writableOctet; + undefined passOctet(octet arg); + octet receiveOctet(); + undefined passOptionalOctet(optional octet arg); + undefined passOptionalOctetWithDefault(optional octet arg = 19); + + readonly attribute unsigned short readonlyUnsignedShort; + attribute unsigned short writableUnsignedShort; + undefined passUnsignedShort(unsigned short arg); + unsigned short receiveUnsignedShort(); + undefined passOptionalUnsignedShort(optional unsigned short arg); + undefined passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); + + readonly attribute unsigned long readonlyUnsignedLong; + attribute unsigned long writableUnsignedLong; + undefined passUnsignedLong(unsigned long arg); + unsigned long receiveUnsignedLong(); + undefined passOptionalUnsignedLong(optional unsigned long arg); + undefined passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); + + readonly attribute unsigned long long readonlyUnsignedLongLong; + attribute unsigned long long writableUnsignedLongLong; + undefined passUnsignedLongLong(unsigned long long arg); + unsigned long long receiveUnsignedLongLong(); + undefined passOptionalUnsignedLongLong(optional unsigned long long arg); + undefined passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); + + attribute float writableFloat; + attribute unrestricted float writableUnrestrictedFloat; + attribute float? writableNullableFloat; + attribute unrestricted float? writableNullableUnrestrictedFloat; + attribute double writableDouble; + attribute unrestricted double writableUnrestrictedDouble; + attribute double? writableNullableDouble; + attribute unrestricted double? writableNullableUnrestrictedDouble; + undefined passFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, sequence<unrestricted float> arg10, + sequence<float?> arg11, sequence<unrestricted float?> arg12, + sequence<double> arg13, sequence<unrestricted double> arg14, + sequence<double?> arg15, sequence<unrestricted double?> arg16); + [LenientFloat] + undefined passLenientFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, + sequence<unrestricted float> arg10, + sequence<float?> arg11, + sequence<unrestricted float?> arg12, + sequence<double> arg13, + sequence<unrestricted double> arg14, + sequence<double?> arg15, + sequence<unrestricted double?> arg16); + [LenientFloat] + attribute float lenientFloatAttr; + [LenientFloat] + attribute double lenientDoubleAttr; + + // Castable interface types + // XXXbz add tests for throwing versions of all the castable interface stuff + TestInterface receiveSelf(); + TestInterface? receiveNullableSelf(); + TestInterface receiveWeakSelf(); + TestInterface? receiveWeakNullableSelf(); + undefined passSelf(TestInterface arg); + undefined passNullableSelf(TestInterface? arg); + attribute TestInterface nonNullSelf; + attribute TestInterface? nullableSelf; + [Cached, Pure] + readonly attribute TestInterface cachedSelf; + // Optional arguments + undefined passOptionalSelf(optional TestInterface? arg); + undefined passOptionalNonNullSelf(optional TestInterface arg); + undefined passOptionalSelfWithDefault(optional TestInterface? arg = null); + + // Non-wrapper-cache interface types + [NewObject] + TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); + [NewObject] + TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); + [NewObject] + sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence(); + + // External interface types + TestExternalInterface receiveExternal(); + TestExternalInterface? receiveNullableExternal(); + TestExternalInterface receiveWeakExternal(); + TestExternalInterface? receiveWeakNullableExternal(); + undefined passExternal(TestExternalInterface arg); + undefined passNullableExternal(TestExternalInterface? arg); + attribute TestExternalInterface nonNullExternal; + attribute TestExternalInterface? nullableExternal; + // Optional arguments + undefined passOptionalExternal(optional TestExternalInterface? arg); + undefined passOptionalNonNullExternal(optional TestExternalInterface arg); + undefined passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); + + // Callback interface types + TestCallbackInterface receiveCallbackInterface(); + TestCallbackInterface? receiveNullableCallbackInterface(); + TestCallbackInterface receiveWeakCallbackInterface(); + TestCallbackInterface? receiveWeakNullableCallbackInterface(); + undefined passCallbackInterface(TestCallbackInterface arg); + undefined passNullableCallbackInterface(TestCallbackInterface? arg); + attribute TestCallbackInterface nonNullCallbackInterface; + attribute TestCallbackInterface? nullableCallbackInterface; + // Optional arguments + undefined passOptionalCallbackInterface(optional TestCallbackInterface? arg); + undefined passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); + undefined passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); + + // Sequence types + [Cached, Pure] + readonly attribute sequence<long> readonlySequence; + [Cached, Pure] + readonly attribute sequence<Dict> readonlySequenceOfDictionaries; + [Cached, Pure] + readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries; + [Cached, Pure, Frozen] + readonly attribute sequence<long> readonlyFrozenSequence; + [Cached, Pure, Frozen] + readonly attribute sequence<long>? readonlyFrozenNullableSequence; + sequence<long> receiveSequence(); + sequence<long>? receiveNullableSequence(); + sequence<long?> receiveSequenceOfNullableInts(); + sequence<long?>? receiveNullableSequenceOfNullableInts(); + undefined passSequence(sequence<long> arg); + undefined passNullableSequence(sequence<long>? arg); + undefined passSequenceOfNullableInts(sequence<long?> arg); + undefined passOptionalSequenceOfNullableInts(optional sequence<long?> arg); + undefined passOptionalNullableSequenceOfNullableInts(optional sequence<long?>? arg); + sequence<TestInterface> receiveCastableObjectSequence(); + sequence<TestCallbackInterface> receiveCallbackObjectSequence(); + sequence<TestInterface?> receiveNullableCastableObjectSequence(); + sequence<TestCallbackInterface?> receiveNullableCallbackObjectSequence(); + sequence<TestInterface>? receiveCastableObjectNullableSequence(); + sequence<TestInterface?>? receiveNullableCastableObjectNullableSequence(); + sequence<TestInterface> receiveWeakCastableObjectSequence(); + sequence<TestInterface?> receiveWeakNullableCastableObjectSequence(); + sequence<TestInterface>? receiveWeakCastableObjectNullableSequence(); + sequence<TestInterface?>? receiveWeakNullableCastableObjectNullableSequence(); + undefined passCastableObjectSequence(sequence<TestInterface> arg); + undefined passNullableCastableObjectSequence(sequence<TestInterface?> arg); + undefined passCastableObjectNullableSequence(sequence<TestInterface>? arg); + undefined passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg); + undefined passOptionalSequence(optional sequence<long> arg); + undefined passOptionalSequenceWithDefaultValue(optional sequence<long> arg = []); + undefined passOptionalNullableSequence(optional sequence<long>? arg); + undefined passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null); + undefined passOptionalNullableSequenceWithDefaultValue2(optional sequence<long>? arg = []); + undefined passOptionalObjectSequence(optional sequence<TestInterface> arg); + undefined passExternalInterfaceSequence(sequence<TestExternalInterface> arg); + undefined passNullableExternalInterfaceSequence(sequence<TestExternalInterface?> arg); + + sequence<DOMString> receiveStringSequence(); + undefined passStringSequence(sequence<DOMString> arg); + + sequence<ByteString> receiveByteStringSequence(); + undefined passByteStringSequence(sequence<ByteString> arg); + + sequence<UTF8String> receiveUTF8StringSequence(); + undefined passUTF8StringSequence(sequence<UTF8String> arg); + + sequence<any> receiveAnySequence(); + sequence<any>? receiveNullableAnySequence(); + //XXXbz No support for sequence of sequence return values yet. + //sequence<sequence<any>> receiveAnySequenceSequence(); + + sequence<object> receiveObjectSequence(); + sequence<object?> receiveNullableObjectSequence(); + + undefined passSequenceOfSequences(sequence<sequence<long>> arg); + undefined passSequenceOfSequencesOfSequences(sequence<sequence<sequence<long>>> arg); + //XXXbz No support for sequence of sequence return values yet. + //sequence<sequence<long>> receiveSequenceOfSequences(); + + // record types + undefined passRecord(record<DOMString, long> arg); + undefined passNullableRecord(record<DOMString, long>? arg); + undefined passRecordOfNullableInts(record<DOMString, long?> arg); + undefined passOptionalRecordOfNullableInts(optional record<DOMString, long?> arg); + undefined passOptionalNullableRecordOfNullableInts(optional record<DOMString, long?>? arg); + undefined passCastableObjectRecord(record<DOMString, TestInterface> arg); + undefined passNullableCastableObjectRecord(record<DOMString, TestInterface?> arg); + undefined passCastableObjectNullableRecord(record<DOMString, TestInterface>? arg); + undefined passNullableCastableObjectNullableRecord(record<DOMString, TestInterface?>? arg); + undefined passOptionalRecord(optional record<DOMString, long> arg); + undefined passOptionalNullableRecord(optional record<DOMString, long>? arg); + undefined passOptionalNullableRecordWithDefaultValue(optional record<DOMString, long>? arg = null); + undefined passOptionalObjectRecord(optional record<DOMString, TestInterface> arg); + undefined passExternalInterfaceRecord(record<DOMString, TestExternalInterface> arg); + undefined passNullableExternalInterfaceRecord(record<DOMString, TestExternalInterface?> arg); + undefined passStringRecord(record<DOMString, DOMString> arg); + undefined passByteStringRecord(record<DOMString, ByteString> arg); + undefined passUTF8StringRecord(record<DOMString, UTF8String> arg); + undefined passRecordOfRecords(record<DOMString, record<DOMString, long>> arg); + record<DOMString, long> receiveRecord(); + record<DOMString, long>? receiveNullableRecord(); + record<DOMString, long?> receiveRecordOfNullableInts(); + record<DOMString, long?>? receiveNullableRecordOfNullableInts(); + //XXXbz No support for record of records return values yet. + //record<DOMString, record<DOMString, long>> receiveRecordOfRecords(); + record<DOMString, any> receiveAnyRecord(); + + // Typed array types + undefined passArrayBuffer(ArrayBuffer arg); + undefined passNullableArrayBuffer(ArrayBuffer? arg); + undefined passOptionalArrayBuffer(optional ArrayBuffer arg); + undefined passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); + undefined passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); + undefined passArrayBufferView(ArrayBufferView arg); + undefined passInt8Array(Int8Array arg); + undefined passInt16Array(Int16Array arg); + undefined passInt32Array(Int32Array arg); + undefined passUint8Array(Uint8Array arg); + undefined passUint16Array(Uint16Array arg); + undefined passUint32Array(Uint32Array arg); + undefined passUint8ClampedArray(Uint8ClampedArray arg); + undefined passFloat32Array(Float32Array arg); + undefined passFloat64Array(Float64Array arg); + undefined passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg); + undefined passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg); + undefined passRecordOfArrayBuffers(record<DOMString, ArrayBuffer> arg); + undefined passRecordOfNullableArrayBuffers(record<DOMString, ArrayBuffer?> arg); + undefined passVariadicTypedArray(Float32Array... arg); + undefined passVariadicNullableTypedArray(Float32Array?... arg); + Uint8Array receiveUint8Array(); + attribute Uint8Array uint8ArrayAttr; + + // DOMString types + undefined passString(DOMString arg); + undefined passNullableString(DOMString? arg); + undefined passOptionalString(optional DOMString arg); + undefined passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); + undefined passOptionalNullableString(optional DOMString? arg); + undefined passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); + undefined passVariadicString(DOMString... arg); + + // ByteString types + undefined passByteString(ByteString arg); + undefined passNullableByteString(ByteString? arg); + undefined passOptionalByteString(optional ByteString arg); + undefined passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); + undefined passOptionalNullableByteString(optional ByteString? arg); + undefined passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); + undefined passVariadicByteString(ByteString... arg); + undefined passUnionByteString((ByteString or long) arg); + undefined passOptionalUnionByteString(optional (ByteString or long) arg); + undefined passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); + + // UTF8String types + undefined passUTF8String(UTF8String arg); + undefined passNullableUTF8String(UTF8String? arg); + undefined passOptionalUTF8String(optional UTF8String arg); + undefined passOptionalUTF8StringWithDefaultValue(optional UTF8String arg = "abc"); + undefined passOptionalNullableUTF8String(optional UTF8String? arg); + undefined passOptionalNullableUTF8StringWithDefaultValue(optional UTF8String? arg = null); + undefined passVariadicUTF8String(UTF8String... arg); + undefined passUnionUTF8String((UTF8String or long) arg); + undefined passOptionalUnionUTF8String(optional (UTF8String or long) arg); + undefined passOptionalUnionUTF8StringWithDefaultValue(optional (UTF8String or long) arg = "abc"); + + // USVString types + undefined passSVS(USVString arg); + undefined passNullableSVS(USVString? arg); + undefined passOptionalSVS(optional USVString arg); + undefined passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); + undefined passOptionalNullableSVS(optional USVString? arg); + undefined passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); + undefined passVariadicSVS(USVString... arg); + USVString receiveSVS(); + + // JSString types + undefined passJSString(JSString arg); + // undefined passNullableJSString(JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalJSString(optional JSString arg); // NOT SUPPORTED YET + undefined passOptionalJSStringWithDefaultValue(optional JSString arg = "abc"); + // undefined passOptionalNullableJSString(optional JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalNullableJSStringWithDefaultValue(optional JSString? arg = null); // NOT SUPPORTED YET + // undefined passVariadicJSString(JSString... arg); // NOT SUPPORTED YET + // undefined passRecordOfJSString(record<DOMString, JSString> arg); // NOT SUPPORTED YET + // undefined passSequenceOfJSString(sequence<JSString> arg); // NOT SUPPORTED YET + // undefined passUnionJSString((JSString or long) arg); // NOT SUPPORTED YET + JSString receiveJSString(); + // sequence<JSString> receiveJSStringSequence(); // NOT SUPPORTED YET + // (JSString or long) receiveJSStringUnion(); // NOT SUPPORTED YET + // record<DOMString, JSString> receiveJSStringRecord(); // NOT SUPPORTED YET + readonly attribute JSString readonlyJSStringAttr; + attribute JSString jsStringAttr; + + // Enumerated types + undefined passEnum(TestEnum arg); + undefined passNullableEnum(TestEnum? arg); + undefined passOptionalEnum(optional TestEnum arg); + undefined passEnumWithDefault(optional TestEnum arg = "a"); + undefined passOptionalNullableEnum(optional TestEnum? arg); + undefined passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null); + undefined passOptionalNullableEnumWithDefaultValue2(optional TestEnum? arg = "a"); + TestEnum receiveEnum(); + TestEnum? receiveNullableEnum(); + attribute TestEnum enumAttribute; + readonly attribute TestEnum readonlyEnumAttribute; + + // Callback types + undefined passCallback(TestCallback arg); + undefined passNullableCallback(TestCallback? arg); + undefined passOptionalCallback(optional TestCallback arg); + undefined passOptionalNullableCallback(optional TestCallback? arg); + undefined passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null); + TestCallback receiveCallback(); + TestCallback? receiveNullableCallback(); + undefined passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); + undefined passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); + undefined passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); + + // Any types + undefined passAny(any arg); + undefined passVariadicAny(any... arg); + undefined passOptionalAny(optional any arg); + undefined passAnyDefaultNull(optional any arg = null); + undefined passSequenceOfAny(sequence<any> arg); + undefined passNullableSequenceOfAny(sequence<any>? arg); + undefined passOptionalSequenceOfAny(optional sequence<any> arg); + undefined passOptionalNullableSequenceOfAny(optional sequence<any>? arg); + undefined passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null); + undefined passSequenceOfSequenceOfAny(sequence<sequence<any>> arg); + undefined passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg); + undefined passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg); + undefined passRecordOfAny(record<DOMString, any> arg); + undefined passNullableRecordOfAny(record<DOMString, any>? arg); + undefined passOptionalRecordOfAny(optional record<DOMString, any> arg); + undefined passOptionalNullableRecordOfAny(optional record<DOMString, any>? arg); + undefined passOptionalRecordOfAnyWithDefaultValue(optional record<DOMString, any>? arg = null); + undefined passRecordOfRecordOfAny(record<DOMString, record<DOMString, any>> arg); + undefined passRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?> arg); + undefined passNullableRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableRecordOfAny(optional record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableSequenceOfAny(optional record<DOMString, sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableRecordOfAny(optional sequence<record<DOMString, any>?>? arg); + any receiveAny(); + + // object types + undefined passObject(object arg); + undefined passVariadicObject(object... arg); + undefined passNullableObject(object? arg); + undefined passVariadicNullableObject(object... arg); + undefined passOptionalObject(optional object arg); + undefined passOptionalNullableObject(optional object? arg); + undefined passOptionalNullableObjectWithDefaultValue(optional object? arg = null); + undefined passSequenceOfObject(sequence<object> arg); + undefined passSequenceOfNullableObject(sequence<object?> arg); + undefined passNullableSequenceOfObject(sequence<object>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg); + undefined passRecordOfObject(record<DOMString, object> arg); + object receiveObject(); + object? receiveNullableObject(); + + // Union types + undefined passUnion((object or long) arg); + // Some union tests are debug-only to avoid creating all those + // unused union types in opt builds. + +#ifdef DEBUG + undefined passUnion2((long or boolean) arg); + undefined passUnion3((object or long or boolean) arg); + undefined passUnion4((Node or long or boolean) arg); + undefined passUnion5((object or boolean) arg); + undefined passUnion6((object or DOMString) arg); + undefined passUnion7((object or DOMString or long) arg); + undefined passUnion8((object or DOMString or boolean) arg); + undefined passUnion9((object or DOMString or long or boolean) arg); + undefined passUnion10(optional (EventInit or long) arg = {}); + undefined passUnion11(optional (CustomEventInit or long) arg = {}); + undefined passUnion12(optional (EventInit or long) arg = 5); + undefined passUnion13(optional (object or long?) arg = null); + undefined passUnion14(optional (object or long?) arg = 5); + undefined passUnion15((sequence<long> or long) arg); + undefined passUnion16(optional (sequence<long> or long) arg); + undefined passUnion17(optional (sequence<long>? or long) arg = 5); + undefined passUnion18((sequence<object> or long) arg); + undefined passUnion19(optional (sequence<object> or long) arg); + undefined passUnion20(optional (sequence<object> or long) arg = []); + undefined passUnion21((record<DOMString, long> or long) arg); + undefined passUnion22((record<DOMString, object> or long) arg); + undefined passUnion23((sequence<ImageData> or long) arg); + undefined passUnion24((sequence<ImageData?> or long) arg); + undefined passUnion25((sequence<sequence<ImageData>> or long) arg); + undefined passUnion26((sequence<sequence<ImageData?>> or long) arg); + undefined passUnion27(optional (sequence<DOMString> or EventInit) arg = {}); + undefined passUnion28(optional (EventInit or sequence<DOMString>) arg = {}); + undefined passUnionWithCallback((EventHandler or long) arg); + undefined passUnionWithByteString((ByteString or long) arg); + undefined passUnionWithUTF8String((UTF8String or long) arg); + undefined passUnionWithRecord((record<DOMString, DOMString> or DOMString) arg); + undefined passUnionWithRecordAndSequence((record<DOMString, DOMString> or sequence<DOMString>) arg); + undefined passUnionWithSequenceAndRecord((sequence<DOMString> or record<DOMString, DOMString>) arg); + undefined passUnionWithSVS((USVString or long) arg); +#endif + undefined passUnionWithNullable((object? or long) arg); + undefined passNullableUnion((object or long)? arg); + undefined passOptionalUnion(optional (object or long) arg); + undefined passOptionalNullableUnion(optional (object or long)? arg); + undefined passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); + //undefined passUnionWithInterfaces((TestInterface or TestExternalInterface) arg); + //undefined passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg); + //undefined passUnionWithSequence((sequence<object> or long) arg); + undefined passUnionWithArrayBuffer((ArrayBuffer or long) arg); + undefined passUnionWithString((DOMString or object) arg); + // Using an enum in a union. Note that we use some enum not declared in our + // binding file, because UnionTypes.h will need to include the binding header + // for this enum. Pick an enum from an interface that won't drag in too much + // stuff. + undefined passUnionWithEnum((SupportedType or object) arg); + + // Trying to use a callback in a union won't include the test + // headers, unfortunately, so won't compile. + // undefined passUnionWithCallback((TestCallback or long) arg); + undefined passUnionWithObject((object or long) arg); + //undefined passUnionWithDict((Dict or long) arg); + + undefined passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); + undefined passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); + undefined passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); + undefined passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); + undefined passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); + undefined passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); + undefined passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); + undefined passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); + undefined passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); + undefined passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); + undefined passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); + undefined passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); + undefined passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); + undefined passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); + undefined passUnionWithDefaultValue20(optional (double or USVString) arg = "abc"); + undefined passUnionWithDefaultValue21(optional (double or USVString) arg = 1); + undefined passUnionWithDefaultValue22(optional (double or USVString) arg = 1.5); + undefined passUnionWithDefaultValue23(optional (double or UTF8String) arg = ""); + undefined passUnionWithDefaultValue24(optional (double or UTF8String) arg = 1); + undefined passUnionWithDefaultValue25(optional (double or UTF8String) arg = 1.5); + + undefined passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); + undefined passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); + undefined passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); + undefined passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); + undefined passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); + undefined passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); + undefined passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); + undefined passNullableUnionWithDefaultValue21(optional (double or USVString)? arg = "abc"); + undefined passNullableUnionWithDefaultValue22(optional (double or USVString)? arg = 1); + undefined passNullableUnionWithDefaultValue23(optional (double or USVString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue24(optional (double or USVString)? arg = null); + undefined passNullableUnionWithDefaultValue25(optional (double or UTF8String)? arg = ""); + undefined passNullableUnionWithDefaultValue26(optional (double or UTF8String)? arg = 1); + undefined passNullableUnionWithDefaultValue27(optional (double or UTF8String)? arg = 1.5); + undefined passNullableUnionWithDefaultValue28(optional (double or UTF8String)? arg = null); + + undefined passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); + undefined passSequenceOfUnions2(sequence<(object or long)> arg); + undefined passVariadicUnion((CanvasPattern or CanvasGradient)... arg); + + undefined passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); + undefined passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); + undefined passRecordOfUnions(record<DOMString, (CanvasPattern or CanvasGradient)> arg); + // XXXbz no move constructor on some unions + // undefined passRecordOfUnions2(record<DOMString, (object or long)> arg); + + (CanvasPattern or CanvasGradient) receiveUnion(); + (object or long) receiveUnion2(); + (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); + (CanvasPattern or CanvasGradient)? receiveNullableUnion(); + (object or long)? receiveNullableUnion2(); + (undefined or CanvasPattern) receiveUnionWithUndefined(); + (undefined? or CanvasPattern) receiveUnionWithNullableUndefined(); + (undefined or CanvasPattern?) receiveUnionWithUndefinedAndNullable(); + (undefined or CanvasPattern)? receiveNullableUnionWithUndefined(); + + attribute (CanvasPattern or CanvasGradient) writableUnion; + attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; + attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; + attribute (undefined or CanvasPattern) writableUnionWithUndefined; + attribute (undefined? or CanvasPattern) writableUnionWithNullableUndefined; + attribute (undefined or CanvasPattern?) writableUnionWithUndefinedAndNullable; + attribute (undefined or CanvasPattern)? writableNullableUnionWithUndefined; + + // Promise types + undefined passPromise(Promise<any> arg); + undefined passOptionalPromise(optional Promise<any> arg); + undefined passPromiseSequence(sequence<Promise<any>> arg); + Promise<any> receivePromise(); + Promise<any> receiveAddrefedPromise(); + + // ObservableArray types + attribute ObservableArray<boolean> booleanObservableArray; + attribute ObservableArray<object> objectObservableArray; + attribute ObservableArray<any> anyObservableArray; + attribute ObservableArray<TestInterface> interfaceObservableArray; + attribute ObservableArray<long?> nullableObservableArray; + + // binaryNames tests + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(); + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(byte argument); + [BinaryName="attributeGetterRenamedTo"] + readonly attribute byte attributeGetterRenamedFrom; + [BinaryName="attributeRenamedTo"] + attribute byte attributeRenamedFrom; + + undefined passDictionary(optional Dict x = {}); + undefined passDictionary2(Dict x); + [Cached, Pure] + readonly attribute Dict readonlyDictionary; + [Cached, Pure] + readonly attribute Dict? readonlyNullableDictionary; + [Cached, Pure] + attribute Dict writableDictionary; + [Cached, Pure, Frozen] + readonly attribute Dict readonlyFrozenDictionary; + [Cached, Pure, Frozen] + readonly attribute Dict? readonlyFrozenNullableDictionary; + [Cached, Pure, Frozen] + attribute Dict writableFrozenDictionary; + Dict receiveDictionary(); + Dict? receiveNullableDictionary(); + undefined passOtherDictionary(optional GrandparentDict x = {}); + undefined passSequenceOfDictionaries(sequence<Dict> x); + undefined passRecordOfDictionaries(record<DOMString, GrandparentDict> x); + // No support for nullable dictionaries inside a sequence (nor should there be) + // undefined passSequenceOfNullableDictionaries(sequence<Dict?> x); + undefined passDictionaryOrLong(optional Dict x = {}); + undefined passDictionaryOrLong(long x); + + undefined passDictContainingDict(optional DictContainingDict arg = {}); + undefined passDictContainingSequence(optional DictContainingSequence arg = {}); + DictContainingSequence receiveDictContainingSequence(); + undefined passVariadicDictionary(Dict... arg); + + // EnforceRange/Clamp tests + undefined dontEnforceRangeOrClamp(byte arg); + undefined doEnforceRange([EnforceRange] byte arg); + undefined doEnforceRangeNullable([EnforceRange] byte? arg); + undefined doClamp([Clamp] byte arg); + undefined doClampNullable([Clamp] byte? arg); + attribute [EnforceRange] byte enforcedByte; + attribute [EnforceRange] byte? enforcedByteNullable; + attribute [Clamp] byte clampedByte; + attribute [Clamp] byte? clampedByteNullable; + + // Typedefs + const myLong myLongConstant = 5; + undefined exerciseTypedefInterfaces1(AnotherNameForTestInterface arg); + AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg); + undefined exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg); + + // Deprecated methods and attributes + [Deprecated="Components"] + attribute boolean deprecatedAttribute; + [Deprecated="Components"] + undefined deprecatedMethod(boolean arg); + [Deprecated="Components"] + undefined deprecatedMethodWithContext(any arg); + + // Static methods and attributes + static attribute boolean staticAttribute; + static undefined staticMethod(boolean arg); + static undefined staticMethodWithContext(any arg); + + // Deprecated methods and attributes; + [Deprecated="Components"] + static attribute boolean staticDeprecatedAttribute; + [Deprecated="Components"] + static undefined staticDeprecatedMethod(boolean arg); + [Deprecated="Components"] + static undefined staticDeprecatedMethodWithContext(any arg); + + // Overload resolution tests + //undefined overload1(DOMString... strs); + boolean overload1(TestInterface arg); + TestInterface overload1(DOMString strs, TestInterface arg); + undefined overload2(TestInterface arg); + undefined overload2(optional Dict arg = {}); + undefined overload2(boolean arg); + undefined overload2(DOMString arg); + undefined overload3(TestInterface arg); + undefined overload3(TestCallback arg); + undefined overload3(boolean arg); + undefined overload4(TestInterface arg); + undefined overload4(TestCallbackInterface arg); + undefined overload4(DOMString arg); + undefined overload5(long arg); + undefined overload5(TestEnum arg); + undefined overload6(long arg); + undefined overload6(boolean arg); + undefined overload7(long arg); + undefined overload7(boolean arg); + undefined overload7(ByteString arg); + undefined overload8(long arg); + undefined overload8(TestInterface arg); + undefined overload9(long? arg); + undefined overload9(DOMString arg); + undefined overload10(long? arg); + undefined overload10(object arg); + undefined overload11(long arg); + undefined overload11(DOMString? arg); + undefined overload12(long arg); + undefined overload12(boolean? arg); + undefined overload13(long? arg); + undefined overload13(boolean arg); + undefined overload14(optional long arg); + undefined overload14(TestInterface arg); + undefined overload15(long arg); + undefined overload15(optional TestInterface arg); + undefined overload16(long arg); + undefined overload16(optional TestInterface? arg); + undefined overload17(sequence<long> arg); + undefined overload17(record<DOMString, long> arg); + undefined overload18(record<DOMString, DOMString> arg); + undefined overload18(sequence<DOMString> arg); + undefined overload19(sequence<long> arg); + undefined overload19(optional Dict arg = {}); + undefined overload20(optional Dict arg = {}); + undefined overload20(sequence<long> arg); + + // Variadic handling + undefined passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); + + // Conditionally exposed methods/attributes + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable1; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable2; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable3; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable4; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable5; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable6; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable7; + [Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable8; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable9; + [Pref="dom.webidl.test1"] + undefined prefable10(); + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable11(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable12; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable13(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable14; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable15; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable16; + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined prefable17(); + [Func="TestFuncControlledMember"] + undefined prefable18(); + [Func="TestFuncControlledMember"] + undefined prefable19(); + [Trial="TestTrial"] + undefined prefable20(); + [Trial="TestTrial"] + readonly attribute boolean prefable21; + [Trial="TestTrial", Func="TestFuncControlledMember"] + readonly attribute boolean prefable22; + + // Conditionally exposed methods/attributes involving [SecureContext] + [SecureContext] + readonly attribute boolean conditionalOnSecureContext1; + [SecureContext, Pref="dom.webidl.test1"] + readonly attribute boolean conditionalOnSecureContext2; + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean conditionalOnSecureContext3; + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean conditionalOnSecureContext4; + [SecureContext] + undefined conditionalOnSecureContext5(); + [SecureContext, Pref="dom.webidl.test1"] + undefined conditionalOnSecureContext6(); + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined conditionalOnSecureContext7(); + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined conditionalOnSecureContext8(); + [SecureContext, Trial="TestTrial"] + readonly attribute boolean conditionalOnSecureContext9; + [SecureContext, Trial="TestTrial"] + undefined conditionalOnSecureContext10(); + + // Miscellania + [LegacyLenientThis] attribute long attrWithLenientThis; + [LegacyUnforgeable] readonly attribute long unforgeableAttr; + [LegacyUnforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; + [LegacyUnforgeable] long unforgeableMethod(); + [LegacyUnforgeable, ChromeOnly] long unforgeableMethod2(); + stringifier; + undefined passRenamedInterface(TestRenamedInterface arg); + [PutForwards=writableByte] readonly attribute TestExampleInterface putForwardsAttr; + [PutForwards=writableByte, LegacyLenientThis] readonly attribute TestExampleInterface putForwardsAttr2; + [PutForwards=writableByte, ChromeOnly] readonly attribute TestExampleInterface putForwardsAttr3; + [Throws] undefined throwingMethod(); + [Throws] attribute boolean throwingAttr; + [GetterThrows] attribute boolean throwingGetterAttr; + [SetterThrows] attribute boolean throwingSetterAttr; + [CanOOM] undefined canOOMMethod(); + [CanOOM] attribute boolean canOOMAttr; + [GetterCanOOM] attribute boolean canOOMGetterAttr; + [SetterCanOOM] attribute boolean canOOMSetterAttr; + [NeedsSubjectPrincipal] undefined needsSubjectPrincipalMethod(); + [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; + [NeedsSubjectPrincipal=NonSystem] undefined needsNonSystemSubjectPrincipalMethod(); + [NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr; + [NeedsCallerType] undefined needsCallerTypeMethod(); + [NeedsCallerType] attribute boolean needsCallerTypeAttr; + [CEReactions] undefined ceReactionsMethod(); + [CEReactions] undefined ceReactionsMethodOverload(); + [CEReactions] undefined ceReactionsMethodOverload(DOMString bar); + [CEReactions] attribute boolean ceReactionsAttr; + legacycaller short(unsigned long arg1, TestInterface arg2); + undefined passArgsWithDefaults(optional long arg1, + optional TestInterface? arg2 = null, + optional Dict arg3 = {}, optional double arg4 = 5.0, + optional float arg5); + attribute any toJSONShouldSkipThis; + attribute TestParentInterface toJSONShouldSkipThis2; + attribute TestCallbackInterface toJSONShouldSkipThis3; + [Default] object toJSON(); + + attribute byte dashed-attribute; + undefined dashed-method(); + + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + undefined nonEnumerableMethod(); + + // [AllowShared] tests + attribute [AllowShared] ArrayBufferViewTypedef allowSharedArrayBufferViewTypedef; + attribute [AllowShared] ArrayBufferView allowSharedArrayBufferView; + attribute [AllowShared] ArrayBufferView? allowSharedNullableArrayBufferView; + attribute [AllowShared] ArrayBuffer allowSharedArrayBuffer; + attribute [AllowShared] ArrayBuffer? allowSharedNullableArrayBuffer; + + undefined passAllowSharedArrayBufferViewTypedef(AllowSharedArrayBufferViewTypedef foo); + undefined passAllowSharedArrayBufferView([AllowShared] ArrayBufferView foo); + undefined passAllowSharedNullableArrayBufferView([AllowShared] ArrayBufferView? foo); + undefined passAllowSharedArrayBuffer([AllowShared] ArrayBuffer foo); + undefined passAllowSharedNullableArrayBuffer([AllowShared] ArrayBuffer? foo); + undefined passUnionArrayBuffer((DOMString or ArrayBuffer) foo); + undefined passUnionAllowSharedArrayBuffer((DOMString or [AllowShared] ArrayBuffer) foo); + + // If you add things here, add them to TestCodeGen and TestJSImplGen as well +}; + +[Exposed=Window] +interface TestExampleProxyInterface { + getter long longIndexedGetter(unsigned long ix); + setter undefined longIndexedSetter(unsigned long y, long z); + readonly attribute unsigned long length; + stringifier DOMString myStringifier(); + getter short shortNameGetter(DOMString nom); + deleter undefined (DOMString nomnom); + setter undefined shortNamedSetter(DOMString me, short value); +}; + +[Exposed=(Window,Worker)] +interface TestExampleWorkerInterface { + [NeedsSubjectPrincipal] undefined needsSubjectPrincipalMethod(); + [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; + [NeedsCallerType] undefined needsCallerTypeMethod(); + [NeedsCallerType] attribute boolean needsCallerTypeAttr; + [NeedsSubjectPrincipal=NonSystem] undefined needsNonSystemSubjectPrincipalMethod(); + [NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr; +}; + +[Exposed=Window] +interface TestExampleThrowingConstructorInterface { + [Throws] + constructor(); + [Throws] + constructor(DOMString str); + [Throws] + constructor(unsigned long num, boolean? boolArg); + [Throws] + constructor(TestInterface? iface); + [Throws] + constructor(unsigned long arg1, TestInterface iface); + [Throws] + constructor(ArrayBuffer arrayBuf); + [Throws] + constructor(Uint8Array typedArr); + // [Throws] constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3); +}; diff --git a/dom/bindings/test/TestFunctions.cpp b/dom/bindings/test/TestFunctions.cpp new file mode 100644 index 0000000000..c50b408704 --- /dev/null +++ b/dom/bindings/test/TestFunctions.cpp @@ -0,0 +1,315 @@ +/* -*- 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/BindingUtils.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/TestFunctions.h" +#include "mozilla/dom/TestFunctionsBinding.h" +#include "mozilla/dom/WindowBinding.h" +#include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h" +#include "nsStringBuffer.h" +#include "mozITestInterfaceJS.h" +#include "nsComponentManagerUtils.h" +#include "nsGlobalWindowInner.h" + +namespace mozilla::dom { + +/* static */ +TestFunctions* TestFunctions::Constructor(GlobalObject& aGlobal) { + return new TestFunctions; +} + +/* static */ +void TestFunctions::ThrowUncatchableException(GlobalObject& aGlobal, + ErrorResult& aRv) { + aRv.ThrowUncatchableException(); +} + +/* static */ +Promise* TestFunctions::PassThroughPromise(GlobalObject& aGlobal, + Promise& aPromise) { + return &aPromise; +} + +/* static */ +already_AddRefed<Promise> TestFunctions::PassThroughCallbackPromise( + GlobalObject& aGlobal, PromiseReturner& aCallback, ErrorResult& aRv) { + return aCallback.Call(aRv); +} + +void TestFunctions::SetStringData(const nsAString& aString) { + mStringData = aString; +} + +void TestFunctions::GetStringDataAsAString(nsAString& aString) { + aString = mStringData; +} + +void TestFunctions::GetStringDataAsAString(uint32_t aLength, + nsAString& aString) { + MOZ_RELEASE_ASSERT(aLength <= mStringData.Length(), + "Bogus test passing in a too-big length"); + aString.Assign(mStringData.BeginReading(), aLength); +} + +void TestFunctions::GetStringDataAsDOMString(const Optional<uint32_t>& aLength, + DOMString& aString) { + uint32_t length; + if (aLength.WasPassed()) { + length = aLength.Value(); + MOZ_RELEASE_ASSERT(length <= mStringData.Length(), + "Bogus test passing in a too-big length"); + } else { + length = mStringData.Length(); + } + + nsStringBuffer* buf = nsStringBuffer::FromString(mStringData); + if (buf) { + aString.SetKnownLiveStringBuffer(buf, length); + return; + } + + // We better have an empty mStringData; otherwise why did we not have a string + // buffer? + MOZ_RELEASE_ASSERT(length == 0, "Why no stringbuffer?"); + // No need to do anything here; aString is already empty. +} + +void TestFunctions::GetShortLiteralString(nsAString& aString) { + // JS inline strings can hold 2 * sizeof(void*) chars, which on 32-bit means 8 + // chars. Return fewer than that. + aString.AssignLiteral(u"012345"); +} + +void TestFunctions::GetMediumLiteralString(nsAString& aString) { + // JS inline strings are at most 2 * sizeof(void*) chars, so at most 16 on + // 64-bit. FakeString can hold 63 chars in its inline buffer (plus the null + // terminator). Let's return 40 chars; that way if we ever move to 128-bit + // void* or something this test will still be valid. + aString.AssignLiteral(u"0123456789012345678901234567890123456789"); +} + +void TestFunctions::GetLongLiteralString(nsAString& aString) { + // Need more than 64 chars. + aString.AssignLiteral( + u"0123456789012345678901234567890123456789" // 40 + "0123456789012345678901234567890123456789" // 80 + ); +} + +void TestFunctions::GetStringbufferString(const nsAString& aInput, + nsAString& aRetval) { + // We have to be a bit careful: if aRetval is an autostring, if we just assign + // it won't cause stringbuffer allocation. So we have to round-trip through + // something that definitely causes a stringbuffer allocation. + nsString str; + // Can't use operator= here, because if aInput is a literal string then str + // would end up the same way. + str.Assign(aInput.BeginReading(), aInput.Length()); + + // Now we might end up hitting our external string cache and getting the wrong + // sort of external string, so replace the last char by a different value + // (replacing, not just appending, to preserve the length). If we have an + // empty string, our caller screwed up and there's not much we can do for + // them. + if (str.Length() > 1) { + char16_t last = str[str.Length() - 1]; + str.Truncate(str.Length() - 1); + if (last == 'x') { + str.Append('y'); + } else { + str.Append('x'); + } + } + + // Here we use operator= to preserve stringbufferness. + aRetval = str; +} + +StringType TestFunctions::GetStringType(const nsAString& aString) { + if (aString.IsLiteral()) { + return StringType::Literal; + } + + if (nsStringBuffer::FromString(aString)) { + return StringType::Stringbuffer; + } + + if (aString.GetDataFlags() & nsAString::DataFlags::INLINE) { + return StringType::Inline; + } + + return StringType::Other; +} + +bool TestFunctions::StringbufferMatchesStored(const nsAString& aString) { + return nsStringBuffer::FromString(aString) && + nsStringBuffer::FromString(aString) == + nsStringBuffer::FromString(mStringData); +} + +void TestFunctions::TestThrowNsresult(ErrorResult& aError) { + nsCOMPtr<mozITestInterfaceJS> impl = + do_CreateInstance("@mozilla.org/dom/test-interface-js;1"); + aError = impl->TestThrowNsresult(); +} + +void TestFunctions::TestThrowNsresultFromNative(ErrorResult& aError) { + nsCOMPtr<mozITestInterfaceJS> impl = + do_CreateInstance("@mozilla.org/dom/test-interface-js;1"); + aError = impl->TestThrowNsresultFromNative(); +} + +already_AddRefed<Promise> TestFunctions::ThrowToRejectPromise( + GlobalObject& aGlobal, ErrorResult& aError) { + aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; +} + +int32_t TestFunctions::One() const { return 1; } + +int32_t TestFunctions::Two() const { return 2; } + +void TestFunctions::SetClampedNullableOctet(const Nullable<uint8_t>& aOctet) { + mClampedNullableOctet = aOctet; +} + +Nullable<uint8_t> TestFunctions::GetClampedNullableOctet() const { + return mClampedNullableOctet; +} + +void TestFunctions::SetEnforcedNullableOctet(const Nullable<uint8_t>& aOctet) { + mEnforcedNullableOctet = aOctet; +} + +Nullable<uint8_t> TestFunctions::GetEnforcedNullableOctet() const { + return mEnforcedNullableOctet; +} + +void TestFunctions::SetArrayBufferView(const ArrayBufferView& aBuffer) {} + +void TestFunctions::GetArrayBufferView(JSContext* aCx, + JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetAllowSharedArrayBufferView( + const ArrayBufferView& aBuffer) {} + +void TestFunctions::GetAllowSharedArrayBufferView( + JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetSequenceOfArrayBufferView( + const Sequence<ArrayBufferView>& aBuffers) {} + +void TestFunctions::GetSequenceOfArrayBufferView(JSContext* aCx, + JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetSequenceOfAllowSharedArrayBufferView( + const Sequence<ArrayBufferView>& aBuffers) {} + +void TestFunctions::GetSequenceOfAllowSharedArrayBufferView( + JSContext* aCx, JS::Handle<JSObject*> aObj, nsTArray<JSObject*>& aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetArrayBuffer(const ArrayBuffer& aBuffer) {} + +void TestFunctions::GetArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetAllowSharedArrayBuffer(const ArrayBuffer& aBuffer) {} + +void TestFunctions::GetAllowSharedArrayBuffer( + JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetSequenceOfArrayBuffer( + const Sequence<ArrayBuffer>& aBuffers) {} + +void TestFunctions::GetSequenceOfArrayBuffer(JSContext* aCx, + JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::SetSequenceOfAllowSharedArrayBuffer( + const Sequence<ArrayBuffer>& aBuffers) {} + +void TestFunctions::GetSequenceOfAllowSharedArrayBuffer( + JSContext* aCx, JS::Handle<JSObject*> aObj, nsTArray<JSObject*>& aRetval, + ErrorResult& aError) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + +void TestFunctions::TestNotAllowShared(const ArrayBufferView& aBuffer) {} + +void TestFunctions::TestNotAllowShared(const ArrayBuffer& aBuffer) {} + +void TestFunctions::TestNotAllowShared(const nsAString& aBuffer) {} + +void TestFunctions::TestAllowShared(const ArrayBufferView& aBuffer) {} + +void TestFunctions::TestAllowShared(const ArrayBuffer& aBuffer) {} + +void TestFunctions::TestDictWithAllowShared( + const DictWithAllowSharedBufferSource& aDict) {} + +void TestFunctions::TestUnionOfBuffferSource( + const ArrayBufferOrArrayBufferViewOrString& aUnion) {} + +void TestFunctions::TestUnionOfAllowSharedBuffferSource( + const MaybeSharedArrayBufferOrMaybeSharedArrayBufferView& aUnion) {} + +bool TestFunctions::ObjectFromAboutBlank(JSContext* aCx, JSObject* aObj) { + // We purposefully don't use WindowOrNull here, because we want to + // demonstrate the incorrect behavior we get, not just fail some asserts. + RefPtr<nsGlobalWindowInner> win; + UNWRAP_MAYBE_CROSS_ORIGIN_OBJECT(Window, aObj, win, aCx); + if (!win) { + return false; + } + + Document* doc = win->GetDoc(); + if (!doc) { + return false; + } + + return doc->GetDocumentURI()->GetSpecOrDefault().EqualsLiteral("about:blank"); +} + +WrapperCachedNonISupportsTestInterface* +TestFunctions::WrapperCachedNonISupportsObject() { + if (!mWrapperCachedNonISupportsTestInterface) { + mWrapperCachedNonISupportsTestInterface = + new WrapperCachedNonISupportsTestInterface(); + } + return mWrapperCachedNonISupportsTestInterface; +} + +bool TestFunctions::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aWrapper) { + return TestFunctions_Binding::Wrap(aCx, this, aGivenProto, aWrapper); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestFunctions.h b/dom/bindings/test/TestFunctions.h new file mode 100644 index 0000000000..9030c454f8 --- /dev/null +++ b/dom/bindings/test/TestFunctions.h @@ -0,0 +1,132 @@ +/* -*- 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_TestFunctions_h +#define mozilla_dom_TestFunctions_h + +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/NonRefcountedDOMObject.h" +#include "mozilla/dom/TestFunctionsBinding.h" +#include "nsString.h" + +namespace mozilla { +namespace dom { + +class Promise; +class PromiseReturner; +class WrapperCachedNonISupportsTestInterface; + +class TestFunctions : public NonRefcountedDOMObject { + public: + static TestFunctions* Constructor(GlobalObject& aGlobal); + + static void ThrowUncatchableException(GlobalObject& aGlobal, + ErrorResult& aRv); + + static Promise* PassThroughPromise(GlobalObject& aGlobal, Promise& aPromise); + + MOZ_CAN_RUN_SCRIPT + static already_AddRefed<Promise> PassThroughCallbackPromise( + GlobalObject& aGlobal, PromiseReturner& aCallback, ErrorResult& aRv); + + void SetStringData(const nsAString& aString); + + void GetStringDataAsAString(nsAString& aString); + void GetStringDataAsAString(uint32_t aLength, nsAString& aString); + void GetStringDataAsDOMString(const Optional<uint32_t>& aLength, + DOMString& aString); + + void GetShortLiteralString(nsAString& aString); + void GetMediumLiteralString(nsAString& aString); + void GetLongLiteralString(nsAString& aString); + + void GetStringbufferString(const nsAString& aInput, nsAString& aRetval); + + StringType GetStringType(const nsAString& aString); + + bool StringbufferMatchesStored(const nsAString& aString); + + void TestThrowNsresult(ErrorResult& aError); + void TestThrowNsresultFromNative(ErrorResult& aError); + static already_AddRefed<Promise> ThrowToRejectPromise(GlobalObject& aGlobal, + ErrorResult& aError); + + int32_t One() const; + int32_t Two() const; + + void SetClampedNullableOctet(const Nullable<uint8_t>& aOctet); + Nullable<uint8_t> GetClampedNullableOctet() const; + void SetEnforcedNullableOctet(const Nullable<uint8_t>& aOctet); + Nullable<uint8_t> GetEnforcedNullableOctet() const; + + void SetArrayBufferView(const ArrayBufferView& aBuffer); + void GetArrayBufferView(JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError); + void SetAllowSharedArrayBufferView(const ArrayBufferView& aBuffer); + void GetAllowSharedArrayBufferView(JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError); + void SetSequenceOfArrayBufferView(const Sequence<ArrayBufferView>& aBuffers); + void GetSequenceOfArrayBufferView(JSContext* aCx, JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError); + void SetSequenceOfAllowSharedArrayBufferView( + const Sequence<ArrayBufferView>& aBuffers); + void GetSequenceOfAllowSharedArrayBufferView(JSContext* aCx, + JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError); + void SetArrayBuffer(const ArrayBuffer& aBuffer); + void GetArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError); + void SetAllowSharedArrayBuffer(const ArrayBuffer& aBuffer); + void GetAllowSharedArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObj, + JS::MutableHandle<JSObject*> aRetval, + ErrorResult& aError); + void SetSequenceOfArrayBuffer(const Sequence<ArrayBuffer>& aBuffers); + void GetSequenceOfArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError); + void SetSequenceOfAllowSharedArrayBuffer( + const Sequence<ArrayBuffer>& aBuffers); + void GetSequenceOfAllowSharedArrayBuffer(JSContext* aCx, + JS::Handle<JSObject*> aObj, + nsTArray<JSObject*>& aRetval, + ErrorResult& aError); + void TestNotAllowShared(const ArrayBufferView& aBuffer); + void TestNotAllowShared(const ArrayBuffer& aBuffer); + void TestNotAllowShared(const nsAString& aBuffer); + void TestAllowShared(const ArrayBufferView& aBuffer); + void TestAllowShared(const ArrayBuffer& aBuffer); + void TestDictWithAllowShared(const DictWithAllowSharedBufferSource& aDict); + void TestUnionOfBuffferSource( + const ArrayBufferOrArrayBufferViewOrString& aUnion); + void TestUnionOfAllowSharedBuffferSource( + const MaybeSharedArrayBufferOrMaybeSharedArrayBufferView& aUnion); + + static bool ObjectFromAboutBlank(JSContext* aCx, JSObject* aObj); + + WrapperCachedNonISupportsTestInterface* WrapperCachedNonISupportsObject(); + + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aWrapper); + + private: + nsString mStringData; + RefPtr<WrapperCachedNonISupportsTestInterface> + mWrapperCachedNonISupportsTestInterface; + + Nullable<uint8_t> mClampedNullableOctet; + Nullable<uint8_t> mEnforcedNullableOctet; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestFunctions_h diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp b/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp new file mode 100644 index 0000000000..a0ec0d64f0 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp @@ -0,0 +1,98 @@ +/* -*- 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/TestInterfaceAsyncIterableDouble.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceAsyncIterableDouble, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceAsyncIterableDouble) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceAsyncIterableDouble) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceAsyncIterableDouble) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceAsyncIterableDouble::TestInterfaceAsyncIterableDouble( + nsPIDOMWindowInner* aParent) + : mParent(aParent) { + mValues.AppendElement(std::pair<nsString, nsString>(u"a"_ns, u"b"_ns)); + mValues.AppendElement(std::pair<nsString, nsString>(u"c"_ns, u"d"_ns)); + mValues.AppendElement(std::pair<nsString, nsString>(u"e"_ns, u"f"_ns)); +} + +// static +already_AddRefed<TestInterfaceAsyncIterableDouble> +TestInterfaceAsyncIterableDouble::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceAsyncIterableDouble> r = + new TestInterfaceAsyncIterableDouble(window); + return r.forget(); +} + +JSObject* TestInterfaceAsyncIterableDouble::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceAsyncIterableDouble_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceAsyncIterableDouble::GetParentObject() const { + return mParent; +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableDouble::GetNextIterationResult(Iterator* aIterator, + ErrorResult& aRv) { + RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + NS_DispatchToMainThread(NewRunnableMethod<RefPtr<Iterator>, RefPtr<Promise>>( + "TestInterfaceAsyncIterableDouble::GetNextIterationResult", this, + &TestInterfaceAsyncIterableDouble::ResolvePromise, aIterator, promise)); + + return promise.forget(); +} + +void TestInterfaceAsyncIterableDouble::ResolvePromise(Iterator* aIterator, + Promise* aPromise) { + IteratorData& data = aIterator->Data(); + + // Test data: ['a', 'b'], ['c', 'd'], ['e', 'f'] + uint32_t idx = data.mIndex; + if (idx >= mValues.Length()) { + iterator_utils::ResolvePromiseForFinished(aPromise); + } else { + switch (aIterator->GetIteratorType()) { + case IterableIteratorBase::IteratorType::Keys: + aPromise->MaybeResolve(mValues[idx].first); + break; + case IterableIteratorBase::IteratorType::Values: + aPromise->MaybeResolve(mValues[idx].second); + break; + case IterableIteratorBase::IteratorType::Entries: + iterator_utils::ResolvePromiseWithKeyAndValue( + aPromise, mValues[idx].first, mValues[idx].second); + break; + } + + data.mIndex++; + } +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDouble.h b/dom/bindings/test/TestInterfaceAsyncIterableDouble.h new file mode 100644 index 0000000000..4b458617dc --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableDouble.h @@ -0,0 +1,64 @@ +/* -*- 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_TestInterfaceAsyncIterableDouble_h +#define mozilla_dom_TestInterfaceAsyncIterableDouble_h + +#include "IterableIterator.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsWrapperCache.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceAsyncIterableDouble final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceAsyncIterableDouble) + + explicit TestInterfaceAsyncIterableDouble(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceAsyncIterableDouble> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + struct IteratorData { + uint32_t mIndex = 0; + }; + + using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableDouble>; + + void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, + ErrorResult& aError) {} + + already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, + ErrorResult& aRv); + + private: + virtual ~TestInterfaceAsyncIterableDouble() = default; + void ResolvePromise(Iterator* aIterator, Promise* aPromise); + + nsCOMPtr<nsPIDOMWindowInner> mParent; + nsTArray<std::pair<nsString, nsString>> mValues; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceAsyncIterableDouble_h diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp new file mode 100644 index 0000000000..300574d7d7 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp @@ -0,0 +1,106 @@ +/* -*- 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/TestInterfaceAsyncIterableDoubleUnion.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceAsyncIterableDoubleUnion, + mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceAsyncIterableDoubleUnion) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceAsyncIterableDoubleUnion) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceAsyncIterableDoubleUnion) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceAsyncIterableDoubleUnion::TestInterfaceAsyncIterableDoubleUnion( + nsPIDOMWindowInner* aParent) + : mParent(aParent) { + OwningStringOrLong a; + a.SetAsLong() = 1; + mValues.AppendElement(std::pair<nsString, OwningStringOrLong>(u"long"_ns, a)); + a.SetAsString() = u"a"_ns; + mValues.AppendElement( + std::pair<nsString, OwningStringOrLong>(u"string"_ns, a)); +} + +// static +already_AddRefed<TestInterfaceAsyncIterableDoubleUnion> +TestInterfaceAsyncIterableDoubleUnion::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceAsyncIterableDoubleUnion> r = + new TestInterfaceAsyncIterableDoubleUnion(window); + return r.forget(); +} + +JSObject* TestInterfaceAsyncIterableDoubleUnion::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceAsyncIterableDoubleUnion_Binding::Wrap(aCx, this, + aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceAsyncIterableDoubleUnion::GetParentObject() + const { + return mParent; +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableDoubleUnion::GetNextIterationResult( + Iterator* aIterator, ErrorResult& aRv) { + RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + NS_DispatchToMainThread(NewRunnableMethod<RefPtr<Iterator>, RefPtr<Promise>>( + "TestInterfaceAsyncIterableDoubleUnion::GetNextIterationResult", this, + &TestInterfaceAsyncIterableDoubleUnion::ResolvePromise, aIterator, + promise)); + + return promise.forget(); +} + +void TestInterfaceAsyncIterableDoubleUnion::ResolvePromise(Iterator* aIterator, + Promise* aPromise) { + IteratorData& data = aIterator->Data(); + + // Test data: + // [long, 1], [string, "a"] + uint32_t idx = data.mIndex; + if (idx >= mValues.Length()) { + iterator_utils::ResolvePromiseForFinished(aPromise); + } else { + switch (aIterator->GetIteratorType()) { + case IterableIteratorBase::IteratorType::Keys: + aPromise->MaybeResolve(mValues[idx].first); + break; + case IterableIteratorBase::IteratorType::Values: + aPromise->MaybeResolve(mValues[idx].second); + break; + case IterableIteratorBase::IteratorType::Entries: + iterator_utils::ResolvePromiseWithKeyAndValue( + aPromise, mValues[idx].first, mValues[idx].second); + break; + } + + data.mIndex++; + } +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h new file mode 100644 index 0000000000..902c99b1a9 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h @@ -0,0 +1,64 @@ +/* -*- 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_TestInterfaceAsyncIterableDoubleUnion_h +#define mozilla_dom_TestInterfaceAsyncIterableDoubleUnion_h + +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "IterableIterator.h" +#include "nsCOMPtr.h" +#include "nsWrapperCache.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceAsyncIterableDoubleUnion final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS( + TestInterfaceAsyncIterableDoubleUnion) + + explicit TestInterfaceAsyncIterableDoubleUnion(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceAsyncIterableDoubleUnion> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + struct IteratorData { + uint32_t mIndex = 0; + }; + + using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableDoubleUnion>; + + void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, + ErrorResult& aError) {} + + already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, + ErrorResult& aRv); + + private: + virtual ~TestInterfaceAsyncIterableDoubleUnion() = default; + void ResolvePromise(Iterator* aIterator, Promise* aPromise); + + nsCOMPtr<nsPIDOMWindowInner> mParent; + nsTArray<std::pair<nsString, OwningStringOrLong>> mValues; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceAsyncIterableDoubleUnion_h diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp b/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp new file mode 100644 index 0000000000..f8d049b840 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp @@ -0,0 +1,130 @@ +/* -*- 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/TestInterfaceAsyncIterableSingle.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/IterableIterator.h" +#include "mozilla/dom/Promise-inl.h" +#include "nsThreadUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceAsyncIterableSingle, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceAsyncIterableSingle) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceAsyncIterableSingle) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceAsyncIterableSingle) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceAsyncIterableSingle::TestInterfaceAsyncIterableSingle( + nsPIDOMWindowInner* aParent, bool aFailToInit) + : mParent(aParent), mFailToInit(aFailToInit) {} + +// static +already_AddRefed<TestInterfaceAsyncIterableSingle> +TestInterfaceAsyncIterableSingle::Constructor( + const GlobalObject& aGlobal, + const TestInterfaceAsyncIterableSingleOptions& aOptions, ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceAsyncIterableSingle> r = + new TestInterfaceAsyncIterableSingle(window, aOptions.mFailToInit); + return r.forget(); +} + +JSObject* TestInterfaceAsyncIterableSingle::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceAsyncIterableSingle_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceAsyncIterableSingle::GetParentObject() const { + return mParent; +} + +void TestInterfaceAsyncIterableSingle::InitAsyncIteratorData( + IteratorData& aData, Iterator::IteratorType aType, ErrorResult& aError) { + if (mFailToInit) { + aError.ThrowTypeError("Caller asked us to fail"); + return; + } + + // Nothing else to do. + MOZ_ASSERT(aData.mIndex == 0); + MOZ_ASSERT(aData.mMultiplier == 1); +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableSingle::GetNextIterationResult(Iterator* aIterator, + ErrorResult& aRv) { + return GetNextIterationResult(aIterator, aIterator->Data(), aRv); +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableSingle::GetNextIterationResult( + IterableIteratorBase* aIterator, IteratorData& aData, ErrorResult& aRv) { + RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsCOMPtr<nsIRunnable> callResolvePromise = + NewRunnableMethod<RefPtr<IterableIteratorBase>, IteratorData&, + RefPtr<Promise>>( + "TestInterfaceAsyncIterableSingle::GetNextIterationResult", this, + &TestInterfaceAsyncIterableSingle::ResolvePromise, aIterator, aData, + promise); + if (aData.mBlockingPromisesIndex < aData.mBlockingPromises.Length()) { + aData.mBlockingPromises[aData.mBlockingPromisesIndex] + ->AddCallbacksWithCycleCollectedArgs( + [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, + nsIRunnable* aCallResolvePromise) { + NS_DispatchToMainThread(aCallResolvePromise); + }, + [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, + nsIRunnable* aCallResolvePromise) {}, + std::move(callResolvePromise)); + ++aData.mBlockingPromisesIndex; + } else { + NS_DispatchToMainThread(callResolvePromise); + } + + return promise.forget(); +} + +void TestInterfaceAsyncIterableSingle::ResolvePromise( + IterableIteratorBase* aIterator, IteratorData& aData, Promise* aPromise) { + if (aData.mIndex >= 10) { + iterator_utils::ResolvePromiseForFinished(aPromise); + } else { + aPromise->MaybeResolve(int32_t(aData.mIndex * 9 % 7 * aData.mMultiplier)); + + aData.mIndex++; + } +} + +void TestInterfaceAsyncIterableSingle::IteratorData::Traverse( + nsCycleCollectionTraversalCallback& cb) { + TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBlockingPromises); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mThrowFromReturn); +} +void TestInterfaceAsyncIterableSingle::IteratorData::Unlink() { + TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; + NS_IMPL_CYCLE_COLLECTION_UNLINK(mBlockingPromises); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mThrowFromReturn); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingle.h b/dom/bindings/test/TestInterfaceAsyncIterableSingle.h new file mode 100644 index 0000000000..c92b35cc7b --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingle.h @@ -0,0 +1,81 @@ +/* -*- 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_TestInterfaceAsyncIterableSingle_h +#define mozilla_dom_TestInterfaceAsyncIterableSingle_h + +#include "IterableIterator.h" +#include "nsCOMPtr.h" +#include "nsWrapperCache.h" +#include "nsTArray.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; +struct TestInterfaceAsyncIterableSingleOptions; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceAsyncIterableSingle : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceAsyncIterableSingle) + + explicit TestInterfaceAsyncIterableSingle(nsPIDOMWindowInner* aParent, + bool aFailToInit = false); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceAsyncIterableSingle> Constructor( + const GlobalObject& aGlobal, + const TestInterfaceAsyncIterableSingleOptions& aOptions, ErrorResult& rv); + + using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableSingle>; + already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, + ErrorResult& aRv); + + struct IteratorData { + void Traverse(nsCycleCollectionTraversalCallback& cb); + void Unlink(); + + uint32_t mIndex = 0; + uint32_t mMultiplier = 1; + Sequence<OwningNonNull<Promise>> mBlockingPromises; + size_t mBlockingPromisesIndex = 0; + uint32_t mFailNextAfter = 4294967295; + bool mThrowFromNext = false; + RefPtr<TestThrowingCallback> mThrowFromReturn; + }; + + void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, + ErrorResult& aError); + + protected: + already_AddRefed<Promise> GetNextIterationResult( + IterableIteratorBase* aIterator, IteratorData& aData, ErrorResult& aRv); + + virtual ~TestInterfaceAsyncIterableSingle() = default; + + private: + void ResolvePromise(IterableIteratorBase* aIterator, IteratorData& aData, + Promise* aPromise); + + nsCOMPtr<nsPIDOMWindowInner> mParent; + bool mFailToInit; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceAsyncIterableSingle_h diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp new file mode 100644 index 0000000000..6c02829186 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp @@ -0,0 +1,118 @@ +/* -*- 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/TestInterfaceAsyncIterableSingleWithArgs.h" +#include "ScriptSettings.h" +#include "js/Value.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/IterableIterator.h" +#include "mozilla/dom/Promise-inl.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_CLASS(TestInterfaceAsyncIterableSingleWithArgs) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED( + TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED( + TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED( + TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mReturnLastCalledWith) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_ADDREF_INHERITED(TestInterfaceAsyncIterableSingleWithArgs, + TestInterfaceAsyncIterableSingle) +NS_IMPL_RELEASE_INHERITED(TestInterfaceAsyncIterableSingleWithArgs, + TestInterfaceAsyncIterableSingle) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( + TestInterfaceAsyncIterableSingleWithArgs) +NS_INTERFACE_MAP_END_INHERITING(TestInterfaceAsyncIterableSingle) + +// static +already_AddRefed<TestInterfaceAsyncIterableSingleWithArgs> +TestInterfaceAsyncIterableSingleWithArgs::Constructor( + const GlobalObject& aGlobal, ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceAsyncIterableSingleWithArgs> r = + new TestInterfaceAsyncIterableSingleWithArgs(window); + return r.forget(); +} + +JSObject* TestInterfaceAsyncIterableSingleWithArgs::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceAsyncIterableSingleWithArgs_Binding::Wrap(aCx, this, + aGivenProto); +} + +void TestInterfaceAsyncIterableSingleWithArgs::InitAsyncIteratorData( + IteratorData& aData, Iterator::IteratorType aType, + const TestInterfaceAsyncIteratorOptions& aOptions, ErrorResult& aError) { + aData.mMultiplier = aOptions.mMultiplier; + aData.mBlockingPromises = aOptions.mBlockingPromises; + aData.mFailNextAfter = aOptions.mFailNextAfter; + aData.mThrowFromNext = aOptions.mThrowFromNext; + if (aOptions.mThrowFromReturn.WasPassed()) { + aData.mThrowFromReturn = &aOptions.mThrowFromReturn.Value(); + } +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableSingleWithArgs::GetNextIterationResult( + Iterator* aIterator, ErrorResult& aRv) { + if (aIterator->Data().mThrowFromNext) { + AutoJSAPI jsapi; + MOZ_RELEASE_ASSERT(jsapi.Init(GetParentObject())); + JS_ReportErrorASCII(jsapi.cx(), "Throwing from next()."); + aRv.MightThrowJSException(); + aRv.StealExceptionFromJSContext(jsapi.cx()); + return nullptr; + } + + if (aIterator->Data().mIndex == aIterator->Data().mFailNextAfter) { + aRv.ThrowTypeError("Failed because we of 'failNextAfter'."); + return nullptr; + } + return TestInterfaceAsyncIterableSingle::GetNextIterationResult( + aIterator, aIterator->Data(), aRv); +} + +already_AddRefed<Promise> +TestInterfaceAsyncIterableSingleWithArgs::IteratorReturn( + JSContext* aCx, Iterator* aIterator, JS::Handle<JS::Value> aValue, + ErrorResult& aRv) { + ++mReturnCallCount; + + if (RefPtr<TestThrowingCallback> throwFromReturn = + aIterator->Data().mThrowFromReturn) { + throwFromReturn->Call(aRv, nullptr, CallbackFunction::eRethrowExceptions); + return nullptr; + } + + RefPtr<Promise> promise = Promise::Create(GetParentObject()->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + mReturnLastCalledWith = aValue; + promise->MaybeResolve(JS::UndefinedHandleValue); + return promise.forget(); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h new file mode 100644 index 0000000000..b9ef4853b8 --- /dev/null +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h @@ -0,0 +1,60 @@ +/* -*- 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_TestInterfaceAsyncIterableSingleWithArgs_h +#define mozilla_dom_TestInterfaceAsyncIterableSingleWithArgs_h + +#include "mozilla/dom/TestInterfaceAsyncIterableSingle.h" + +namespace mozilla::dom { + +struct TestInterfaceAsyncIteratorOptions; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceAsyncIterableSingleWithArgs final + : public TestInterfaceAsyncIterableSingle { + public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( + TestInterfaceAsyncIterableSingleWithArgs, + TestInterfaceAsyncIterableSingle) + + using TestInterfaceAsyncIterableSingle::TestInterfaceAsyncIterableSingle; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceAsyncIterableSingleWithArgs> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + using Iterator = + AsyncIterableIterator<TestInterfaceAsyncIterableSingleWithArgs>; + + void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, + const TestInterfaceAsyncIteratorOptions& aOptions, + ErrorResult& aError); + + already_AddRefed<Promise> GetNextIterationResult( + Iterator* aIterator, ErrorResult& aRv) MOZ_CAN_RUN_SCRIPT; + already_AddRefed<Promise> IteratorReturn(JSContext* aCx, Iterator* aIterator, + JS::Handle<JS::Value> aValue, + ErrorResult& aRv) MOZ_CAN_RUN_SCRIPT; + + uint32_t ReturnCallCount() { return mReturnCallCount; } + void GetReturnLastCalledWith(JSContext* aCx, + JS::MutableHandle<JS::Value> aReturnCalledWith) { + aReturnCalledWith.set(mReturnLastCalledWith); + } + + private: + ~TestInterfaceAsyncIterableSingleWithArgs() = default; + + JS::Heap<JS::Value> mReturnLastCalledWith; + uint32_t mReturnCallCount = 0; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_TestInterfaceAsyncIterableSingleWithArgs_h diff --git a/dom/bindings/test/TestInterfaceIterableDouble.cpp b/dom/bindings/test/TestInterfaceIterableDouble.cpp new file mode 100644 index 0000000000..8882518399 --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableDouble.cpp @@ -0,0 +1,71 @@ +/* -*- 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/TestInterfaceIterableDouble.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableDouble, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableDouble) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableDouble) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableDouble) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceIterableDouble::TestInterfaceIterableDouble( + nsPIDOMWindowInner* aParent) + : mParent(aParent) { + mValues.AppendElement(std::pair<nsString, nsString>(u"a"_ns, u"b"_ns)); + mValues.AppendElement(std::pair<nsString, nsString>(u"c"_ns, u"d"_ns)); + mValues.AppendElement(std::pair<nsString, nsString>(u"e"_ns, u"f"_ns)); +} + +// static +already_AddRefed<TestInterfaceIterableDouble> +TestInterfaceIterableDouble::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceIterableDouble> r = + new TestInterfaceIterableDouble(window); + return r.forget(); +} + +JSObject* TestInterfaceIterableDouble::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceIterableDouble_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceIterableDouble::GetParentObject() const { + return mParent; +} + +size_t TestInterfaceIterableDouble::GetIterableLength() { + return mValues.Length(); +} + +nsAString& TestInterfaceIterableDouble::GetKeyAtIndex(uint32_t aIndex) { + MOZ_ASSERT(aIndex < mValues.Length()); + return mValues.ElementAt(aIndex).first; +} + +nsAString& TestInterfaceIterableDouble::GetValueAtIndex(uint32_t aIndex) { + MOZ_ASSERT(aIndex < mValues.Length()); + return mValues.ElementAt(aIndex).second; +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceIterableDouble.h b/dom/bindings/test/TestInterfaceIterableDouble.h new file mode 100644 index 0000000000..ba38b47e89 --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableDouble.h @@ -0,0 +1,53 @@ +/* -*- 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_TestInterfaceIterableDouble_h +#define mozilla_dom_TestInterfaceIterableDouble_h + +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsWrapperCache.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceIterableDouble final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceIterableDouble) + + explicit TestInterfaceIterableDouble(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceIterableDouble> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + size_t GetIterableLength(); + nsAString& GetKeyAtIndex(uint32_t aIndex); + nsAString& GetValueAtIndex(uint32_t aIndex); + + private: + virtual ~TestInterfaceIterableDouble() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; + nsTArray<std::pair<nsString, nsString>> mValues; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceIterableDouble_h diff --git a/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp b/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp new file mode 100644 index 0000000000..a83641a1ee --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableDoubleUnion.cpp @@ -0,0 +1,75 @@ +/* -*- 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/TestInterfaceIterableDoubleUnion.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableDoubleUnion, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableDoubleUnion) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableDoubleUnion) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableDoubleUnion) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceIterableDoubleUnion::TestInterfaceIterableDoubleUnion( + nsPIDOMWindowInner* aParent) + : mParent(aParent) { + OwningStringOrLong a; + a.SetAsLong() = 1; + mValues.AppendElement(std::pair<nsString, OwningStringOrLong>(u"long"_ns, a)); + a.SetAsString() = u"a"_ns; + mValues.AppendElement( + std::pair<nsString, OwningStringOrLong>(u"string"_ns, a)); +} + +// static +already_AddRefed<TestInterfaceIterableDoubleUnion> +TestInterfaceIterableDoubleUnion::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceIterableDoubleUnion> r = + new TestInterfaceIterableDoubleUnion(window); + return r.forget(); +} + +JSObject* TestInterfaceIterableDoubleUnion::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceIterableDoubleUnion_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceIterableDoubleUnion::GetParentObject() const { + return mParent; +} + +size_t TestInterfaceIterableDoubleUnion::GetIterableLength() { + return mValues.Length(); +} + +nsAString& TestInterfaceIterableDoubleUnion::GetKeyAtIndex(uint32_t aIndex) { + MOZ_ASSERT(aIndex < mValues.Length()); + return mValues.ElementAt(aIndex).first; +} + +OwningStringOrLong& TestInterfaceIterableDoubleUnion::GetValueAtIndex( + uint32_t aIndex) { + MOZ_ASSERT(aIndex < mValues.Length()); + return mValues.ElementAt(aIndex).second; +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceIterableDoubleUnion.h b/dom/bindings/test/TestInterfaceIterableDoubleUnion.h new file mode 100644 index 0000000000..d35744922e --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableDoubleUnion.h @@ -0,0 +1,52 @@ +/* -*- 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_TestInterfaceIterableDoubleUnion_h +#define mozilla_dom_TestInterfaceIterableDoubleUnion_h + +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsCOMPtr.h" +#include "nsWrapperCache.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceIterableDoubleUnion final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceIterableDoubleUnion) + + explicit TestInterfaceIterableDoubleUnion(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceIterableDoubleUnion> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + size_t GetIterableLength(); + nsAString& GetKeyAtIndex(uint32_t aIndex); + OwningStringOrLong& GetValueAtIndex(uint32_t aIndex); + + private: + virtual ~TestInterfaceIterableDoubleUnion() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; + nsTArray<std::pair<nsString, OwningStringOrLong>> mValues; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceIterableDoubleUnion_h diff --git a/dom/bindings/test/TestInterfaceIterableSingle.cpp b/dom/bindings/test/TestInterfaceIterableSingle.cpp new file mode 100644 index 0000000000..4da02e9093 --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableSingle.cpp @@ -0,0 +1,72 @@ +/* -*- 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/TestInterfaceIterableSingle.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableSingle, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableSingle) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableSingle) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableSingle) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceIterableSingle::TestInterfaceIterableSingle( + nsPIDOMWindowInner* aParent) + : mParent(aParent) { + for (int i = 0; i < 3; ++i) { + mValues.AppendElement(i); + } +} + +// static +already_AddRefed<TestInterfaceIterableSingle> +TestInterfaceIterableSingle::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceIterableSingle> r = + new TestInterfaceIterableSingle(window); + return r.forget(); +} + +JSObject* TestInterfaceIterableSingle::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceIterableSingle_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceIterableSingle::GetParentObject() const { + return mParent; +} + +uint32_t TestInterfaceIterableSingle::Length() const { + return mValues.Length(); +} + +int32_t TestInterfaceIterableSingle::IndexedGetter(uint32_t aIndex, + bool& aFound) const { + if (aIndex >= mValues.Length()) { + aFound = false; + return 0; + } + + aFound = true; + return mValues[aIndex]; +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceIterableSingle.h b/dom/bindings/test/TestInterfaceIterableSingle.h new file mode 100644 index 0000000000..68104d1d15 --- /dev/null +++ b/dom/bindings/test/TestInterfaceIterableSingle.h @@ -0,0 +1,51 @@ +/* -*- 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_TestInterfaceIterableSingle_h +#define mozilla_dom_TestInterfaceIterableSingle_h + +#include "nsCOMPtr.h" +#include "nsWrapperCache.h" +#include "nsTArray.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl iterable interfaces, using +// primitives for value type +class TestInterfaceIterableSingle final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceIterableSingle) + + explicit TestInterfaceIterableSingle(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceIterableSingle> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + uint32_t Length() const; + int32_t IndexedGetter(uint32_t aIndex, bool& aFound) const; + + private: + virtual ~TestInterfaceIterableSingle() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; + nsTArray<int32_t> mValues; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceIterableSingle_h diff --git a/dom/bindings/test/TestInterfaceJS.sys.mjs b/dom/bindings/test/TestInterfaceJS.sys.mjs new file mode 100644 index 0000000000..01dcbe96cf --- /dev/null +++ b/dom/bindings/test/TestInterfaceJS.sys.mjs @@ -0,0 +1,220 @@ +/* -*- 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/. */ +/* global noSuchMethodExistsYo1, noSuchMethodExistsYo2, noSuchMethodExistsYo3 */ + +export function TestInterfaceJS() {} + +TestInterfaceJS.prototype = { + QueryInterface: ChromeUtils.generateQI([ + "nsIDOMGlobalPropertyInitializer", + "mozITestInterfaceJS", + ]), + + init(win) { + this._win = win; + }, + + __init(anyArg, objectArg, dictionaryArg) { + this._anyAttr = undefined; + this._objectAttr = null; + this._anyArg = anyArg; + this._objectArg = objectArg; + this._dictionaryArg = dictionaryArg; + }, + + get anyArg() { + return this._anyArg; + }, + get objectArg() { + return this._objectArg; + }, + getDictionaryArg() { + return this._dictionaryArg; + }, + get anyAttr() { + return this._anyAttr; + }, + set anyAttr(val) { + this._anyAttr = val; + }, + get objectAttr() { + return this._objectAttr; + }, + set objectAttr(val) { + this._objectAttr = val; + }, + getDictionaryAttr() { + return this._dictionaryAttr; + }, + setDictionaryAttr(val) { + this._dictionaryAttr = val; + }, + pingPongAny(any) { + return any; + }, + pingPongObject(obj) { + return obj; + }, + pingPongObjectOrString(objectOrString) { + return objectOrString; + }, + pingPongDictionary(dict) { + return dict; + }, + pingPongDictionaryOrLong(dictOrLong) { + return dictOrLong.anyMember || dictOrLong; + }, + pingPongRecord(rec) { + return JSON.stringify(rec); + }, + objectSequenceLength(seq) { + return seq.length; + }, + anySequenceLength(seq) { + return seq.length; + }, + + getCallerPrincipal() { + return Cu.getWebIDLCallerPrincipal().origin; + }, + + convertSVS(svs) { + return svs; + }, + + pingPongUnion(x) { + return x; + }, + pingPongUnionContainingNull(x) { + return x; + }, + pingPongNullableUnion(x) { + return x; + }, + returnBadUnion(x) { + return 3; + }, + + testSequenceOverload(arg) {}, + testSequenceUnion(arg) {}, + + testThrowError() { + throw new this._win.Error("We are an Error"); + }, + + testThrowDOMException() { + throw new this._win.DOMException( + "We are a DOMException", + "NotSupportedError" + ); + }, + + testThrowTypeError() { + throw new this._win.TypeError("We are a TypeError"); + }, + + testThrowNsresult() { + // This is explicitly testing preservation of raw thrown Crs in XPCJS + // eslint-disable-next-line mozilla/no-throw-cr-literal + throw Cr.NS_BINDING_ABORTED; + }, + + testThrowNsresultFromNative(x) { + // We want to throw an exception that we generate from an nsresult thrown + // by a C++ component. + Services.io.notImplemented(); + }, + + testThrowCallbackError(callback) { + callback(); + }, + + testThrowXraySelfHosted() { + this._win.Array.prototype.forEach(); + }, + + testThrowSelfHosted() { + Array.prototype.forEach(); + }, + + testPromiseWithThrowingChromePromiseInit() { + return new this._win.Promise(function() { + noSuchMethodExistsYo1(); + }); + }, + + testPromiseWithThrowingContentPromiseInit(func) { + return new this._win.Promise(func); + }, + + testPromiseWithDOMExceptionThrowingPromiseInit() { + return new this._win.Promise(() => { + throw new this._win.DOMException( + "We are a second DOMException", + "NotFoundError" + ); + }); + }, + + testPromiseWithThrowingChromeThenFunction() { + return this._win.Promise.resolve(5).then(function() { + noSuchMethodExistsYo2(); + }); + }, + + testPromiseWithThrowingContentThenFunction(func) { + return this._win.Promise.resolve(10).then(func); + }, + + testPromiseWithDOMExceptionThrowingThenFunction() { + return this._win.Promise.resolve(5).then(() => { + throw new this._win.DOMException( + "We are a third DOMException", + "NetworkError" + ); + }); + }, + + testPromiseWithThrowingChromeThenable() { + var thenable = { + then() { + noSuchMethodExistsYo3(); + }, + }; + return new this._win.Promise(function(resolve) { + resolve(thenable); + }); + }, + + testPromiseWithThrowingContentThenable(thenable) { + // Waive Xrays on the thenable, because we're calling resolve() in the + // chrome compartment, so that's the compartment the "then" property get + // will happen in, and if we leave the Xray in place the function-valued + // property won't return the function. + return this._win.Promise.resolve(Cu.waiveXrays(thenable)); + }, + + testPromiseWithDOMExceptionThrowingThenable() { + var thenable = { + then: () => { + throw new this._win.DOMException( + "We are a fourth DOMException", + "TypeMismatchError" + ); + }, + }; + return new this._win.Promise(function(resolve) { + resolve(thenable); + }); + }, + + get onsomething() { + return this.__DOM_IMPL__.getEventHandler("onsomething"); + }, + + set onsomething(val) { + this.__DOM_IMPL__.setEventHandler("onsomething", val); + }, +}; diff --git a/dom/bindings/test/TestInterfaceLength.cpp b/dom/bindings/test/TestInterfaceLength.cpp new file mode 100644 index 0000000000..cbb2ffa5c6 --- /dev/null +++ b/dom/bindings/test/TestInterfaceLength.cpp @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/TestInterfaceLength.h" +#include "mozilla/dom/TestFunctionsBinding.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(TestInterfaceLength) + +JSObject* TestInterfaceLength::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceLength_Binding::Wrap(aCx, this, aGivenProto); +} + +already_AddRefed<TestInterfaceLength> TestInterfaceLength::Constructor( + const GlobalObject& aGlobalObject, const bool aArg) { + return MakeAndAddRef<TestInterfaceLength>(); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceLength.h b/dom/bindings/test/TestInterfaceLength.h new file mode 100644 index 0000000000..989333bbf0 --- /dev/null +++ b/dom/bindings/test/TestInterfaceLength.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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_TestInterfaceLength_h +#define mozilla_dom_TestInterfaceLength_h + +#include "js/TypeDecls.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" + +namespace mozilla::dom { + +class TestInterfaceLength final : public nsWrapperCache { + public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TestInterfaceLength) + NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(TestInterfaceLength) + + public: + TestInterfaceLength() = default; + + static already_AddRefed<TestInterfaceLength> Constructor( + const GlobalObject& aGlobalObject, const bool aArg); + + protected: + ~TestInterfaceLength() = default; + + public: + nsISupports* GetParentObject() const { return nullptr; } + JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_TestInterfaceLength_h diff --git a/dom/bindings/test/TestInterfaceMaplike.cpp b/dom/bindings/test/TestInterfaceMaplike.cpp new file mode 100644 index 0000000000..ba8ccf7279 --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplike.cpp @@ -0,0 +1,74 @@ +/* -*- 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/TestInterfaceMaplike.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplike, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplike) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplike) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplike) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceMaplike::TestInterfaceMaplike(nsPIDOMWindowInner* aParent) + : mParent(aParent) {} + +// static +already_AddRefed<TestInterfaceMaplike> TestInterfaceMaplike::Constructor( + const GlobalObject& aGlobal, ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceMaplike> r = new TestInterfaceMaplike(window); + return r.forget(); +} + +JSObject* TestInterfaceMaplike::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceMaplike_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceMaplike::GetParentObject() const { + return mParent; +} + +void TestInterfaceMaplike::SetInternal(const nsAString& aKey, int32_t aValue) { + ErrorResult rv; + TestInterfaceMaplike_Binding::MaplikeHelpers::Set(this, aKey, aValue, rv); +} + +void TestInterfaceMaplike::ClearInternal() { + ErrorResult rv; + TestInterfaceMaplike_Binding::MaplikeHelpers::Clear(this, rv); +} + +bool TestInterfaceMaplike::DeleteInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplike_Binding::MaplikeHelpers::Delete(this, aKey, rv); +} + +bool TestInterfaceMaplike::HasInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplike_Binding::MaplikeHelpers::Has(this, aKey, rv); +} + +int32_t TestInterfaceMaplike::GetInternal(const nsAString& aKey, + ErrorResult& aRv) { + return TestInterfaceMaplike_Binding::MaplikeHelpers::Get(this, aKey, aRv); +} +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceMaplike.h b/dom/bindings/test/TestInterfaceMaplike.h new file mode 100644 index 0000000000..e82f290d17 --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplike.h @@ -0,0 +1,52 @@ +/* -*- 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_TestInterfaceMaplike_h +#define mozilla_dom_TestInterfaceMaplike_h + +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl maplike interfaces, using +// primitives for key and value types. +class TestInterfaceMaplike final : public nsISupports, public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceMaplike) + + explicit TestInterfaceMaplike(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceMaplike> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + // External access for testing internal convenience functions. + void SetInternal(const nsAString& aKey, int32_t aValue); + void ClearInternal(); + bool DeleteInternal(const nsAString& aKey); + bool HasInternal(const nsAString& aKey); + int32_t GetInternal(const nsAString& aKey, ErrorResult& aRv); + + private: + virtual ~TestInterfaceMaplike() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceMaplike_h diff --git a/dom/bindings/test/TestInterfaceMaplikeJSObject.cpp b/dom/bindings/test/TestInterfaceMaplikeJSObject.cpp new file mode 100644 index 0000000000..e9fb50e4b6 --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplikeJSObject.cpp @@ -0,0 +1,85 @@ +/* -*- 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/TestInterfaceMaplikeJSObject.h" +#include "mozilla/dom/TestInterfaceMaplike.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplikeJSObject, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplikeJSObject) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplikeJSObject) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplikeJSObject) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceMaplikeJSObject::TestInterfaceMaplikeJSObject( + nsPIDOMWindowInner* aParent) + : mParent(aParent) {} + +// static +already_AddRefed<TestInterfaceMaplikeJSObject> +TestInterfaceMaplikeJSObject::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceMaplikeJSObject> r = + new TestInterfaceMaplikeJSObject(window); + return r.forget(); +} + +JSObject* TestInterfaceMaplikeJSObject::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceMaplikeJSObject_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceMaplikeJSObject::GetParentObject() const { + return mParent; +} + +void TestInterfaceMaplikeJSObject::SetInternal(JSContext* aCx, + const nsAString& aKey, + JS::Handle<JSObject*> aObject) { + ErrorResult rv; + TestInterfaceMaplikeJSObject_Binding::MaplikeHelpers::Set(this, aKey, aObject, + rv); +} + +void TestInterfaceMaplikeJSObject::ClearInternal() { + ErrorResult rv; + TestInterfaceMaplikeJSObject_Binding::MaplikeHelpers::Clear(this, rv); +} + +bool TestInterfaceMaplikeJSObject::DeleteInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplikeJSObject_Binding::MaplikeHelpers::Delete(this, + aKey, rv); +} + +bool TestInterfaceMaplikeJSObject::HasInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplikeJSObject_Binding::MaplikeHelpers::Has(this, aKey, + rv); +} + +void TestInterfaceMaplikeJSObject::GetInternal( + JSContext* aCx, const nsAString& aKey, JS::MutableHandle<JSObject*> aRetVal, + ErrorResult& aRv) { + TestInterfaceMaplikeJSObject_Binding::MaplikeHelpers::Get(this, aCx, aKey, + aRetVal, aRv); +} +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceMaplikeJSObject.h b/dom/bindings/test/TestInterfaceMaplikeJSObject.h new file mode 100644 index 0000000000..00feda7796 --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplikeJSObject.h @@ -0,0 +1,55 @@ +/* -*- 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_TestInterfaceMaplikeJSObject_h +#define mozilla_dom_TestInterfaceMaplikeJSObject_h + +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl maplike interfaces, using +// primitives for key types and objects for value types. +class TestInterfaceMaplikeJSObject final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceMaplikeJSObject) + + explicit TestInterfaceMaplikeJSObject(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceMaplikeJSObject> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + // External access for testing internal convenience functions. + void SetInternal(JSContext* aCx, const nsAString& aKey, + JS::Handle<JSObject*> aObject); + void ClearInternal(); + bool DeleteInternal(const nsAString& aKey); + bool HasInternal(const nsAString& aKey); + void GetInternal(JSContext* aCx, const nsAString& aKey, + JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv); + + private: + virtual ~TestInterfaceMaplikeJSObject() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceMaplikeJSObject_h diff --git a/dom/bindings/test/TestInterfaceMaplikeObject.cpp b/dom/bindings/test/TestInterfaceMaplikeObject.cpp new file mode 100644 index 0000000000..b05e33df6b --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplikeObject.cpp @@ -0,0 +1,81 @@ +/* -*- 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/TestInterfaceMaplikeObject.h" +#include "mozilla/dom/TestInterfaceMaplike.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplikeObject, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplikeObject) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplikeObject) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplikeObject) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceMaplikeObject::TestInterfaceMaplikeObject( + nsPIDOMWindowInner* aParent) + : mParent(aParent) {} + +// static +already_AddRefed<TestInterfaceMaplikeObject> +TestInterfaceMaplikeObject::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceMaplikeObject> r = new TestInterfaceMaplikeObject(window); + return r.forget(); +} + +JSObject* TestInterfaceMaplikeObject::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceMaplikeObject_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceMaplikeObject::GetParentObject() const { + return mParent; +} + +void TestInterfaceMaplikeObject::SetInternal(const nsAString& aKey) { + RefPtr<TestInterfaceMaplike> p(new TestInterfaceMaplike(mParent)); + ErrorResult rv; + TestInterfaceMaplikeObject_Binding::MaplikeHelpers::Set(this, aKey, *p, rv); +} + +void TestInterfaceMaplikeObject::ClearInternal() { + ErrorResult rv; + TestInterfaceMaplikeObject_Binding::MaplikeHelpers::Clear(this, rv); +} + +bool TestInterfaceMaplikeObject::DeleteInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplikeObject_Binding::MaplikeHelpers::Delete(this, aKey, + rv); +} + +bool TestInterfaceMaplikeObject::HasInternal(const nsAString& aKey) { + ErrorResult rv; + return TestInterfaceMaplikeObject_Binding::MaplikeHelpers::Has(this, aKey, + rv); +} + +already_AddRefed<TestInterfaceMaplike> TestInterfaceMaplikeObject::GetInternal( + const nsAString& aKey, ErrorResult& aRv) { + return TestInterfaceMaplikeObject_Binding::MaplikeHelpers::Get(this, aKey, + aRv); +} +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceMaplikeObject.h b/dom/bindings/test/TestInterfaceMaplikeObject.h new file mode 100644 index 0000000000..894447cc41 --- /dev/null +++ b/dom/bindings/test/TestInterfaceMaplikeObject.h @@ -0,0 +1,55 @@ +/* -*- 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_TestInterfaceMaplikeObject_h +#define mozilla_dom_TestInterfaceMaplikeObject_h + +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; +class TestInterfaceMaplike; + +// Implementation of test binding for webidl maplike interfaces, using +// primitives for key types and objects for value types. +class TestInterfaceMaplikeObject final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceMaplikeObject) + + explicit TestInterfaceMaplikeObject(nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceMaplikeObject> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + // External access for testing internal convenience functions. + void SetInternal(const nsAString& aKey); + void ClearInternal(); + bool DeleteInternal(const nsAString& aKey); + bool HasInternal(const nsAString& aKey); + already_AddRefed<TestInterfaceMaplike> GetInternal(const nsAString& aKey, + ErrorResult& aRv); + + private: + virtual ~TestInterfaceMaplikeObject() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceMaplikeObject_h diff --git a/dom/bindings/test/TestInterfaceObservableArray.cpp b/dom/bindings/test/TestInterfaceObservableArray.cpp new file mode 100644 index 0000000000..cb8d532eb8 --- /dev/null +++ b/dom/bindings/test/TestInterfaceObservableArray.cpp @@ -0,0 +1,225 @@ +/* -*- 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/TestInterfaceObservableArray.h" +#include "mozilla/dom/TestInterfaceObservableArrayBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceObservableArray, mParent, + mSetBooleanCallback, + mDeleteBooleanCallback, + mSetObjectCallback, mDeleteObjectCallback, + mSetInterfaceCallback, + mDeleteInterfaceCallback) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceObservableArray) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceObservableArray) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceObservableArray) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceObservableArray::TestInterfaceObservableArray( + nsPIDOMWindowInner* aParent, const ObservableArrayCallbacks& aCallbacks) + : mParent(aParent) { + if (aCallbacks.mSetBooleanCallback.WasPassed()) { + mSetBooleanCallback = &aCallbacks.mSetBooleanCallback.Value(); + } + if (aCallbacks.mDeleteBooleanCallback.WasPassed()) { + mDeleteBooleanCallback = &aCallbacks.mDeleteBooleanCallback.Value(); + } + if (aCallbacks.mSetObjectCallback.WasPassed()) { + mSetObjectCallback = &aCallbacks.mSetObjectCallback.Value(); + } + if (aCallbacks.mDeleteObjectCallback.WasPassed()) { + mDeleteObjectCallback = &aCallbacks.mDeleteObjectCallback.Value(); + } + if (aCallbacks.mSetInterfaceCallback.WasPassed()) { + mSetInterfaceCallback = &aCallbacks.mSetInterfaceCallback.Value(); + } + if (aCallbacks.mDeleteInterfaceCallback.WasPassed()) { + mDeleteInterfaceCallback = &aCallbacks.mDeleteInterfaceCallback.Value(); + } +} + +// static +already_AddRefed<TestInterfaceObservableArray> +TestInterfaceObservableArray::Constructor( + const GlobalObject& aGlobal, const ObservableArrayCallbacks& aCallbacks, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceObservableArray> r = + new TestInterfaceObservableArray(window, aCallbacks); + return r.forget(); +} + +JSObject* TestInterfaceObservableArray::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceObservableArray_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceObservableArray::GetParentObject() const { + return mParent; +} + +void TestInterfaceObservableArray::OnSetObservableArrayObject( + JSContext* aCx, JS::Handle<JSObject*> aValue, uint32_t aIndex, + ErrorResult& aRv) { + if (mSetObjectCallback) { + MOZ_KnownLive(mSetObjectCallback) + ->Call(aValue, aIndex, aRv, "OnSetObservableArrayObject", + CallbackFunction::eRethrowExceptions); + } +} + +void TestInterfaceObservableArray::OnDeleteObservableArrayObject( + JSContext* aCx, JS::Handle<JSObject*> aValue, uint32_t aIndex, + ErrorResult& aRv) { + if (mDeleteObjectCallback) { + MOZ_KnownLive(mDeleteObjectCallback) + ->Call(aValue, aIndex, aRv, "OnDeleteObservableArrayObject", + CallbackFunction::eRethrowExceptions); + } +} + +void TestInterfaceObservableArray::OnSetObservableArrayBoolean( + bool aValue, uint32_t aIndex, ErrorResult& aRv) { + if (mSetBooleanCallback) { + MOZ_KnownLive(mSetBooleanCallback) + ->Call(aValue, aIndex, aRv, "OnSetObservableArrayBoolean", + CallbackFunction::eRethrowExceptions); + } +} + +void TestInterfaceObservableArray::OnDeleteObservableArrayBoolean( + bool aValue, uint32_t aIndex, ErrorResult& aRv) { + if (mDeleteBooleanCallback) { + MOZ_KnownLive(mDeleteBooleanCallback) + ->Call(aValue, aIndex, aRv, "OnDeleteObservableArrayBoolean", + CallbackFunction::eRethrowExceptions); + } +} + +void TestInterfaceObservableArray::OnSetObservableArrayInterface( + TestInterfaceObservableArray* aValue, uint32_t aIndex, ErrorResult& aRv) { + if (mSetInterfaceCallback && aValue) { + MOZ_KnownLive(mSetInterfaceCallback) + ->Call(*aValue, aIndex, aRv, "OnSetObservableArrayInterface", + CallbackFunction::eRethrowExceptions); + } +} + +void TestInterfaceObservableArray::OnDeleteObservableArrayInterface( + TestInterfaceObservableArray* aValue, uint32_t aIndex, ErrorResult& aRv) { + if (mDeleteInterfaceCallback && aValue) { + MOZ_KnownLive(mDeleteInterfaceCallback) + ->Call(*aValue, aIndex, aRv, "OnDeleteObservableArrayInterface", + CallbackFunction::eRethrowExceptions); + } +} + +bool TestInterfaceObservableArray::BooleanElementAtInternal(uint32_t aIndex, + ErrorResult& aRv) { + return TestInterfaceObservableArray_Binding::ObservableArrayBooleanHelpers:: + ElementAt(this, aIndex, aRv); +} + +void TestInterfaceObservableArray::ObjectElementAtInternal( + JSContext* aCx, uint32_t aIndex, JS::MutableHandle<JSObject*> aValue, + ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayObjectHelpers::ElementAt( + this, aCx, aIndex, aValue, aRv); +} + +already_AddRefed<TestInterfaceObservableArray> +TestInterfaceObservableArray::InterfaceElementAtInternal(uint32_t aIndex, + ErrorResult& aRv) { + return TestInterfaceObservableArray_Binding::ObservableArrayInterfaceHelpers:: + ElementAt(this, aIndex, aRv); +} + +void TestInterfaceObservableArray::BooleanReplaceElementAtInternal( + uint32_t aIndex, bool aValue, ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayBooleanHelpers:: + ReplaceElementAt(this, aIndex, aValue, aRv); +} + +void TestInterfaceObservableArray::ObjectReplaceElementAtInternal( + JSContext* aCx, uint32_t aIndex, JS::Handle<JSObject*> aValue, + ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayObjectHelpers:: + ReplaceElementAt(this, aIndex, aValue, aRv); +} + +void TestInterfaceObservableArray::InterfaceReplaceElementAtInternal( + uint32_t aIndex, TestInterfaceObservableArray& aValue, ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayInterfaceHelpers:: + ReplaceElementAt(this, aIndex, aValue, aRv); +} + +void TestInterfaceObservableArray::BooleanAppendElementInternal( + bool aValue, ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayBooleanHelpers:: + AppendElement(this, aValue, aRv); +} + +void TestInterfaceObservableArray::ObjectAppendElementInternal( + JSContext* aCx, JS::Handle<JSObject*> aValue, ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayObjectHelpers:: + AppendElement(this, aValue, aRv); +} + +void TestInterfaceObservableArray::InterfaceAppendElementInternal( + TestInterfaceObservableArray& aValue, ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayInterfaceHelpers:: + AppendElement(this, aValue, aRv); +} + +void TestInterfaceObservableArray::BooleanRemoveLastElementInternal( + ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayBooleanHelpers:: + RemoveLastElement(this, aRv); +} + +void TestInterfaceObservableArray::ObjectRemoveLastElementInternal( + ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayObjectHelpers:: + RemoveLastElement(this, aRv); +} + +void TestInterfaceObservableArray::InterfaceRemoveLastElementInternal( + ErrorResult& aRv) { + TestInterfaceObservableArray_Binding::ObservableArrayInterfaceHelpers:: + RemoveLastElement(this, aRv); +} + +uint32_t TestInterfaceObservableArray::BooleanLengthInternal(ErrorResult& aRv) { + return TestInterfaceObservableArray_Binding::ObservableArrayBooleanHelpers:: + Length(this, aRv); +} + +uint32_t TestInterfaceObservableArray::ObjectLengthInternal(ErrorResult& aRv) { + return TestInterfaceObservableArray_Binding::ObservableArrayObjectHelpers:: + Length(this, aRv); +} + +uint32_t TestInterfaceObservableArray::InterfaceLengthInternal( + ErrorResult& aRv) { + return TestInterfaceObservableArray_Binding::ObservableArrayInterfaceHelpers:: + Length(this, aRv); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceObservableArray.h b/dom/bindings/test/TestInterfaceObservableArray.h new file mode 100644 index 0000000000..3329663ac6 --- /dev/null +++ b/dom/bindings/test/TestInterfaceObservableArray.h @@ -0,0 +1,115 @@ +/* -*- 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_TestInterfaceObservableArray_h +#define mozilla_dom_TestInterfaceObservableArray_h + +#include "nsCOMPtr.h" +#include "nsWrapperCache.h" +#include "nsTArray.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; +class SetDeleteBooleanCallback; +class SetDeleteInterfaceCallback; +class SetDeleteObjectCallback; +struct ObservableArrayCallbacks; + +// Implementation of test binding for webidl ObservableArray type, using +// primitives for value type +class TestInterfaceObservableArray final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceObservableArray) + + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceObservableArray> Constructor( + const GlobalObject& aGlobal, const ObservableArrayCallbacks& aCallbacks, + ErrorResult& rv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnSetObservableArrayObject(JSContext* aCx, JS::Handle<JSObject*> aValue, + uint32_t aIndex, ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnDeleteObservableArrayObject(JSContext* aCx, + JS::Handle<JSObject*> aValue, + uint32_t aIndex, ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnSetObservableArrayBoolean(bool aValue, uint32_t aIndex, + ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnDeleteObservableArrayBoolean(bool aValue, uint32_t aIndex, + ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnSetObservableArrayInterface(TestInterfaceObservableArray* aValue, + uint32_t aIndex, ErrorResult& aRv); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void OnDeleteObservableArrayInterface(TestInterfaceObservableArray* aValue, + uint32_t aIndex, ErrorResult& aRv); + + bool BooleanElementAtInternal(uint32_t aIndex, ErrorResult& aRv); + void ObjectElementAtInternal(JSContext* aCx, uint32_t aIndex, + JS::MutableHandle<JSObject*> aValue, + ErrorResult& aRv); + already_AddRefed<TestInterfaceObservableArray> InterfaceElementAtInternal( + uint32_t aIndex, ErrorResult& aRv); + + void BooleanReplaceElementAtInternal(uint32_t aIndex, bool aValue, + ErrorResult& aRv); + void ObjectReplaceElementAtInternal(JSContext* aCx, uint32_t aIndex, + JS::Handle<JSObject*> aValue, + ErrorResult& aRv); + void InterfaceReplaceElementAtInternal(uint32_t aIndex, + TestInterfaceObservableArray& aValue, + ErrorResult& aRv); + + void BooleanAppendElementInternal(bool aValue, ErrorResult& aRv); + void ObjectAppendElementInternal(JSContext* aCx, JS::Handle<JSObject*> aValue, + ErrorResult& aRv); + void InterfaceAppendElementInternal(TestInterfaceObservableArray& aValue, + ErrorResult& aRv); + + void BooleanRemoveLastElementInternal(ErrorResult& aRv); + void ObjectRemoveLastElementInternal(ErrorResult& aRv); + void InterfaceRemoveLastElementInternal(ErrorResult& aRv); + + uint32_t BooleanLengthInternal(ErrorResult& aRv); + uint32_t ObjectLengthInternal(ErrorResult& aRv); + uint32_t InterfaceLengthInternal(ErrorResult& aRv); + + private: + explicit TestInterfaceObservableArray( + nsPIDOMWindowInner* aParent, const ObservableArrayCallbacks& aCallbacks); + virtual ~TestInterfaceObservableArray() = default; + + nsCOMPtr<nsPIDOMWindowInner> mParent; + RefPtr<SetDeleteBooleanCallback> mSetBooleanCallback; + RefPtr<SetDeleteBooleanCallback> mDeleteBooleanCallback; + RefPtr<SetDeleteObjectCallback> mSetObjectCallback; + RefPtr<SetDeleteObjectCallback> mDeleteObjectCallback; + RefPtr<SetDeleteInterfaceCallback> mSetInterfaceCallback; + RefPtr<SetDeleteInterfaceCallback> mDeleteInterfaceCallback; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceObservableArray_h diff --git a/dom/bindings/test/TestInterfaceSetlike.cpp b/dom/bindings/test/TestInterfaceSetlike.cpp new file mode 100644 index 0000000000..ac973d1c23 --- /dev/null +++ b/dom/bindings/test/TestInterfaceSetlike.cpp @@ -0,0 +1,51 @@ +/* -*- 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/TestInterfaceSetlike.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlike, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlike) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlike) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlike) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceSetlike::TestInterfaceSetlike(JSContext* aCx, + nsPIDOMWindowInner* aParent) + : mParent(aParent) {} + +// static +already_AddRefed<TestInterfaceSetlike> TestInterfaceSetlike::Constructor( + const GlobalObject& aGlobal, ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceSetlike> r = new TestInterfaceSetlike(nullptr, window); + return r.forget(); +} + +JSObject* TestInterfaceSetlike::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceSetlike_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceSetlike::GetParentObject() const { + return mParent; +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceSetlike.h b/dom/bindings/test/TestInterfaceSetlike.h new file mode 100644 index 0000000000..c99a0240ea --- /dev/null +++ b/dom/bindings/test/TestInterfaceSetlike.h @@ -0,0 +1,44 @@ +/* -*- 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_TestInterfaceSetlike_h +#define mozilla_dom_TestInterfaceSetlike_h + +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl setlike interfaces, using +// primitives for key type. +class TestInterfaceSetlike final : public nsISupports, public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceSetlike) + explicit TestInterfaceSetlike(JSContext* aCx, nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceSetlike> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + private: + virtual ~TestInterfaceSetlike() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceSetlike_h diff --git a/dom/bindings/test/TestInterfaceSetlikeNode.cpp b/dom/bindings/test/TestInterfaceSetlikeNode.cpp new file mode 100644 index 0000000000..5d01c50b42 --- /dev/null +++ b/dom/bindings/test/TestInterfaceSetlikeNode.cpp @@ -0,0 +1,53 @@ +/* -*- 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/TestInterfaceSetlikeNode.h" +#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" +#include "nsPIDOMWindow.h" +#include "mozilla/dom/BindingUtils.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlikeNode, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlikeNode) +NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlikeNode) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlikeNode) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +TestInterfaceSetlikeNode::TestInterfaceSetlikeNode(JSContext* aCx, + nsPIDOMWindowInner* aParent) + : mParent(aParent) {} + +// static +already_AddRefed<TestInterfaceSetlikeNode> +TestInterfaceSetlikeNode::Constructor(const GlobalObject& aGlobal, + ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + RefPtr<TestInterfaceSetlikeNode> r = + new TestInterfaceSetlikeNode(nullptr, window); + return r.forget(); +} + +JSObject* TestInterfaceSetlikeNode::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return TestInterfaceSetlikeNode_Binding::Wrap(aCx, this, aGivenProto); +} + +nsPIDOMWindowInner* TestInterfaceSetlikeNode::GetParentObject() const { + return mParent; +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceSetlikeNode.h b/dom/bindings/test/TestInterfaceSetlikeNode.h new file mode 100644 index 0000000000..c4efdeab19 --- /dev/null +++ b/dom/bindings/test/TestInterfaceSetlikeNode.h @@ -0,0 +1,46 @@ +/* -*- 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_TestInterfaceSetlikeNode_h +#define mozilla_dom_TestInterfaceSetlikeNode_h + +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindowInner; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class GlobalObject; + +// Implementation of test binding for webidl setlike interfaces, using +// primitives for key type. +class TestInterfaceSetlikeNode final : public nsISupports, + public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(TestInterfaceSetlikeNode) + explicit TestInterfaceSetlikeNode(JSContext* aCx, + nsPIDOMWindowInner* aParent); + nsPIDOMWindowInner* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + static already_AddRefed<TestInterfaceSetlikeNode> Constructor( + const GlobalObject& aGlobal, ErrorResult& rv); + + private: + virtual ~TestInterfaceSetlikeNode() = default; + nsCOMPtr<nsPIDOMWindowInner> mParent; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TestInterfaceSetlikeNode_h diff --git a/dom/bindings/test/TestJSImplGen.webidl b/dom/bindings/test/TestJSImplGen.webidl new file mode 100644 index 0000000000..7a1028dc6f --- /dev/null +++ b/dom/bindings/test/TestJSImplGen.webidl @@ -0,0 +1,884 @@ +/* -*- 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/. + */ + +typedef TestJSImplInterface AnotherNameForTestJSImplInterface; +typedef TestJSImplInterface YetAnotherNameForTestJSImplInterface; +typedef TestJSImplInterface? NullableTestJSImplInterface; + +callback MyTestCallback = undefined(); + +enum MyTestEnum { + "a", + "b" +}; + +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface;1"] +interface TestJSImplInterface { + // We don't support multiple constructors (bug 869268) or named constructors + // for JS-implemented WebIDL. + [Throws] + constructor(DOMString str, unsigned long num, boolean? boolArg, + TestInterface? iface, long arg1, + DictForConstructor dict, any any1, + object obj1, + object? obj2, sequence<Dict> seq, optional any any2, + optional object obj3, + optional object? obj4, + Uint8Array typedArr, + ArrayBuffer arrayBuf); + + // Integer types + // XXXbz add tests for throwing versions of all the integer stuff + readonly attribute byte readonlyByte; + attribute byte writableByte; + undefined passByte(byte arg); + byte receiveByte(); + undefined passOptionalByte(optional byte arg); + undefined passOptionalByteBeforeRequired(optional byte arg1, byte arg2); + undefined passOptionalByteWithDefault(optional byte arg = 0); + undefined passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2); + undefined passNullableByte(byte? arg); + undefined passOptionalNullableByte(optional byte? arg); + undefined passVariadicByte(byte... arg); + // [Cached] is not supported in JS-implemented WebIDL. + //[Cached, Pure] + //readonly attribute byte cachedByte; + //[Cached, Constant] + //readonly attribute byte cachedConstantByte; + //[Cached, Pure] + //attribute byte cachedWritableByte; + [Affects=Nothing] + attribute byte sideEffectFreeByte; + [Affects=Nothing, DependsOn=DOMState] + attribute byte domDependentByte; + [Affects=Nothing, DependsOn=Nothing] + readonly attribute byte constantByte; + [DependsOn=DeviceState, Affects=Nothing] + readonly attribute byte deviceStateDependentByte; + [Affects=Nothing] + byte returnByteSideEffectFree(); + [Affects=Nothing, DependsOn=DOMState] + byte returnDOMDependentByte(); + [Affects=Nothing, DependsOn=Nothing] + byte returnConstantByte(); + [DependsOn=DeviceState, Affects=Nothing] + byte returnDeviceStateDependentByte(); + + readonly attribute short readonlyShort; + attribute short writableShort; + undefined passShort(short arg); + short receiveShort(); + undefined passOptionalShort(optional short arg); + undefined passOptionalShortWithDefault(optional short arg = 5); + + readonly attribute long readonlyLong; + attribute long writableLong; + undefined passLong(long arg); + long receiveLong(); + undefined passOptionalLong(optional long arg); + undefined passOptionalLongWithDefault(optional long arg = 7); + + readonly attribute long long readonlyLongLong; + attribute long long writableLongLong; + undefined passLongLong(long long arg); + long long receiveLongLong(); + undefined passOptionalLongLong(optional long long arg); + undefined passOptionalLongLongWithDefault(optional long long arg = -12); + + readonly attribute octet readonlyOctet; + attribute octet writableOctet; + undefined passOctet(octet arg); + octet receiveOctet(); + undefined passOptionalOctet(optional octet arg); + undefined passOptionalOctetWithDefault(optional octet arg = 19); + + readonly attribute unsigned short readonlyUnsignedShort; + attribute unsigned short writableUnsignedShort; + undefined passUnsignedShort(unsigned short arg); + unsigned short receiveUnsignedShort(); + undefined passOptionalUnsignedShort(optional unsigned short arg); + undefined passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2); + + readonly attribute unsigned long readonlyUnsignedLong; + attribute unsigned long writableUnsignedLong; + undefined passUnsignedLong(unsigned long arg); + unsigned long receiveUnsignedLong(); + undefined passOptionalUnsignedLong(optional unsigned long arg); + undefined passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6); + + readonly attribute unsigned long long readonlyUnsignedLongLong; + attribute unsigned long long writableUnsignedLongLong; + undefined passUnsignedLongLong(unsigned long long arg); + unsigned long long receiveUnsignedLongLong(); + undefined passOptionalUnsignedLongLong(optional unsigned long long arg); + undefined passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17); + + attribute float writableFloat; + attribute unrestricted float writableUnrestrictedFloat; + attribute float? writableNullableFloat; + attribute unrestricted float? writableNullableUnrestrictedFloat; + attribute double writableDouble; + attribute unrestricted double writableUnrestrictedDouble; + attribute double? writableNullableDouble; + attribute unrestricted double? writableNullableUnrestrictedDouble; + undefined passFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, sequence<unrestricted float> arg10, + sequence<float?> arg11, sequence<unrestricted float?> arg12, + sequence<double> arg13, sequence<unrestricted double> arg14, + sequence<double?> arg15, sequence<unrestricted double?> arg16); + [LenientFloat] + undefined passLenientFloat(float arg1, unrestricted float arg2, + float? arg3, unrestricted float? arg4, + double arg5, unrestricted double arg6, + double? arg7, unrestricted double? arg8, + sequence<float> arg9, + sequence<unrestricted float> arg10, + sequence<float?> arg11, + sequence<unrestricted float?> arg12, + sequence<double> arg13, + sequence<unrestricted double> arg14, + sequence<double?> arg15, + sequence<unrestricted double?> arg16); + [LenientFloat] + attribute float lenientFloatAttr; + [LenientFloat] + attribute double lenientDoubleAttr; + + // Castable interface types + // XXXbz add tests for throwing versions of all the castable interface stuff + TestJSImplInterface receiveSelf(); + TestJSImplInterface? receiveNullableSelf(); + + TestJSImplInterface receiveWeakSelf(); + TestJSImplInterface? receiveWeakNullableSelf(); + + // A version to test for casting to TestJSImplInterface& + undefined passSelf(TestJSImplInterface arg); + undefined passNullableSelf(TestJSImplInterface? arg); + attribute TestJSImplInterface nonNullSelf; + attribute TestJSImplInterface? nullableSelf; + // [Cached] is not supported in JS-implemented WebIDL. + //[Cached, Pure] + //readonly attribute TestJSImplInterface cachedSelf; + // Optional arguments + undefined passOptionalSelf(optional TestJSImplInterface? arg); + undefined passOptionalNonNullSelf(optional TestJSImplInterface arg); + undefined passOptionalSelfWithDefault(optional TestJSImplInterface? arg = null); + + // Non-wrapper-cache interface types + [NewObject] + TestNonWrapperCacheInterface receiveNonWrapperCacheInterface(); + [NewObject] + TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface(); + + [NewObject] + sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence(); + [NewObject] + sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence(); + + // External interface types + TestExternalInterface receiveExternal(); + TestExternalInterface? receiveNullableExternal(); + TestExternalInterface receiveWeakExternal(); + TestExternalInterface? receiveWeakNullableExternal(); + undefined passExternal(TestExternalInterface arg); + undefined passNullableExternal(TestExternalInterface? arg); + attribute TestExternalInterface nonNullExternal; + attribute TestExternalInterface? nullableExternal; + // Optional arguments + undefined passOptionalExternal(optional TestExternalInterface? arg); + undefined passOptionalNonNullExternal(optional TestExternalInterface arg); + undefined passOptionalExternalWithDefault(optional TestExternalInterface? arg = null); + + // Callback interface types + TestCallbackInterface receiveCallbackInterface(); + TestCallbackInterface? receiveNullableCallbackInterface(); + TestCallbackInterface receiveWeakCallbackInterface(); + TestCallbackInterface? receiveWeakNullableCallbackInterface(); + undefined passCallbackInterface(TestCallbackInterface arg); + undefined passNullableCallbackInterface(TestCallbackInterface? arg); + attribute TestCallbackInterface nonNullCallbackInterface; + attribute TestCallbackInterface? nullableCallbackInterface; + // Optional arguments + undefined passOptionalCallbackInterface(optional TestCallbackInterface? arg); + undefined passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg); + undefined passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null); + + // Sequence types + // [Cached] is not supported in JS-implemented WebIDL. + //[Cached, Pure] + //readonly attribute sequence<long> readonlySequence; + //[Cached, Pure] + //readonly attribute sequence<Dict> readonlySequenceOfDictionaries; + //[Cached, Pure] + //readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries; + //[Cached, Pure, Frozen] + //readonly attribute sequence<long> readonlyFrozenSequence; + //[Cached, Pure, Frozen] + //readonly attribute sequence<long>? readonlyFrozenNullableSequence; + sequence<long> receiveSequence(); + sequence<long>? receiveNullableSequence(); + sequence<long?> receiveSequenceOfNullableInts(); + sequence<long?>? receiveNullableSequenceOfNullableInts(); + undefined passSequence(sequence<long> arg); + undefined passNullableSequence(sequence<long>? arg); + undefined passSequenceOfNullableInts(sequence<long?> arg); + undefined passOptionalSequenceOfNullableInts(optional sequence<long?> arg); + undefined passOptionalNullableSequenceOfNullableInts(optional sequence<long?>? arg); + sequence<TestJSImplInterface> receiveCastableObjectSequence(); + sequence<TestCallbackInterface> receiveCallbackObjectSequence(); + sequence<TestJSImplInterface?> receiveNullableCastableObjectSequence(); + sequence<TestCallbackInterface?> receiveNullableCallbackObjectSequence(); + sequence<TestJSImplInterface>? receiveCastableObjectNullableSequence(); + sequence<TestJSImplInterface?>? receiveNullableCastableObjectNullableSequence(); + sequence<TestJSImplInterface> receiveWeakCastableObjectSequence(); + sequence<TestJSImplInterface?> receiveWeakNullableCastableObjectSequence(); + sequence<TestJSImplInterface>? receiveWeakCastableObjectNullableSequence(); + sequence<TestJSImplInterface?>? receiveWeakNullableCastableObjectNullableSequence(); + undefined passCastableObjectSequence(sequence<TestJSImplInterface> arg); + undefined passNullableCastableObjectSequence(sequence<TestJSImplInterface?> arg); + undefined passCastableObjectNullableSequence(sequence<TestJSImplInterface>? arg); + undefined passNullableCastableObjectNullableSequence(sequence<TestJSImplInterface?>? arg); + undefined passOptionalSequence(optional sequence<long> arg); + undefined passOptionalSequenceWithDefaultValue(optional sequence<long> arg = []); + undefined passOptionalNullableSequence(optional sequence<long>? arg); + undefined passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null); + undefined passOptionalNullableSequenceWithDefaultValue2(optional sequence<long>? arg = []); + undefined passOptionalObjectSequence(optional sequence<TestJSImplInterface> arg); + undefined passExternalInterfaceSequence(sequence<TestExternalInterface> arg); + undefined passNullableExternalInterfaceSequence(sequence<TestExternalInterface?> arg); + + sequence<DOMString> receiveStringSequence(); + sequence<ByteString> receiveByteStringSequence(); + sequence<UTF8String> receiveUTF8StringSequence(); + // Callback interface problem. See bug 843261. + //undefined passStringSequence(sequence<DOMString> arg); + sequence<any> receiveAnySequence(); + sequence<any>? receiveNullableAnySequence(); + //XXXbz No support for sequence of sequence return values yet. + //sequence<sequence<any>> receiveAnySequenceSequence(); + + sequence<object> receiveObjectSequence(); + sequence<object?> receiveNullableObjectSequence(); + + undefined passSequenceOfSequences(sequence<sequence<long>> arg); + undefined passSequenceOfSequencesOfSequences(sequence<sequence<sequence<long>>> arg); + //XXXbz No support for sequence of sequence return values yet. + //sequence<sequence<long>> receiveSequenceOfSequences(); + + // record types + undefined passRecord(record<DOMString, long> arg); + undefined passNullableRecord(record<DOMString, long>? arg); + undefined passRecordOfNullableInts(record<DOMString, long?> arg); + undefined passOptionalRecordOfNullableInts(optional record<DOMString, long?> arg); + undefined passOptionalNullableRecordOfNullableInts(optional record<DOMString, long?>? arg); + undefined passCastableObjectRecord(record<DOMString, TestInterface> arg); + undefined passNullableCastableObjectRecord(record<DOMString, TestInterface?> arg); + undefined passCastableObjectNullableRecord(record<DOMString, TestInterface>? arg); + undefined passNullableCastableObjectNullableRecord(record<DOMString, TestInterface?>? arg); + undefined passOptionalRecord(optional record<DOMString, long> arg); + undefined passOptionalNullableRecord(optional record<DOMString, long>? arg); + undefined passOptionalNullableRecordWithDefaultValue(optional record<DOMString, long>? arg = null); + undefined passOptionalObjectRecord(optional record<DOMString, TestInterface> arg); + undefined passExternalInterfaceRecord(record<DOMString, TestExternalInterface> arg); + undefined passNullableExternalInterfaceRecord(record<DOMString, TestExternalInterface?> arg); + undefined passStringRecord(record<DOMString, DOMString> arg); + undefined passByteStringRecord(record<DOMString, ByteString> arg); + undefined passUTF8StringRecord(record<DOMString, UTF8String> arg); + undefined passRecordOfRecords(record<DOMString, record<DOMString, long>> arg); + record<DOMString, long> receiveRecord(); + record<DOMString, long>? receiveNullableRecord(); + record<DOMString, long?> receiveRecordOfNullableInts(); + record<DOMString, long?>? receiveNullableRecordOfNullableInts(); + //XXXbz No support for record of records return values yet. + //record<DOMString, record<DOMString, long>> receiveRecordOfRecords(); + record<DOMString, any> receiveAnyRecord(); + + // Typed array types + undefined passArrayBuffer(ArrayBuffer arg); + undefined passNullableArrayBuffer(ArrayBuffer? arg); + undefined passOptionalArrayBuffer(optional ArrayBuffer arg); + undefined passOptionalNullableArrayBuffer(optional ArrayBuffer? arg); + undefined passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null); + undefined passArrayBufferView(ArrayBufferView arg); + undefined passInt8Array(Int8Array arg); + undefined passInt16Array(Int16Array arg); + undefined passInt32Array(Int32Array arg); + undefined passUint8Array(Uint8Array arg); + undefined passUint16Array(Uint16Array arg); + undefined passUint32Array(Uint32Array arg); + undefined passUint8ClampedArray(Uint8ClampedArray arg); + undefined passFloat32Array(Float32Array arg); + undefined passFloat64Array(Float64Array arg); + undefined passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg); + undefined passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg); + undefined passRecordOfArrayBuffers(record<DOMString, ArrayBuffer> arg); + undefined passRecordOfNullableArrayBuffers(record<DOMString, ArrayBuffer?> arg); + undefined passVariadicTypedArray(Float32Array... arg); + undefined passVariadicNullableTypedArray(Float32Array?... arg); + Uint8Array receiveUint8Array(); + attribute Uint8Array uint8ArrayAttr; + + // DOMString types + undefined passString(DOMString arg); + undefined passNullableString(DOMString? arg); + undefined passOptionalString(optional DOMString arg); + undefined passOptionalStringWithDefaultValue(optional DOMString arg = "abc"); + undefined passOptionalNullableString(optional DOMString? arg); + undefined passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null); + undefined passVariadicString(DOMString... arg); + + // ByteString types + undefined passByteString(ByteString arg); + undefined passNullableByteString(ByteString? arg); + undefined passOptionalByteString(optional ByteString arg); + undefined passOptionalByteStringWithDefaultValue(optional ByteString arg = "abc"); + undefined passOptionalNullableByteString(optional ByteString? arg); + undefined passOptionalNullableByteStringWithDefaultValue(optional ByteString? arg = null); + undefined passVariadicByteString(ByteString... arg); + undefined passUnionByteString((ByteString or long) arg); + undefined passOptionalUnionByteString(optional (ByteString or long) arg); + undefined passOptionalUnionByteStringWithDefaultValue(optional (ByteString or long) arg = "abc"); + + // UTF8String types + undefined passUTF8String(UTF8String arg); + undefined passNullableUTF8String(UTF8String? arg); + undefined passOptionalUTF8String(optional UTF8String arg); + undefined passOptionalUTF8StringWithDefaultValue(optional UTF8String arg = "abc"); + undefined passOptionalNullableUTF8String(optional UTF8String? arg); + undefined passOptionalNullableUTF8StringWithDefaultValue(optional UTF8String? arg = null); + undefined passVariadicUTF8String(UTF8String... arg); + undefined passUnionUTF8String((UTF8String or long) arg); + undefined passOptionalUnionUTF8String(optional (UTF8String or long) arg); + undefined passOptionalUnionUTF8StringWithDefaultValue(optional (UTF8String or long) arg = "abc"); + + // USVString types + undefined passSVS(USVString arg); + undefined passNullableSVS(USVString? arg); + undefined passOptionalSVS(optional USVString arg); + undefined passOptionalSVSWithDefaultValue(optional USVString arg = "abc"); + undefined passOptionalNullableSVS(optional USVString? arg); + undefined passOptionalNullableSVSWithDefaultValue(optional USVString? arg = null); + undefined passVariadicSVS(USVString... arg); + USVString receiveSVS(); + + // JSString types + undefined passJSString(JSString arg); + // undefined passNullableJSString(JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalJSString(optional JSString arg); // NOT SUPPORTED YET + undefined passOptionalJSStringWithDefaultValue(optional JSString arg = "abc"); + // undefined passOptionalNullableJSString(optional JSString? arg); // NOT SUPPORTED YET + // undefined passOptionalNullableJSStringWithDefaultValue(optional JSString? arg = null); // NOT SUPPORTED YET + // undefined passVariadicJSString(JSString... arg); // NOT SUPPORTED YET + // undefined passRecordOfJSString(record<DOMString, JSString> arg); // NOT SUPPORTED YET + // undefined passSequenceOfJSString(sequence<JSString> arg); // NOT SUPPORTED YET + // undefined passUnionJSString((JSString or long) arg); // NOT SUPPORTED YET + JSString receiveJSString(); + // sequence<JSString> receiveJSStringSequence(); // NOT SUPPORTED YET + // (JSString or long) receiveJSStringUnion(); // NOT SUPPORTED YET + // record<DOMString, JSString> receiveJSStringRecord(); // NOT SUPPORTED YET + readonly attribute JSString readonlyJSStringAttr; + attribute JSString jsStringAttr; + + // Enumerated types + undefined passEnum(MyTestEnum arg); + undefined passNullableEnum(MyTestEnum? arg); + undefined passOptionalEnum(optional MyTestEnum arg); + undefined passEnumWithDefault(optional MyTestEnum arg = "a"); + undefined passOptionalNullableEnum(optional MyTestEnum? arg); + undefined passOptionalNullableEnumWithDefaultValue(optional MyTestEnum? arg = null); + undefined passOptionalNullableEnumWithDefaultValue2(optional MyTestEnum? arg = "a"); + MyTestEnum receiveEnum(); + MyTestEnum? receiveNullableEnum(); + attribute MyTestEnum enumAttribute; + readonly attribute MyTestEnum readonlyEnumAttribute; + + // Callback types + undefined passCallback(MyTestCallback arg); + undefined passNullableCallback(MyTestCallback? arg); + undefined passOptionalCallback(optional MyTestCallback arg); + undefined passOptionalNullableCallback(optional MyTestCallback? arg); + undefined passOptionalNullableCallbackWithDefaultValue(optional MyTestCallback? arg = null); + MyTestCallback receiveCallback(); + MyTestCallback? receiveNullableCallback(); + // Hmm. These two don't work, I think because I need a locally modified version of TestTreatAsNullCallback. + //undefined passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg); + //undefined passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg); + undefined passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null); + + // Any types + undefined passAny(any arg); + undefined passVariadicAny(any... arg); + undefined passOptionalAny(optional any arg); + undefined passAnyDefaultNull(optional any arg = null); + undefined passSequenceOfAny(sequence<any> arg); + undefined passNullableSequenceOfAny(sequence<any>? arg); + undefined passOptionalSequenceOfAny(optional sequence<any> arg); + undefined passOptionalNullableSequenceOfAny(optional sequence<any>? arg); + undefined passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null); + undefined passSequenceOfSequenceOfAny(sequence<sequence<any>> arg); + undefined passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg); + undefined passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg); + undefined passRecordOfAny(record<DOMString, any> arg); + undefined passNullableRecordOfAny(record<DOMString, any>? arg); + undefined passOptionalRecordOfAny(optional record<DOMString, any> arg); + undefined passOptionalNullableRecordOfAny(optional record<DOMString, any>? arg); + undefined passOptionalRecordOfAnyWithDefaultValue(optional record<DOMString, any>? arg = null); + undefined passRecordOfRecordOfAny(record<DOMString, record<DOMString, any>> arg); + undefined passRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?> arg); + undefined passNullableRecordOfNullableRecordOfAny(record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableRecordOfAny(optional record<DOMString, record<DOMString, any>?>? arg); + undefined passOptionalNullableRecordOfNullableSequenceOfAny(optional record<DOMString, sequence<any>?>? arg); + undefined passOptionalNullableSequenceOfNullableRecordOfAny(optional sequence<record<DOMString, any>?>? arg); + any receiveAny(); + + // object types + undefined passObject(object arg); + undefined passVariadicObject(object... arg); + undefined passNullableObject(object? arg); + undefined passVariadicNullableObject(object... arg); + undefined passOptionalObject(optional object arg); + undefined passOptionalNullableObject(optional object? arg); + undefined passOptionalNullableObjectWithDefaultValue(optional object? arg = null); + undefined passSequenceOfObject(sequence<object> arg); + undefined passSequenceOfNullableObject(sequence<object?> arg); + undefined passNullableSequenceOfObject(sequence<object>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg); + undefined passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg); + undefined passRecordOfObject(record<DOMString, object> arg); + object receiveObject(); + object? receiveNullableObject(); + + // Union types + undefined passUnion((object or long) arg); + // Some union tests are debug-only to aundefined creating all those + // unused union types in opt builds. +#ifdef DEBUG + undefined passUnion2((long or boolean) arg); + undefined passUnion3((object or long or boolean) arg); + undefined passUnion4((Node or long or boolean) arg); + undefined passUnion5((object or boolean) arg); + undefined passUnion6((object or DOMString) arg); + undefined passUnion7((object or DOMString or long) arg); + undefined passUnion8((object or DOMString or boolean) arg); + undefined passUnion9((object or DOMString or long or boolean) arg); + undefined passUnion10(optional (EventInit or long) arg = {}); + undefined passUnion11(optional (CustomEventInit or long) arg = {}); + undefined passUnion12(optional (EventInit or long) arg = 5); + undefined passUnion13(optional (object or long?) arg = null); + undefined passUnion14(optional (object or long?) arg = 5); + undefined passUnion15((sequence<long> or long) arg); + undefined passUnion16(optional (sequence<long> or long) arg); + undefined passUnion17(optional (sequence<long>? or long) arg = 5); + undefined passUnion18((sequence<object> or long) arg); + undefined passUnion19(optional (sequence<object> or long) arg); + undefined passUnion20(optional (sequence<object> or long) arg = []); + undefined passUnion21((record<DOMString, long> or long) arg); + undefined passUnion22((record<DOMString, object> or long) arg); + undefined passUnion23((sequence<ImageData> or long) arg); + undefined passUnion24((sequence<ImageData?> or long) arg); + undefined passUnion25((sequence<sequence<ImageData>> or long) arg); + undefined passUnion26((sequence<sequence<ImageData?>> or long) arg); + undefined passUnion27(optional (sequence<DOMString> or EventInit) arg = {}); + undefined passUnion28(optional (EventInit or sequence<DOMString>) arg = {}); + undefined passUnionWithCallback((EventHandler or long) arg); + undefined passUnionWithByteString((ByteString or long) arg); + undefined passUnionWithUTF8String((UTF8String or long) arg); + undefined passUnionWithRecord((record<DOMString, DOMString> or DOMString) arg); + undefined passUnionWithRecordAndSequence((record<DOMString, DOMString> or sequence<DOMString>) arg); + undefined passUnionWithSequenceAndRecord((sequence<DOMString> or record<DOMString, DOMString>) arg); + undefined passUnionWithSVS((USVString or long) arg); +#endif + undefined passUnionWithNullable((object? or long) arg); + undefined passNullableUnion((object or long)? arg); + undefined passOptionalUnion(optional (object or long) arg); + undefined passOptionalNullableUnion(optional (object or long)? arg); + undefined passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null); + //undefined passUnionWithInterfaces((TestJSImplInterface or TestExternalInterface) arg); + //undefined passUnionWithInterfacesAndNullable((TestJSImplInterface? or TestExternalInterface) arg); + //undefined passUnionWithSequence((sequence<object> or long) arg); + undefined passUnionWithArrayBuffer((ArrayBuffer or long) arg); + undefined passUnionWithString((DOMString or object) arg); + // Using an enum in a union. Note that we use some enum not declared in our + // binding file, because UnionTypes.h will need to include the binding header + // for this enum. Pick an enum from an interface that won't drag in too much + // stuff. + undefined passUnionWithEnum((SupportedType or object) arg); + + // Trying to use a callback in a union won't include the test + // headers, unfortunately, so won't compile. + // undefined passUnionWithCallback((MyTestCallback or long) arg); + undefined passUnionWithObject((object or long) arg); + //undefined passUnionWithDict((Dict or long) arg); + + undefined passUnionWithDefaultValue1(optional (double or DOMString) arg = ""); + undefined passUnionWithDefaultValue2(optional (double or DOMString) arg = 1); + undefined passUnionWithDefaultValue3(optional (double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue4(optional (float or DOMString) arg = ""); + undefined passUnionWithDefaultValue5(optional (float or DOMString) arg = 1); + undefined passUnionWithDefaultValue6(optional (float or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue7(optional (unrestricted double or DOMString) arg = ""); + undefined passUnionWithDefaultValue8(optional (unrestricted double or DOMString) arg = 1); + undefined passUnionWithDefaultValue9(optional (unrestricted double or DOMString) arg = 1.5); + undefined passUnionWithDefaultValue10(optional (unrestricted double or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue11(optional (unrestricted float or DOMString) arg = ""); + undefined passUnionWithDefaultValue12(optional (unrestricted float or DOMString) arg = 1); + undefined passUnionWithDefaultValue13(optional (unrestricted float or DOMString) arg = Infinity); + undefined passUnionWithDefaultValue14(optional (double or ByteString) arg = ""); + undefined passUnionWithDefaultValue15(optional (double or ByteString) arg = 1); + undefined passUnionWithDefaultValue16(optional (double or ByteString) arg = 1.5); + undefined passUnionWithDefaultValue17(optional (double or SupportedType) arg = "text/html"); + undefined passUnionWithDefaultValue18(optional (double or SupportedType) arg = 1); + undefined passUnionWithDefaultValue19(optional (double or SupportedType) arg = 1.5); + undefined passUnionWithDefaultValue20(optional (double or USVString) arg = "abc"); + undefined passUnionWithDefaultValue21(optional (double or USVString) arg = 1); + undefined passUnionWithDefaultValue22(optional (double or USVString) arg = 1.5); + undefined passUnionWithDefaultValue23(optional (double or UTF8String) arg = ""); + undefined passUnionWithDefaultValue24(optional (double or UTF8String) arg = 1); + undefined passUnionWithDefaultValue25(optional (double or UTF8String) arg = 1.5); + + undefined passNullableUnionWithDefaultValue1(optional (double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue2(optional (double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue3(optional (double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue4(optional (float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue5(optional (float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue6(optional (float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue7(optional (unrestricted double or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue8(optional (unrestricted double or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue9(optional (unrestricted double or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue10(optional (unrestricted float or DOMString)? arg = ""); + undefined passNullableUnionWithDefaultValue11(optional (unrestricted float or DOMString)? arg = 1); + undefined passNullableUnionWithDefaultValue12(optional (unrestricted float or DOMString)? arg = null); + undefined passNullableUnionWithDefaultValue13(optional (double or ByteString)? arg = ""); + undefined passNullableUnionWithDefaultValue14(optional (double or ByteString)? arg = 1); + undefined passNullableUnionWithDefaultValue15(optional (double or ByteString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue16(optional (double or ByteString)? arg = null); + undefined passNullableUnionWithDefaultValue17(optional (double or SupportedType)? arg = "text/html"); + undefined passNullableUnionWithDefaultValue18(optional (double or SupportedType)? arg = 1); + undefined passNullableUnionWithDefaultValue19(optional (double or SupportedType)? arg = 1.5); + undefined passNullableUnionWithDefaultValue20(optional (double or SupportedType)? arg = null); + undefined passNullableUnionWithDefaultValue21(optional (double or USVString)? arg = "abc"); + undefined passNullableUnionWithDefaultValue22(optional (double or USVString)? arg = 1); + undefined passNullableUnionWithDefaultValue23(optional (double or USVString)? arg = 1.5); + undefined passNullableUnionWithDefaultValue24(optional (double or USVString)? arg = null); + undefined passNullableUnionWithDefaultValue25(optional (double or UTF8String)? arg = ""); + undefined passNullableUnionWithDefaultValue26(optional (double or UTF8String)? arg = 1); + undefined passNullableUnionWithDefaultValue27(optional (double or UTF8String)? arg = 1.5); + undefined passNullableUnionWithDefaultValue28(optional (double or UTF8String)? arg = null); + + undefined passSequenceOfUnions(sequence<(CanvasPattern or CanvasGradient)> arg); + undefined passSequenceOfUnions2(sequence<(object or long)> arg); + undefined passVariadicUnion((CanvasPattern or CanvasGradient)... arg); + + undefined passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg); + undefined passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg); + undefined passRecordOfUnions(record<DOMString, (CanvasPattern or CanvasGradient)> arg); + // XXXbz no move constructor on some unions + // undefined passRecordOfUnions2(record<DOMString, (object or long)> arg); + + (CanvasPattern or CanvasGradient) receiveUnion(); + (object or long) receiveUnion2(); + (CanvasPattern? or CanvasGradient) receiveUnionContainingNull(); + (CanvasPattern or CanvasGradient)? receiveNullableUnion(); + (object or long)? receiveNullableUnion2(); + + attribute (CanvasPattern or CanvasGradient) writableUnion; + attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull; + attribute (CanvasPattern or CanvasGradient)? writableNullableUnion; + + // Promise types + undefined passPromise(Promise<any> arg); + undefined passOptionalPromise(optional Promise<any> arg); + undefined passPromiseSequence(sequence<Promise<any>> arg); + Promise<any> receivePromise(); + Promise<any> receiveAddrefedPromise(); + + // binaryNames tests + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(); + [BinaryName="methodRenamedTo"] + undefined methodRenamedFrom(byte argument); + [BinaryName="attributeGetterRenamedTo"] + readonly attribute byte attributeGetterRenamedFrom; + [BinaryName="attributeRenamedTo"] + attribute byte attributeRenamedFrom; + + undefined passDictionary(optional Dict x = {}); + undefined passDictionary2(Dict x); + // [Cached] is not supported in JS-implemented WebIDL. + //[Cached, Pure] + //readonly attribute Dict readonlyDictionary; + //[Cached, Pure] + //readonly attribute Dict? readonlyNullableDictionary; + //[Cached, Pure] + //attribute Dict writableDictionary; + //[Cached, Pure, Frozen] + //readonly attribute Dict readonlyFrozenDictionary; + //[Cached, Pure, Frozen] + //readonly attribute Dict? readonlyFrozenNullableDictionary; + //[Cached, Pure, Frozen] + //attribute Dict writableFrozenDictionary; + Dict receiveDictionary(); + Dict? receiveNullableDictionary(); + undefined passOtherDictionary(optional GrandparentDict x = {}); + undefined passSequenceOfDictionaries(sequence<Dict> x); + undefined passRecordOfDictionaries(record<DOMString, GrandparentDict> x); + // No support for nullable dictionaries inside a sequence (nor should there be) + // undefined passSequenceOfNullableDictionaries(sequence<Dict?> x); + undefined passDictionaryOrLong(optional Dict x = {}); + undefined passDictionaryOrLong(long x); + + undefined passDictContainingDict(optional DictContainingDict arg = {}); + undefined passDictContainingSequence(optional DictContainingSequence arg = {}); + DictContainingSequence receiveDictContainingSequence(); + undefined passVariadicDictionary(Dict... arg); + + // EnforceRange/Clamp tests + undefined dontEnforceRangeOrClamp(byte arg); + undefined doEnforceRange([EnforceRange] byte arg); + undefined doEnforceRangeNullable([EnforceRange] byte? arg); + undefined doClamp([Clamp] byte arg); + undefined doClampNullable([Clamp] byte? arg); + attribute [EnforceRange] byte enforcedByte; + attribute [EnforceRange] byte? enforcedByteNullable; + attribute [Clamp] byte clampedByte; + attribute [Clamp] byte? clampedByteNullable; + + // Typedefs + const myLong myLongConstant = 5; + undefined exerciseTypedefInterfaces1(AnotherNameForTestJSImplInterface arg); + AnotherNameForTestJSImplInterface exerciseTypedefInterfaces2(NullableTestJSImplInterface arg); + undefined exerciseTypedefInterfaces3(YetAnotherNameForTestJSImplInterface arg); + + // Deprecated methods and attributes + [Deprecated="Components"] + attribute byte deprecatedAttribute; + [Deprecated="Components"] + byte deprecatedMethod(); + [Deprecated="Components"] + undefined deprecatedMethodWithContext(any arg); + + // Static methods and attributes + // FIXME: Bug 863952 Static things are not supported yet + /* + static attribute boolean staticAttribute; + static undefined staticMethod(boolean arg); + static undefined staticMethodWithContext(any arg); + + // Deprecated static methods and attributes + [Deprecated="Components"] + static attribute byte staticDeprecatedAttribute; + [Deprecated="Components"] + static byte staticDeprecatedMethod(); + [Deprecated="Components"] + static byte staticDeprecatedMethodWithContext(); + */ + + // Overload resolution tests + //undefined overload1(DOMString... strs); + boolean overload1(TestJSImplInterface arg); + TestJSImplInterface overload1(DOMString strs, TestJSImplInterface arg); + undefined overload2(TestJSImplInterface arg); + undefined overload2(optional Dict arg = {}); + undefined overload2(boolean arg); + undefined overload2(DOMString arg); + undefined overload3(TestJSImplInterface arg); + undefined overload3(MyTestCallback arg); + undefined overload3(boolean arg); + undefined overload4(TestJSImplInterface arg); + undefined overload4(TestCallbackInterface arg); + undefined overload4(DOMString arg); + undefined overload5(long arg); + undefined overload5(MyTestEnum arg); + undefined overload6(long arg); + undefined overload6(boolean arg); + undefined overload7(long arg); + undefined overload7(boolean arg); + undefined overload7(ByteString arg); + undefined overload8(long arg); + undefined overload8(TestJSImplInterface arg); + undefined overload9(long? arg); + undefined overload9(DOMString arg); + undefined overload10(long? arg); + undefined overload10(object arg); + undefined overload11(long arg); + undefined overload11(DOMString? arg); + undefined overload12(long arg); + undefined overload12(boolean? arg); + undefined overload13(long? arg); + undefined overload13(boolean arg); + undefined overload14(optional long arg); + undefined overload14(TestInterface arg); + undefined overload15(long arg); + undefined overload15(optional TestInterface arg); + undefined overload16(long arg); + undefined overload16(optional TestInterface? arg); + undefined overload17(sequence<long> arg); + undefined overload17(record<DOMString, long> arg); + undefined overload18(record<DOMString, DOMString> arg); + undefined overload18(sequence<DOMString> arg); + undefined overload19(sequence<long> arg); + undefined overload19(optional Dict arg = {}); + undefined overload20(optional Dict arg = {}); + undefined overload20(sequence<long> arg); + + // Variadic handling + undefined passVariadicThirdArg(DOMString arg1, long arg2, TestJSImplInterface... arg3); + + // Conditionally exposed methods/attributes + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable1; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable2; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable3; + [Pref="dom.webidl.test2"] + readonly attribute boolean prefable4; + [Pref="dom.webidl.test1"] + readonly attribute boolean prefable5; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable6; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable7; + [Pref="dom.webidl.test2", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable8; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean prefable9; + [Pref="dom.webidl.test1"] + undefined prefable10(); + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable11(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable12; + [Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined prefable13(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean prefable14; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable15; + [Func="TestFuncControlledMember"] + readonly attribute boolean prefable16; + [Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined prefable17(); + [Func="TestFuncControlledMember"] + undefined prefable18(); + [Func="TestFuncControlledMember"] + undefined prefable19(); + [Pref="dom.webidl.test1", Func="TestFuncControlledMember", ChromeOnly] + undefined prefable20(); + + // Conditionally exposed methods/attributes involving [SecureContext] + [SecureContext] + readonly attribute boolean conditionalOnSecureContext1; + [SecureContext, Pref="dom.webidl.test1"] + readonly attribute boolean conditionalOnSecureContext2; + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + readonly attribute boolean conditionalOnSecureContext3; + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + readonly attribute boolean conditionalOnSecureContext4; + [SecureContext] + undefined conditionalOnSecureContext5(); + [SecureContext, Pref="dom.webidl.test1"] + undefined conditionalOnSecureContext6(); + [SecureContext, Pref="dom.webidl.test1", Func="nsGenericHTMLElement::LegacyTouchAPIEnabled"] + undefined conditionalOnSecureContext7(); + [SecureContext, Pref="dom.webidl.test1", Func="TestFuncControlledMember"] + undefined conditionalOnSecureContext8(); + + // Miscellania + [LegacyLenientThis] attribute long attrWithLenientThis; + // FIXME: Bug 863954 Unforgeable things get all confused when + // non-JS-implemented interfaces inherit from JS-implemented ones or vice + // versa. + // [Unforgeable] readonly attribute long unforgeableAttr; + // [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2; + // [Unforgeable] long unforgeableMethod(); + // [Unforgeable, ChromeOnly] long unforgeableMethod2(); + // FIXME: Bug 863955 No stringifiers yet + // stringifier; + undefined passRenamedInterface(TestRenamedInterface arg); + [PutForwards=writableByte] readonly attribute TestJSImplInterface putForwardsAttr; + [PutForwards=writableByte, LegacyLenientThis] readonly attribute TestJSImplInterface putForwardsAttr2; + [PutForwards=writableByte, ChromeOnly] readonly attribute TestJSImplInterface putForwardsAttr3; + [Throws] undefined throwingMethod(); + [Throws] attribute boolean throwingAttr; + [GetterThrows] attribute boolean throwingGetterAttr; + [SetterThrows] attribute boolean throwingSetterAttr; + [CanOOM] undefined canOOMMethod(); + [CanOOM] attribute boolean canOOMAttr; + [GetterCanOOM] attribute boolean canOOMGetterAttr; + [SetterCanOOM] attribute boolean canOOMSetterAttr; + [CEReactions] undefined ceReactionsMethod(); + [CEReactions] undefined ceReactionsMethodOverload(); + [CEReactions] undefined ceReactionsMethodOverload(DOMString bar); + [CEReactions] attribute boolean ceReactionsAttr; + // NeedsSubjectPrincipal not supported on JS-implemented things for + // now, because we always pass in the caller principal anyway. + // [NeedsSubjectPrincipal] undefined needsSubjectPrincipalMethod(); + // [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr; + // legacycaller short(unsigned long arg1, TestInterface arg2); + undefined passArgsWithDefaults(optional long arg1, + optional TestInterface? arg2 = null, + optional Dict arg3 = {}, optional double arg4 = 5.0, + optional float arg5); + attribute any toJSONShouldSkipThis; + attribute TestParentInterface toJSONShouldSkipThis2; + attribute TestCallbackInterface toJSONShouldSkipThis3; + [Default] object toJSON(); + + attribute byte dashed-attribute; + undefined dashed-method(); + + // [NonEnumerable] tests + [NonEnumerable] + attribute boolean nonEnumerableAttr; + [NonEnumerable] + const boolean nonEnumerableConst = true; + [NonEnumerable] + undefined nonEnumerableMethod(); + + // [AllowShared] tests + attribute [AllowShared] ArrayBufferViewTypedef allowSharedArrayBufferViewTypedef; + attribute [AllowShared] ArrayBufferView allowSharedArrayBufferView; + attribute [AllowShared] ArrayBufferView? allowSharedNullableArrayBufferView; + attribute [AllowShared] ArrayBuffer allowSharedArrayBuffer; + attribute [AllowShared] ArrayBuffer? allowSharedNullableArrayBuffer; + + undefined passAllowSharedArrayBufferViewTypedef(AllowSharedArrayBufferViewTypedef foo); + undefined passAllowSharedArrayBufferView([AllowShared] ArrayBufferView foo); + undefined passAllowSharedNullableArrayBufferView([AllowShared] ArrayBufferView? foo); + undefined passAllowSharedArrayBuffer([AllowShared] ArrayBuffer foo); + undefined passAllowSharedNullableArrayBuffer([AllowShared] ArrayBuffer? foo); + undefined passUnionArrayBuffer((DOMString or ArrayBuffer) foo); + undefined passUnionAllowSharedArrayBuffer((DOMString or [AllowShared] ArrayBuffer) foo); + + // If you add things here, add them to TestCodeGen as well +}; + +[Exposed=Window] +interface TestCImplementedInterface : TestJSImplInterface { +}; + +[Exposed=Window] +interface TestCImplementedInterface2 { +}; + +[LegacyNoInterfaceObject, + JSImplementation="@mozilla.org/test-js-impl-interface;2", + Exposed=Window] +interface TestJSImplNoInterfaceObject { + // [Cached] is not supported in JS-implemented WebIDL. + //[Cached, Pure] + //readonly attribute byte cachedByte; +}; diff --git a/dom/bindings/test/TestJSImplInheritanceGen.webidl b/dom/bindings/test/TestJSImplInheritanceGen.webidl new file mode 100644 index 0000000000..b4b66d20a0 --- /dev/null +++ b/dom/bindings/test/TestJSImplInheritanceGen.webidl @@ -0,0 +1,39 @@ +/* -*- 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/. + */ + +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface2;1"] +interface TestJSImplInterface2 : TestCImplementedInterface { + [Throws] + constructor(); +}; + +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface3;1"] +interface TestJSImplInterface3 : TestCImplementedInterface2 { + [Throws] + constructor(); +}; + +// Important: TestJSImplInterface5 needs to come before TestJSImplInterface6 in +// this file to test what it's trying to test. +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface5;1"] +interface TestJSImplInterface5 : TestJSImplInterface6 { + [Throws] + constructor(); +}; + +// Important: TestJSImplInterface6 needs to come after TestJSImplInterface3 in +// this file to test what it's trying to test. +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface6;1"] +interface TestJSImplInterface6 : TestJSImplInterface3 { + [Throws] + constructor(); +}; + +[Exposed=Window, JSImplementation="@mozilla.org/test-js-impl-interface4;1"] +interface TestJSImplInterface4 : EventTarget { + [Throws] + constructor(); +}; diff --git a/dom/bindings/test/TestTrialInterface.cpp b/dom/bindings/test/TestTrialInterface.cpp new file mode 100644 index 0000000000..e0b9bb44f9 --- /dev/null +++ b/dom/bindings/test/TestTrialInterface.cpp @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/TestTrialInterface.h" +#include "mozilla/dom/TestFunctionsBinding.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(TestTrialInterface) + +JSObject* TestTrialInterface::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return TestTrialInterface_Binding::Wrap(aCx, this, aGivenProto); +} + +already_AddRefed<TestTrialInterface> TestTrialInterface::Constructor( + const GlobalObject& aGlobalObject) { + return MakeAndAddRef<TestTrialInterface>(); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/TestTrialInterface.h b/dom/bindings/test/TestTrialInterface.h new file mode 100644 index 0000000000..1fa746b09a --- /dev/null +++ b/dom/bindings/test/TestTrialInterface.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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_TestTrialInterface_h +#define mozilla_dom_TestTrialInterface_h + +#include "js/TypeDecls.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" + +namespace mozilla::dom { + +class TestTrialInterface final : public nsWrapperCache { + public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TestTrialInterface) + NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(TestTrialInterface) + + public: + TestTrialInterface() = default; + + static already_AddRefed<TestTrialInterface> Constructor( + const GlobalObject& aGlobalObject); + + protected: + ~TestTrialInterface() = default; + + public: + nsISupports* GetParentObject() const { return nullptr; } + JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_TestTrialInterface_h diff --git a/dom/bindings/test/TestTypedef.webidl b/dom/bindings/test/TestTypedef.webidl new file mode 100644 index 0000000000..7f758c79e8 --- /dev/null +++ b/dom/bindings/test/TestTypedef.webidl @@ -0,0 +1,7 @@ +/* -*- 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/. + */ + +typedef TestInterface YetAnotherNameForTestInterface; diff --git a/dom/bindings/test/WrapperCachedNonISupportsTestInterface.cpp b/dom/bindings/test/WrapperCachedNonISupportsTestInterface.cpp new file mode 100644 index 0000000000..aa69488a09 --- /dev/null +++ b/dom/bindings/test/WrapperCachedNonISupportsTestInterface.cpp @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/WrapperCachedNonISupportsTestInterface.h" +#include "mozilla/dom/TestFunctionsBinding.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WrapperCachedNonISupportsTestInterface) + +JSObject* WrapperCachedNonISupportsTestInterface::WrapObject( + JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { + return WrapperCachedNonISupportsTestInterface_Binding::Wrap(aCx, this, + aGivenProto); +} + +already_AddRefed<WrapperCachedNonISupportsTestInterface> +WrapperCachedNonISupportsTestInterface::Constructor( + const GlobalObject& aGlobalObject) { + RefPtr<WrapperCachedNonISupportsTestInterface> result = + new WrapperCachedNonISupportsTestInterface(); + return result.forget(); +} + +} // namespace mozilla::dom diff --git a/dom/bindings/test/WrapperCachedNonISupportsTestInterface.h b/dom/bindings/test/WrapperCachedNonISupportsTestInterface.h new file mode 100644 index 0000000000..c226d03456 --- /dev/null +++ b/dom/bindings/test/WrapperCachedNonISupportsTestInterface.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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_WrapperCachedNonISupportsTestInterface_h +#define mozilla_dom_WrapperCachedNonISupportsTestInterface_h + +#include "js/TypeDecls.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" + +namespace mozilla { +namespace dom { + +class WrapperCachedNonISupportsTestInterface final : public nsWrapperCache { + public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING( + WrapperCachedNonISupportsTestInterface) + NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS( + WrapperCachedNonISupportsTestInterface) + + public: + WrapperCachedNonISupportsTestInterface() = default; + + static already_AddRefed<WrapperCachedNonISupportsTestInterface> Constructor( + const GlobalObject& aGlobalObject); + + protected: + ~WrapperCachedNonISupportsTestInterface() = default; + + public: + nsISupports* GetParentObject() const { return nullptr; } + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_WrapperCachedNonISupportsTestInterface_h diff --git a/dom/bindings/test/chrome.ini b/dom/bindings/test/chrome.ini new file mode 100644 index 0000000000..e96c2c1209 --- /dev/null +++ b/dom/bindings/test/chrome.ini @@ -0,0 +1,18 @@ +[DEFAULT] +support-files = + !/dom/bindings/test/file_bug775543.html + !/dom/bindings/test/file_document_location_set_via_xray.html + !/dom/bindings/test/file_dom_xrays.html + !/dom/bindings/test/file_proxies_via_xray.html + +[test_bug775543.html] +[test_document_location_set_via_xray.html] +[test_dom_xrays.html] +[test_proxies_via_xray.html] +[test_document_location_via_xray_cached.html] +[test_bug1123516_maplikesetlikechrome.xhtml] +skip-if = debug == false +[test_bug1287912.html] +[test_bug1457051.html] +[test_interfaceLength_chrome.html] +skip-if = debug == false diff --git a/dom/bindings/test/file_InstanceOf.html b/dom/bindings/test/file_InstanceOf.html new file mode 100644 index 0000000000..61e2bc295e --- /dev/null +++ b/dom/bindings/test/file_InstanceOf.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML> +<html> +<body> +<script type="application/javascript"> +function runTest() { + return [ parent.HTMLElement.prototype instanceof Element, + parent.HTMLElement.prototype instanceof parent.Element ]; +} +</script> +</body> +</html> diff --git a/dom/bindings/test/file_barewordGetsWindow_frame1.html b/dom/bindings/test/file_barewordGetsWindow_frame1.html new file mode 100644 index 0000000000..f20ba8a257 --- /dev/null +++ b/dom/bindings/test/file_barewordGetsWindow_frame1.html @@ -0,0 +1 @@ +OLD
\ No newline at end of file diff --git a/dom/bindings/test/file_barewordGetsWindow_frame2.html b/dom/bindings/test/file_barewordGetsWindow_frame2.html new file mode 100644 index 0000000000..5f08364e3b --- /dev/null +++ b/dom/bindings/test/file_barewordGetsWindow_frame2.html @@ -0,0 +1 @@ +NEW
\ No newline at end of file diff --git a/dom/bindings/test/file_bug775543.html b/dom/bindings/test/file_bug775543.html new file mode 100644 index 0000000000..856d14ab0e --- /dev/null +++ b/dom/bindings/test/file_bug775543.html @@ -0,0 +1,5 @@ +<body> +<script> +var worker = new Worker("a"); +</script> +</body> diff --git a/dom/bindings/test/file_document_location_set_via_xray.html b/dom/bindings/test/file_document_location_set_via_xray.html new file mode 100644 index 0000000000..323acba666 --- /dev/null +++ b/dom/bindings/test/file_document_location_set_via_xray.html @@ -0,0 +1,5 @@ +<body> +<script> +document.x = 5; +</script> +</body> diff --git a/dom/bindings/test/file_dom_xrays.html b/dom/bindings/test/file_dom_xrays.html new file mode 100644 index 0000000000..bf8f9491ef --- /dev/null +++ b/dom/bindings/test/file_dom_xrays.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> + <script> + window.expando = 42; + window.shadowedIframe = 42; + Object.setPrototypeOf(window, Object.create(Window.prototype, + { + shadowedIframe: { value: 42 }, + iframe: { value: 42 }, + document: { value: 42 }, + addEventListener: { value: 42 }, + toString: { value: 42 }, + })); + window.documentElement.expando = 42; + Object.defineProperty(window.documentElement, "version", { value: 42 }); + </script> + <iframe name="shadowedIframe" id="shadowedIframe"></iframe> + <iframe name="iframe" id="iframe"></iframe> + <iframe name="document" id="document"></iframe> + <iframe name="self" id="self"></iframe> + <iframe name="addEventListener" id="addEventListener"></iframe> + <iframe name="toString" id="toString"></iframe> + <iframe name="item" id="item"></iframe> +</html> diff --git a/dom/bindings/test/file_proxies_via_xray.html b/dom/bindings/test/file_proxies_via_xray.html new file mode 100644 index 0000000000..135c1f5301 --- /dev/null +++ b/dom/bindings/test/file_proxies_via_xray.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> + <script> + document.x = 5; + </script> + <img id="y" name="y"></div> + <img id="z" name="z"></div> +</html> diff --git a/dom/bindings/test/forOf_iframe.html b/dom/bindings/test/forOf_iframe.html new file mode 100644 index 0000000000..91417aba0e --- /dev/null +++ b/dom/bindings/test/forOf_iframe.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>iframe content for test_forOf_iframe.html</title> +</head> +<body> + <div id="basket"> + <span id="egg0"></span> + <span id="egg1"><span id="duckling1"></span></span> + <span id="egg2"></span> + </div> +</body> +</html> diff --git a/dom/bindings/test/mochitest.ini b/dom/bindings/test/mochitest.ini new file mode 100644 index 0000000000..6746ee60aa --- /dev/null +++ b/dom/bindings/test/mochitest.ini @@ -0,0 +1,106 @@ +[DEFAULT] +support-files = + file_InstanceOf.html + file_bug775543.html + file_document_location_set_via_xray.html + file_dom_xrays.html + file_proxies_via_xray.html + forOf_iframe.html + !/js/xpconnect/tests/mochitest/file_empty.html +prefs = + javascript.options.large_arraybuffers=true + +[test_async_stacks.html] +[test_ByteString.html] +[test_InstanceOf.html] +[test_bug560072.html] +[test_bug742191.html] +[test_bug759621.html] +[test_bug773326.html] +[test_bug788369.html] +[test_bug852846.html] +[test_bug862092.html] +[test_bug1036214.html] +skip-if = !debug +[test_bug1041646.html] +[test_bug1123875.html] +[test_barewordGetsWindow.html] +support-files = + file_barewordGetsWindow_frame1.html + file_barewordGetsWindow_frame2.html +[test_callback_across_document_open.html] +[test_callback_default_thisval.html] +[test_cloneAndImportNode.html] +[test_defineProperty.html] +[test_enums.html] +[test_exceptionThrowing.html] +[test_exception_messages.html] +[test_forOf.html] +[test_integers.html] +[test_interfaceLength.html] +skip-if = debug == false +[test_interfaceName.html] +[test_interfaceToString.html] +[test_prefOnConstructor.html] +skip-if = debug == false +[test_exceptions_from_jsimplemented.html] +tags = webrtc +[test_lenientThis.html] +[test_lookupGetter.html] +[test_namedNoIndexed.html] +[test_named_getter_enumerability.html] +[test_Object.prototype_props.html] +[test_proxy_expandos.html] +[test_proxy_accessors.html] +[test_returnUnion.html] +skip-if = debug == false +[test_usvstring.html] +skip-if = debug == false +[test_sequence_wrapping.html] +subsuite = gpu +[test_setWithNamedGetterNoNamedSetter.html] +[test_throwing_method_noDCE.html] +[test_treat_non_object_as_null.html] +[test_traceProtos.html] +[test_sequence_detection.html] +skip-if = debug == false +[test_exception_options_from_jsimplemented.html] +skip-if = debug == false +[test_promise_rejections_from_jsimplemented.html] +skip-if = debug == false +[test_worker_UnwrapArg.html] +[test_unforgeablesonexpando.html] +[test_crossOriginWindowSymbolAccess.html] +[test_primitive_this.html] +[test_callback_exceptions.html] +[test_bug1123516_maplikesetlike.html] +skip-if = debug == false +[test_jsimplemented_eventhandler.html] +skip-if = debug == false +[test_jsimplemented_cross_realm_this.html] +skip-if = debug == false +[test_iterable.html] +skip-if = debug == false +[test_async_iterable.html] +skip-if = debug == false +[test_oom_reporting.html] +[test_domProxyArrayLengthGetter.html] +[test_exceptionSanitization.html] +skip-if = debug == false +[test_stringBindings.html] +skip-if = debug == false +[test_jsimplemented_subclassing.html] +[test_toJSON.html] +skip-if = debug == false +[test_attributes_on_types.html] +skip-if = debug == false +[test_large_arraybuffers.html] +skip-if = (debug == false || bits == 32) # Large ArrayBuffers are only supported on 64-bit platforms. +[test_observablearray.html] +skip-if = debug == false +[test_observablearray_proxyhandler.html] +skip-if = debug == false +[test_observablearray_helper.html] +skip-if = debug == false +[test_large_imageData.html] +[test_remoteProxyAsPrototype.html] diff --git a/dom/bindings/test/moz.build b/dom/bindings/test/moz.build new file mode 100644 index 0000000000..05af10fb7b --- /dev/null +++ b/dom/bindings/test/moz.build @@ -0,0 +1,68 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DEFINES["IMPL_LIBXUL"] = True +DEFINES["MOZILLA_INTERNAL_API"] = True + +# Do NOT export this library. We don't actually want our test code +# being added to libxul or anything. + +Library("dombindings_test_s") + +MOCHITEST_MANIFESTS += ["mochitest.ini"] + +MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"] + +TEST_WEBIDL_FILES += [ + "TestDictionary.webidl", + "TestJSImplInheritanceGen.webidl", + "TestTypedef.webidl", +] + +TESTING_JS_MODULES += [ + "TestInterfaceJS.sys.mjs", +] + +PREPROCESSED_TEST_WEBIDL_FILES += [ + "TestCodeGen.webidl", + "TestExampleGen.webidl", + "TestJSImplGen.webidl", +] + +WEBIDL_EXAMPLE_INTERFACES += [ + "TestExampleInterface", + "TestExampleProxyInterface", + "TestExampleThrowingConstructorInterface", + "TestExampleWorkerInterface", +] + +# Bug 932082 tracks having bindings use namespaced includes. +LOCAL_INCLUDES += [ + "!/dist/include/mozilla/dom", +] + +LOCAL_INCLUDES += [ + "!..", + "/dom/bindings", + "/js/xpconnect/src", + "/js/xpconnect/wrappers", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +if CONFIG["MOZ_DEBUG"]: + XPIDL_SOURCES += [ + "mozITestInterfaceJS.idl", + ] + + XPIDL_MODULE = "dom_bindings_test" + +# Because we don't actually link this code anywhere, we don't care about +# their optimization level, so don't waste time on optimization. +if CONFIG["CC_TYPE"] == "clang-cl": + CXXFLAGS += ["-Od"] +else: + CXXFLAGS += ["-O0"] diff --git a/dom/bindings/test/mozITestInterfaceJS.idl b/dom/bindings/test/mozITestInterfaceJS.idl new file mode 100644 index 0000000000..7bfbc9b25f --- /dev/null +++ b/dom/bindings/test/mozITestInterfaceJS.idl @@ -0,0 +1,21 @@ +/* -*- Mode: IDL; tab-width: 4; 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/. */ + +#include "nsISupports.idl" + +/** + * An interface to allow testing of binding interactions with JS-implemented + * XPCOM components. The actual implementation is TestInterfaceJS, just like + * for TestInteraceJS.webidl. + */ + +[scriptable, uuid(9eeb2c12-ddd9-4734-8cfb-c0cdfb136e07)] +interface mozITestInterfaceJS : nsISupports { + // Test throwing Components.results.NS_BINDING_ABORTED. + void testThrowNsresult(); + // Test calling a C++ component which throws an nsresult exception. + void testThrowNsresultFromNative(); +}; diff --git a/dom/bindings/test/test_ByteString.html b/dom/bindings/test/test_ByteString.html new file mode 100644 index 0000000000..c4285228e9 --- /dev/null +++ b/dom/bindings/test/test_ByteString.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=796850 +--> +<head> + <meta charset="utf-8"> + <title>Test for ByteString support</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=796850">Mozilla Bug 796850</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + + /** Test for Bug 796850 **/ + var xhr = new XMLHttpRequest(); + var caught = false; + try { + xhr.open("\u5427", "about:mozilla", true); + } catch (TypeError) { + caught = true; + } + ok(caught, "Character values > 255 not rejected for ByteString"); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_InstanceOf.html b/dom/bindings/test/test_InstanceOf.html new file mode 100644 index 0000000000..d04e4e4771 --- /dev/null +++ b/dom/bindings/test/test_InstanceOf.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=748983 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 748983</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=748983">Mozilla Bug 748983</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 748983 **/ + +SimpleTest.waitForExplicitFinish(); + +function runTest() { + ok(document instanceof EventTarget, "document is an event target"); + ok(new XMLHttpRequest() instanceof XMLHttpRequest, "instanceof should work on XHR"); + ok(HTMLElement.prototype instanceof Node, "instanceof needs to walk the prototype chain"); + + var otherWin = document.getElementById("testFrame").contentWindow; + + ok(otherWin.HTMLElement.prototype instanceof otherWin.Node, "Same-origin instanceof of a interface prototype object should work, even if called cross-origin"); + ok(!(otherWin.HTMLElement.prototype instanceof Node), "Cross-origin instanceof of a interface prototype object shouldn't work"); + + // We need to reset HTMLElement.prototype.__proto__ to the original value + // before using anything from the harness, otherwise the harness code breaks + // in weird ways. + HTMLElement.prototype.__proto__ = otherWin.Element.prototype; + var [ shouldSucceed, shouldFail ] = otherWin.runTest(); + shouldSucceed = shouldSucceed && HTMLElement.prototype instanceof otherWin.Element; + shouldFail = shouldFail && HTMLElement.prototype instanceof Element; + HTMLElement.prototype.__proto__ = Element.prototype; + + ok(shouldSucceed, "If an interface prototype object is on the protochain then instanceof with the interface object should succeed"); + ok(!shouldFail, "If an interface prototype object is not on the protochain then instanceof with the interface object should succeed"); + + SimpleTest.finish(); +} + +</script> +</pre> +<iframe id="testFrame" src="file_InstanceOf.html" onload="runTest()"></iframe> +</body> +</html> diff --git a/dom/bindings/test/test_Object.prototype_props.html b/dom/bindings/test/test_Object.prototype_props.html new file mode 100644 index 0000000000..b0e42dbc05 --- /dev/null +++ b/dom/bindings/test/test_Object.prototype_props.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for bug 987110</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +/* global test, assert_array_equals */ +test(function() { + var props = Object.getOwnPropertyNames(Object.prototype); + // If you change this list, make sure it continues to match the list in + // Codegen.py's CGDictionary.getMemberDefinition method. + var expected = [ + "constructor", "toString", "toLocaleString", "valueOf", + "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", + "__defineGetter__", "__defineSetter__", "__lookupGetter__", + "__lookupSetter__", "__proto__", + ]; + assert_array_equals(props.sort(), expected.sort()); +}, "Own properties of Object.prototype"); +</script> diff --git a/dom/bindings/test/test_async_iterable.html b/dom/bindings/test/test_async_iterable.html new file mode 100644 index 0000000000..8f1f04aea7 --- /dev/null +++ b/dom/bindings/test/test_async_iterable.html @@ -0,0 +1,300 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> + <head> + <title>Test Async Iterable Interface</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script class="testbody" type="application/javascript"> + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +const singleValues = Array(10).fill(0).map((_, i) => i * 9 % 7); + +async function check_single_result_values(values, multiplier = 1) { + is(values.length, 10, `AsyncIterableSingle: should return 10 elements`); + for (let i = 0; i < 10; i++) { + let expected = singleValues[i] * multiplier; + is(values[i], expected, + `AsyncIterableSingle: should be ${expected}, get ${values[i]}`); + } +} + +async function check_single_result(itr, multiplier = 1) { + let values = []; + for await (let v of itr) { + values.push(v); + } + check_single_result_values(values, multiplier); +} + +async function test_data_single() { + info(`AsyncIterableSingle: Testing simple iterable creation and functionality`); + + // eslint-disable-next-line no-undef + let itr = new TestInterfaceAsyncIterableSingle({ failToInit: true }); + let initFailed = false; + try { + itr.values(); + } catch (e) { + initFailed = true; + } + ok(initFailed, + "AsyncIterableSingle: A failure in asynchronous iterator initialization " + + "steps should propagate to the caller of the asynchronous iterator's " + + "constructor."); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingle(); + is(itr.values, itr[Symbol.asyncIterator], + `AsyncIterableSingle: Should be using @@asyncIterator for 'values'`); + + await check_single_result(itr); + await check_single_result(itr.values()); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + is(itr.values, itr[Symbol.asyncIterator], + `AsyncIterableSingleWithArgs: Should be using @@asyncIterator for 'values'`); + + await check_single_result(itr, 1); + await check_single_result(itr.values({ multiplier: 2 }), 2); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingle(); + let itrValues = itr.values(); + let values = []; + for (let i = 0; i < 10; ++i) { + values.push(itrValues.next()); + } + check_single_result_values(await Promise.all(values).then(v => v.map(w => w.value))); + + // Test that there is only one ongoing promise at a time. + // Async iterables return a promise that is then resolved with the iterator + // value. We create an array of unresolved promises here, one promise for + // every result that we expect from the iterator. We pass that array of + // promises to the .value() method of the + // TestInterfaceAsyncIterableSingleWithArgs, and it will chain the resolving + // of each resulting iterator value on the corresponding promise from this + // array. We then resolve the promises in the array one by one in reverse + // order. This tries to make sure that the iterator always resolves the + // promises in the order of iteration. + let unblockers = []; + let blockingPromises = []; + for (let i = 0; i < 10; ++i) { + let unblocker; + let promise = new Promise((resolve, reject) => { + unblocker = resolve; + }); + unblockers.push(unblocker); + blockingPromises.push(promise); + } + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + itrValues = itr.values({ blockingPromises }); + values = []; + for (let i = 0; i < 10; ++i) { + values.push(itrValues.next()); + } + unblockers.reverse(); + for (let unblocker of unblockers) { + unblocker(); + } + + check_single_result_values(await Promise.all(values).then(v => v.map(w => w.value))); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + + let callCount = itr.returnCallCount; + + let i = 0; + for await (let v of itr) { + if (++i > 1) { + break; + } + values.push(v); + } + + is(itr.returnCallCount, callCount + 1, + `AsyncIterableSingle: breaking out of for-await-of loop should call "return"`); + is(itr.returnLastCalledWith, undefined, + `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm should be called with the argument that was passed in.`); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + + async function * yieldFromIterator () { + yield * itr + } + + let yieldingIterator = yieldFromIterator(); + + let result = await yieldingIterator.next(); + is(result.value, singleValues[0], + `AsyncIterableSingle: should be ${singleValues[0]}, get ${result.value}`); + result = await yieldingIterator.next(); + is(result.value, singleValues[1], + `AsyncIterableSingle: should be ${singleValues[1]}, get ${result.value}`); + + result = await yieldingIterator.return("abcd"); + is(typeof result, "object", + `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); + is(result.done, true, + `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); + is(result.value, "abcd", + `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); + is(itr.returnLastCalledWith, "abcd", + `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm should be called with the argument that was passed in.`); + + result = await yieldingIterator.return("efgh"); + is(typeof result, "object", + `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); + is(result.done, true, + `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); + is(result.value, "efgh", + `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); + is(itr.returnLastCalledWith, "abcd", + `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm shouldn't be called if the iterator's 'is finished' flag is true already.`); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + itrValues = itr.values({ failNextAfter: 1 }); + await itrValues.next().then(({ value, done }) => { + is(value, singleValues[0], "First value is correct"); + ok(!done, "Expecting more values"); + return itrValues.next(); + }).then(() => { + ok(false, "Second call to next() should convert failure to a rejected promise."); + return itrValues.next(); + }).catch(() => { + ok(true, "Second call to next() should convert failure to a rejected promise."); + return itrValues.next(); + }).then(({ done }) => { + ok(done, "An earlier failure in next() should set the async iterator's 'is finished' flag to true."); + }).catch(() => { + ok(false, "An earlier failure in next() shouldn't cause subsequent calls to return a rejected promise."); + }); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + itrValues = itr.values({ throwFromNext: true }); + await itrValues.next().then(() => { + ok(false, "Should have rejected from the exception"); + }).catch(() => { + ok(true, "Should have rejected from the exception"); + }); + + // eslint-disable-next-line no-undef + itr = new TestInterfaceAsyncIterableSingleWithArgs(); + itrValues = itr.values({ throwFromReturn: () => { throw new DOMException("Throw from return", "InvalidStateError"); } }); + await itrValues.return().then(() => { + ok(false, "Should have rejected from the exception"); + }).catch(() => { + ok(true, "Should have rejected from the exception"); + }); +} + +async function test_data_double() { + info(`AsyncIterableDouble: Testing simple iterable creation and functionality`); + + // eslint-disable-next-line no-undef + let itr = new TestInterfaceAsyncIterableDouble(); + is(itr.entries, itr[Symbol.asyncIterator], + `AsyncIterableDouble: Should be using @@asyncIterator for 'entries'`); + + let elements = [["a", "b"], ["c", "d"], ["e", "f"]]; + let key_itr = itr.keys(); + let value_itr = itr.values(); + let entries_itr = itr.entries(); + let key = await key_itr.next(); + let value = await value_itr.next(); + let entry = await entries_itr.next(); + for (let i = 0; i < 3; ++i) { + is(key.value, elements[i][0], `AsyncIterableDouble: Key.value should be ${elements[i][0]}, got ${key.value}`); + is(key.done, false, `AsyncIterableDouble: Key.done should be false, got ${key.done}`); + is(value.value, elements[i][1], `AsyncIterableDouble: Value.value should be ${elements[i][1]}, got ${value.value}`); + is(value.done, false, `AsyncIterableDouble: Value.done should be false, got ${value.done}`); + is(entry.value[0], elements[i][0], `AsyncIterableDouble: Entry.value[0] should be ${elements[i][0]}, got ${entry.value[0]}`); + is(entry.value[1], elements[i][1], `AsyncIterableDouble: Entry.value[1] should be ${elements[i][1]}, got ${entry.value[1]}`); + is(entry.done, false, `AsyncIterableDouble: Entry.done should be false, got ${entry.done}`); + + key = await key_itr.next(); + value = await value_itr.next(); + entry = await entries_itr.next(); + } + is(key.value, undefined, `AsyncIterableDouble: Key.value should be ${undefined}, got ${key.value}`); + is(key.done, true, `AsyncIterableDouble: Key.done should be true, got ${key.done}`); + is(value.value, undefined, `AsyncIterableDouble: Value.value should be ${undefined}, got ${value.value}`); + is(value.done, true, `AsyncIterableDouble: Value.done should be true, got ${value.done}`); + is(entry.value, undefined, `AsyncIterableDouble: Entry.value should be ${undefined}, got ${entry.value}`); + is(entry.done, true, `AsyncIterableDouble: Entry.done should be true, got ${entry.done}`); + + let idx = 0; + for await (let [itrkey, itrvalue] of itr) { + is(itrkey, elements[idx][0], `AsyncIterableDouble: Looping at ${idx} should have key ${elements[idx][0]}, got ${key}`); + is(itrvalue, elements[idx][1], `AsyncIterableDouble: Looping at ${idx} should have value ${elements[idx][1]}, got ${value}`); + ++idx; + } + is(idx, 3, `AsyncIterableDouble: Should have 3 loops of for-await-of, got ${idx}`); +} + +async function test_data_double_union() { + info(`AsyncIterableDoubleUnion: Testing simple iterable creation and functionality`); + + // eslint-disable-next-line no-undef + let itr = new TestInterfaceAsyncIterableDoubleUnion(); + is(itr.entries, itr[Symbol.asyncIterator], + `AsyncIterableDoubleUnion: Should be using @@asyncIterator for 'entries'`); + + let elements = [["long", 1], ["string", "a"]]; + let key_itr = itr.keys(); + let value_itr = itr.values(); + let entries_itr = itr.entries(); + let key = await key_itr.next(); + let value = await value_itr.next(); + let entry = await entries_itr.next(); + for (let i = 0; i < 2; ++i) { + is(key.value, elements[i][0], `AsyncIterableDoubleUnion: Key.value should be ${elements[i][0]}, got ${key.value}`); + is(key.done, false, `AsyncIterableDoubleUnion: Key.done should be false, got ${key.done}`); + is(value.value, elements[i][1], `AsyncIterableDoubleUnion: Value.value should be ${elements[i][1]}, got ${value.value}`); + is(value.done, false, `AsyncIterableDoubleUnion: Value.done should be false, got ${value.done}`); + is(entry.value[0], elements[i][0], `AsyncIterableDoubleUnion: Entry.value[0] should be ${elements[i][0]}, got ${entry.value[0]}`); + is(entry.value[1], elements[i][1], `AsyncIterableDoubleUnion: Entry.value[1] should be ${elements[i][1]}, got ${entry.value[1]}`); + is(entry.done, false, `AsyncIterableDoubleUnion: Entry.done should be false, got ${entry.done}`); + + key = await key_itr.next(); + value = await value_itr.next(); + entry = await entries_itr.next(); + } + is(key.value, undefined, `AsyncIterableDoubleUnion: Key.value should be ${undefined}, got ${key.value}`); + is(key.done, true, `AsyncIterableDoubleUnion: Key.done should be true, got ${key.done}`); + is(value.value, undefined, `AsyncIterableDoubleUnion: Value.value should be ${undefined}, got ${value.value}`); + is(value.done, true, `AsyncIterableDoubleUnion: Value.done should be true, got ${value.done}`); + is(entry.value, undefined, `AsyncIterableDoubleUnion: Entry.value should be ${undefined}, got ${entry.value}`); + is(entry.done, true, `AsyncIterableDoubleUnion: Entry.done should be true, got ${entry.done}`); + + let idx = 0; + for await (let [itrkey, itrvalue] of itr) { + is(itrkey, elements[idx][0], `AsyncIterableDoubleUnion: Looping at ${idx} should have key ${elements[idx][0]}, got ${key}`); + is(itrvalue, elements[idx][1], `AsyncIterableDoubleUnion: Looping at ${idx} should have value ${elements[idx][1]}, got ${value}`); + ++idx; + } + is(idx, 2, `AsyncIterableDoubleUnion: Should have 2 loops of for-await-of, got ${idx}`); +} + +add_task(async function do_tests() { + await test_data_single(); + await test_data_double(); + await test_data_double_union(); +}); + + </script> + </body> +</html> diff --git a/dom/bindings/test/test_async_stacks.html b/dom/bindings/test/test_async_stacks.html new file mode 100644 index 0000000000..fe761e783b --- /dev/null +++ b/dom/bindings/test/test_async_stacks.html @@ -0,0 +1,109 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1148593 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1148593</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global noSuchFunction */ + + /** Test for Bug 1148593 **/ + + SimpleTest.waitForExplicitFinish(); + + var TESTS; + + function nextTest() { + var t = TESTS.pop(); + if (t) { + t(); + } else { + SimpleTest.finish(); + } + } + + function checkStack(functionName) { + try { + noSuchFunction(); + } catch (e) { + ok(e.stack.includes(functionName), "stack includes " + functionName); + } + nextTest(); + } + + function eventListener() { + checkStack("registerEventListener"); + } + function registerEventListener(link) { + link.onload = eventListener; + } + function eventTest() { + var link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = "data:text/css,"; + registerEventListener(link); + document.body.appendChild(link); + } + + function xhrListener() { + checkStack("xhrTest"); + } + function xhrTest() { + var ourFile = location.href; + var x = new XMLHttpRequest(); + x.onload = xhrListener; + x.open("get", ourFile, true); + x.send(); + } + + function rafListener() { + checkStack("rafTest"); + } + function rafTest() { + requestAnimationFrame(rafListener); + } + + var intervalId; + function intervalHandler() { + clearInterval(intervalId); + checkStack("intervalTest"); + } + function intervalTest() { + intervalId = setInterval(intervalHandler, 5); + } + + function postMessageHandler(ev) { + ev.stopPropagation(); + checkStack("postMessageTest"); + } + function postMessageTest() { + window.addEventListener("message", postMessageHandler, true); + window.postMessage("whatever", "*"); + } + + function runTests() { + TESTS = [postMessageTest, intervalTest, rafTest, xhrTest, eventTest]; + nextTest(); + } + + addLoadEvent(function() { + SpecialPowers.pushPrefEnv( + {"set": [["javascript.options.asyncstack_capture_debuggee_only", false]]}, + runTests); + }); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1148593">Mozilla Bug 1148593</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_attributes_on_types.html b/dom/bindings/test/test_attributes_on_types.html new file mode 100644 index 0000000000..ce606d2014 --- /dev/null +++ b/dom/bindings/test/test_attributes_on_types.html @@ -0,0 +1,246 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1295322 +--> +<head> + <meta charset="utf-8"> + <title>Test for WebIDL attributes on types</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295322">Mozilla Bug 1295322</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + /* global TestFunctions */ + + add_task(async function push_permission() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); + }); + + add_task(function testClampedNullableOctet() { + let test = new TestFunctions(); + test.clampedNullableOctet = null; + is(test.clampedNullableOctet, null, "clampedNullableOctet should be null"); + test.clampedNullableOctet = -1; + is(test.clampedNullableOctet, 0, "clampedNullableOctet should be clamped to 0"); + test.clampedNullableOctet = 256; + is(test.clampedNullableOctet, 255, "clampedNullableOctet should be clamped 255"); + test.clampedNullableOctet = 200; + is(test.clampedNullableOctet, 200, "clampedNullableOctet should be 200"); + test.clampedNullableOctet = null; + is(test.clampedNullableOctet, null, "clampedNullableOctet should be null"); + }); + + add_task(function testEnforcedNullableOctet() { + let test = new TestFunctions(); + test.enforcedNullableOctet = null; + is(test.enforcedNullableOctet, null, "enforcedNullableOctet should be null"); + try { + test.enforcedNullableOctet = -1; + ok(false, "Setting -1 to enforcedNullableOctet should throw exception"); + } catch(e) {} + is(test.enforcedNullableOctet, null, "enforcedNullableOctet should still be null"); + try { + test.enforcedNullableOctet = 256; + ok(false, "Setting 256 to enforcedNullableOctet should throw exception"); + } catch(e) {} + is(test.enforcedNullableOctet, null, "enforcedNullableOctet should still be null"); + test.enforcedNullableOctet = 200; + is(test.enforcedNullableOctet, 200, "enforcedNullableOctet should be 200"); + test.enforcedNullableOctet = null; + is(test.enforcedNullableOctet, null, "enforcedNullableOctet should be null"); + }); + + add_task(function testAllowShared() { + let test = new TestFunctions(); + [{type: "ArrayBuffer", isShared: false}, + {type: "SharedArrayBuffer", isShared: true}].forEach(arrayBuffer => { + if (self[arrayBuffer.type] === undefined) { + // https://bugzilla.mozilla.org/show_bug.cgi?id=1606624 + // Once we enable SharedArrayBuffer on all channel, we could remove + // this. + todo(false, `${arrayBuffer.type} is unavailable.`); + return; + } + + let buffer = new self[arrayBuffer.type](32); + let threw = false; + // Test Not Allow Shared + try { + test.testNotAllowShared(buffer); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testNotAllowShared with ${arrayBuffer.type}`); + + try { + test.testDictWithAllowShared({arrayBuffer: buffer}); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testDictWithAllowShared with {arrayBuffer: ${arrayBuffer.type}}`); + + try { + test.testUnionOfBuffferSource(buffer); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testUnionOfBuffferSource with ${arrayBuffer.type}`); + + try { + test.arrayBuffer = buffer; + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Set arrayBuffer to ${arrayBuffer.type}`); + + try { + test.sequenceOfArrayBuffer = [buffer]; + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Set sequenceOfArrayBuffer to [${arrayBuffer.type}]`); + + // Test Allow Shared + try { + test.testAllowShared(buffer); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testAllowShared with ${arrayBuffer.type}`); + + try { + test.testDictWithAllowShared({allowSharedArrayBuffer: buffer}); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testDictWithAllowShared with {allowSharedArrayBuffer: ${arrayBuffer.type}}`); + + try { + test.testUnionOfAllowSharedBuffferSource(buffer); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testUnionOfAllowSharedBuffferSource with ${arrayBuffer.type}`); + + try { + test.allowSharedArrayBuffer = buffer; + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Set allowSharedArrayBuffer to ${arrayBuffer.type}`); + + try { + test.sequenceOfAllowSharedArrayBuffer = [buffer]; + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Set sequenceOfAllowSharedArrayBuffer to [${arrayBuffer.type}]`); + + ["Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", + "Int32Array", "Uint32Array", "Float32Array", "Float64Array", "DataView"].forEach(arrayType => { + let array = new self[arrayType](buffer); + // Test Not Allow Shared + try { + test.testNotAllowShared(array); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testNotAllowShared with ${arrayType} (${arrayBuffer.type})`); + + try { + test.testDictWithAllowShared({arrayBufferView: array}); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testDictWithAllowShared with {arrayBufferView: ${arrayType} (${arrayBuffer.type})}`); + + try { + test.testUnionOfBuffferSource(array); + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Call testUnionOfBuffferSource with ${arrayType} (${arrayBuffer.type})`); + + try { + test.arrayBufferView = array; + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Set arrayBufferView to ${arrayType} (${arrayBuffer.type})`); + + try { + test.sequenceOfArrayBufferView = [array]; + threw = false; + } catch(e) { + threw = true; + } + is(threw, arrayBuffer.isShared, `Set sequenceOfArrayBufferView to [${arrayType} (${arrayBuffer.type})]`); + + // Test Allow Shared + try { + test.testAllowShared(array); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testAllowShared with ${arrayType} (${arrayBuffer.type})`); + + try { + test.testDictWithAllowShared({allowSharedArrayBufferView: array}); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testDictWithAllowShared with {allowSharedArrayBufferView: ${arrayType} (${arrayBuffer.type})}`); + + try { + test.testUnionOfAllowSharedBuffferSource(array); + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Call testUnionOfAllowSharedBuffferSource with ${arrayType} (${arrayBuffer.type})`); + + try { + test.allowSharedArrayBufferView = array; + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Set allowSharedArrayBufferView to ${arrayType} (${arrayBuffer.type})`); + + try { + test.sequenceOfAllowSharedArrayBufferView = [array]; + threw = false; + } catch(e) { + threw = true; + } + ok(!threw, `Set sequenceOfAllowSharedArrayBufferView to [${arrayType} (${arrayBuffer.type})]`); + }); + }); + }); + </script> +</body> +</html> diff --git a/dom/bindings/test/test_barewordGetsWindow.html b/dom/bindings/test/test_barewordGetsWindow.html new file mode 100644 index 0000000000..ddd62fc520 --- /dev/null +++ b/dom/bindings/test/test_barewordGetsWindow.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=936056 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 936056</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 936056 **/ + SimpleTest.waitForExplicitFinish(); + window.onload = function() { + var desc = Object.getOwnPropertyDescriptor(frames[0], "document"); + if (!desc || !desc.get) { + todo(false, "This test does nothing so far, but will once Window is on WebIDL bindings"); + SimpleTest.finish(); + return; + } + var get = desc.get; + ok(get, "Couldn't find document getter"); + Object.defineProperty(frames[0], "foo", { get, configurable: true }); + + var barewordFunc = frames[0].eval("(function (count) { var doc; for (var i = 0; i < count; ++i) doc = foo; return doc.documentElement; })"); + var qualifiedFunc = frames[0].eval("(function (count) { var doc; for (var i = 0; i < count; ++i) doc = window.document; return doc.documentElement; })"); + document.querySelector("iframe").onload = function() { + // interp + is(barewordFunc(1).innerText, "OLD", "Bareword should see own inner 1"); + is(qualifiedFunc(1).innerText, "NEW", + "Qualified should see current inner 1"); + // baseline + is(barewordFunc(100).innerText, "OLD", "Bareword should see own inner 2"); + is(qualifiedFunc(100).innerText, "NEW", + "Qualified should see current inner 2"); + // ion + is(barewordFunc(10000).innerText, "OLD", "Bareword should see own inner 3"); + is(qualifiedFunc(10000).innerText, "NEW", + "Qualified should see current inner 2"); + SimpleTest.finish(); + }; + frames[0].location = "file_barewordGetsWindow_frame2.html"; + }; + + + + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=936056">Mozilla Bug 936056</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe src="file_barewordGetsWindow_frame1.html"></iframe> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug1036214.html b/dom/bindings/test/test_bug1036214.html new file mode 100644 index 0000000000..8fbe373b65 --- /dev/null +++ b/dom/bindings/test/test_bug1036214.html @@ -0,0 +1,141 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1036214 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1036214</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS */ + + /** Test for subsumes-checking |any| and |object| for js-implemented WebIDL. **/ + SimpleTest.waitForExplicitFinish(); + var xoObjects = []; + function setup() { + // window[0] is same-process and cross-origin, even with Fission enabled. + xoObjects.push(window[0]); + xoObjects.push(window[0].location); + xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap(window[0]).document)); + xoObjects.push(SpecialPowers.unwrap(SpecialPowers)); + xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap)); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go); + } + + function setup2() { + if (SpecialPowers.useRemoteSubframes) { + // window[1] is cross-origin and out of process, with Fission enabled. + xoObjects.push(window[1]); + xoObjects.push(window[1].location); + } + } + + function checkThrows(f, msg) { + try { + f(); + ok(false, "Should have thrown: " + msg); + } catch (e) { + ok(true, "Threw correctly: " + msg); + ok(/denied|insecure/.test(e), "Threw security exception: " + e); + } + } + + function go() { + // + // Test the basics of the test interface. + // + + var any = { a: 11 }; + var obj = { b: 22, c: "str" }; + var obj2 = { foo: "baz" }; + var myDict = { anyMember: 42, objectMember: { answer: 42 }, objectOrStringMember: { answer: "anobject" }, + anySequenceMember: [{}, 1, "thirdinsequence"], + objectRecordMember: { key: { answer: "fortytwo" } }, + innerDictionary: { innerObject: { answer: "rabbithole" } } }; + var t = new TestInterfaceJS(any, obj, myDict); + is(Object.getPrototypeOf(t), TestInterfaceJS.prototype, "Prototype setup works correctly"); + is(t.anyArg, any, "anyArg is correct"); + is(t.objectArg, obj, "objectArg is correct"); + is(t.getDictionaryArg().anyMember, 42, "dictionaryArg looks correct"); + is(t.getDictionaryArg().objectMember.answer, 42, "dictionaryArg looks correct"); + is(t.getDictionaryArg().objectRecordMember.key.answer, "fortytwo", "dictionaryArg looks correct"); + is(t.getDictionaryArg().objectRecordMember.key.answer, "fortytwo", "dictionaryArg looks correct"); + t.anyAttr = 2; + is(t.anyAttr, 2, "ping-pong any attribute works"); + t.objAttr = obj2; + is(t.objAttr, obj2, "ping-pong object attribute works"); + t.setDictionaryAttr(myDict); + is(t.getDictionaryAttr().anyMember, 42, "ping-pong dictionary works"); + is(t.getDictionaryAttr().objectMember.answer, 42, "ping-pong dictionary works"); + is(t.getDictionaryAttr().objectRecordMember.key.answer, "fortytwo", "ping-pong dictionary works"); + is(t.getDictionaryAttr().objectRecordMember.key.answer, "fortytwo", "ping-pong dictionary works"); + + is(any, t.pingPongAny(any), "ping-pong works with any"); + is(obj, t.pingPongObject(obj), "ping-pong works with obj"); + is(obj, t.pingPongObjectOrString(obj), "ping-pong works with obj or string"); + is("foo", t.pingPongObjectOrString("foo"), "ping-pong works with obj or string"); + is(t.pingPongDictionary(myDict).anyMember, 42, "ping pong works with dict"); + is(t.pingPongDictionary(myDict).objectMember.answer, 42, "ping pong works with dict"); + is(t.pingPongDictionary(myDict).objectOrStringMember.answer, "anobject", "ping pong works with dict"); + is(t.pingPongDictionary(myDict).anySequenceMember[2], "thirdinsequence", "ping pong works with dict"); + is(t.pingPongDictionary(myDict).objectRecordMember.key.answer, "fortytwo", "ping pong works with dict"); + is(t.pingPongDictionary(myDict).objectRecordMember.key.answer, "fortytwo", "ping pong works with dict"); + is(t.pingPongDictionary(myDict).innerDictionary.innerObject.answer, "rabbithole", "ping pong works with layered dicts"); + is(t.pingPongDictionaryOrLong({anyMember: 42}), 42, "ping pong (dict or long) works with dict"); + is(t.pingPongDictionaryOrLong(42), 42, "ping pong (dict or long) works with long"); + ok(/canary/.test(t.pingPongRecord({ someVal: 42, someOtherVal: "canary" })), "ping pong works with record"); + is(t.objectSequenceLength([{}, {}, {}]), 3, "ping pong works with object sequence"); + is(t.anySequenceLength([42, "string", {}, undefined]), 4, "ping pong works with any sequence"); + + // + // Test that we throw in the cross-origin cases. + // + + xoObjects.forEach(function(xoObj) { + new TestInterfaceJS(); + checkThrows(() => new TestInterfaceJS(xoObj, undefined), "any param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, xoObj), "obj param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, undefined, { anyMember: xoObj }), "any dict param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectMember: xoObj }), "object dict param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, undefined, { objectOrStringMember: xoObj }), "union dict param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, undefined, { anySequenceMember: [0, xoObj, "hi" ] }), "sequence dict param for constructor"); + checkThrows(() => new TestInterfaceJS(undefined, undefined, { innerDictionary: { innerObject: xoObj } }), "inner dict param for constructor"); + checkThrows(() => t.anyAttr = xoObj, "anyAttr"); + checkThrows(() => t.objectAttr = xoObj, "objAttr"); + checkThrows(() => t.setDictionaryAttr({ anyMember: xoObj }), "dictionaryAttr any"); + checkThrows(() => t.setDictionaryAttr({ objectMember: xoObj }), "dictionaryAttr object"); + checkThrows(() => t.pingPongAny(xoObj), "pingpong any"); + checkThrows(() => t.pingPongObject(xoObj), "pingpong obj"); + checkThrows(() => t.pingPongObjectOrString(xoObj), "pingpong union"); + checkThrows(() => t.pingPongDictionary({ anyMember: xoObj }), "dictionary pingpong any"); + checkThrows(() => t.pingPongDictionary({ objectMember: xoObj }), "dictionary pingpong object"); + checkThrows(() => t.pingPongDictionary({ anyMember: xoObj, objectMember: xoObj }), "dictionary pingpong both"); + checkThrows(() => t.pingPongDictionary({ objectOrStringMember: xoObj }), "dictionary pingpong objectorstring"); + checkThrows(() => t.pingPongDictionary({ objectRecordMember: { key: xoObj } }), "dictionary pingpong record of object"); + checkThrows(() => t.pingPongDictionaryOrLong({ objectMember: xoObj }), "unionable dictionary"); + checkThrows(() => t.pingPongDictionaryOrLong({ anyMember: xoObj }), "unionable dictionary"); + checkThrows(() => t.pingPongRecord({ someMember: 42, someOtherMember: {}, crossOriginMember: xoObj }), "record"); + checkThrows(() => t.objectSequenceLength([{}, {}, xoObj, {}]), "object sequence"); + checkThrows(() => t.anySequenceLength([42, "someString", xoObj, {}]), "any sequence"); + }); + + + SimpleTest.finish(); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1036214">Mozilla Bug 1036214</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +<iframe id="ifr" onload="setup();" src="http://test1.mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe> +<iframe id="ifr2" onload="setup2();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe> +</body> +</html> diff --git a/dom/bindings/test/test_bug1041646.html b/dom/bindings/test/test_bug1041646.html new file mode 100644 index 0000000000..95550a98e2 --- /dev/null +++ b/dom/bindings/test/test_bug1041646.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1041646 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1041646</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1041646 **/ + // We need to reject the promise with a DOMException, so make sure we have + // something that produces one. + function throwException() { + document.createTextNode("").appendChild(document); + } + try { + throwException(); + } catch (e) { + ok(e instanceof DOMException, "This test won't test what it should be testing"); + } + + SimpleTest.waitForExplicitFinish(); + + // We want a new DOMException each time here. + for (var i = 0; i < 100; ++i) { + new Promise(throwException); + } + + // Now make sure we wait for all those promises above to reject themselves + Promise.resolve(1).then(function() { + SpecialPowers.gc(); // This should not assert or crash + SimpleTest.finish(); + }); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1041646">Mozilla Bug 1041646</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug1123516_maplikesetlike.html b/dom/bindings/test/test_bug1123516_maplikesetlike.html new file mode 100644 index 0000000000..bc5048eb05 --- /dev/null +++ b/dom/bindings/test/test_bug1123516_maplikesetlike.html @@ -0,0 +1,278 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> + <head> + <title>Test Maplike Interface</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script class="testbody" type="application/javascript"> + /* global TestInterfaceMaplike, TestInterfaceSetlike, TestInterfaceMaplikeObject, TestInterfaceMaplikeJSObject*/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { + var base_properties = [["has", "function", 1], + ["entries", "function", 0], + ["keys", "function", 0], + ["values", "function", 0], + ["forEach", "function", 1], + ["size", "number"]]; + var maplike_properties = base_properties.concat([["set", "function", 2]]); + var rw_properties = [["clear", "function", 0], + ["delete", "function", 1]]; + var setlike_rw_properties = base_properties.concat(rw_properties).concat([["add", "function", 1]]); + var maplike_rw_properties = maplike_properties.concat(rw_properties).concat([["get", "function", 1]]); + var testExistence = function testExistence(prefix, obj, properties) { + for (var [name, type, args] of properties) { + // Properties are somewhere up the proto chain, hasOwnProperty won't work + isnot(obj[name], undefined, + `${prefix} object has property ${name}`); + + is(typeof obj[name], type, + `${prefix} object property ${name} is a ${type}`); + // Check function length + if (type == "function") { + is(obj[name].length, args, + `${prefix} object property ${name} is length ${args}`); + is(obj[name].name, name, + `${prefix} object method name is ${name}`); + } + + // Find where property is on proto chain, check for enumerablility there. + var owner = obj; + while (owner) { + var propDesc = Object.getOwnPropertyDescriptor(owner, name); + if (propDesc) { + ok(propDesc.enumerable, + `${prefix} object property ${name} should be enumerable`); + break; + } + owner = Object.getPrototypeOf(owner); + } + } + }; + + var m; + var testSet; + var testIndex; + + // Simple map creation and functionality test + info("SimpleMap: Testing simple map creation and functionality"); + m = new TestInterfaceMaplike(); + ok(m, "SimpleMap: got a TestInterfaceMaplike object"); + testExistence("SimpleMap: ", m, maplike_rw_properties); + is(m.size, 0, "SimpleMap: size should be zero"); + ok(!m.has("test"), "SimpleMap: maplike has should return false"); + is(m.get("test"), undefined, "SimpleMap: maplike get should return undefined on bogus lookup"); + var m1 = m.set("test", 1); + is(m, m1, "SimpleMap: return from set should be map object"); + is(m.size, 1, "SimpleMap: size should be 1"); + ok(m.has("test"), "SimpleMap: maplike has should return true"); + is(m.get("test"), 1, "SimpleMap: maplike get should return value entered"); + m.set("test2", 2); + is(m.size, 2, "SimpleMap: size should be 2"); + testSet = [["test", 1], ["test2", 2]]; + testIndex = 0; + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "SimpleMap: foreach obj is correct"); + is(k, testSet[testIndex][0], "SimpleMap: foreach map key: " + k + " = " + testSet[testIndex][0]); + is(v, testSet[testIndex][1], "SimpleMap: foreach map value: " + v + " = " + testSet[testIndex][1]); + testIndex += 1; + }); + is(testIndex, 2, "SimpleMap: foreach ran correct number of times"); + ok(m.has("test2"), "SimpleMap: maplike has should return true"); + is(m.get("test2"), 2, "SimpleMap: maplike get should return value entered"); + is(m.delete("test2"), true, "SimpleMap: maplike deletion should return boolean"); + is(m.size, 1, "SimpleMap: size should be 1"); + var iterable = false; + for (let e of m) { + iterable = true; + is(e[0], "test", "SimpleMap: iterable first array element should be key"); + is(e[1], 1, "SimpleMap: iterable second array element should be value"); + } + is(m[Symbol.iterator].length, 0, "SimpleMap: @@iterator symbol is correct length"); + is(m[Symbol.iterator].name, "entries", "SimpleMap: @@iterator symbol has correct name"); + is(m[Symbol.iterator], m.entries, 'SimpleMap: @@iterator is an alias for "entries"'); + ok(iterable, "SimpleMap: @@iterator symbol resolved correctly"); + for (let k of m.keys()) { + is(k, "test", "SimpleMap: first keys element should be 'test'"); + } + for (let v of m.values()) { + is(v, 1, "SimpleMap: first values elements should be 1"); + } + for (let e of m.entries()) { + is(e[0], "test", "SimpleMap: entries first array element should be 'test'"); + is(e[1], 1, "SimpleMap: entries second array element should be 1"); + } + m.clear(); + is(m.size, 0, "SimpleMap: size should be 0 after clear"); + + // Simple set creation and functionality test + info("SimpleSet: Testing simple set creation and functionality"); + m = new TestInterfaceSetlike(); + ok(m, "SimpleSet: got a TestInterfaceSetlike object"); + testExistence("SimpleSet: ", m, setlike_rw_properties); + is(m.size, 0, "SimpleSet: size should be zero"); + ok(!m.has("test"), "SimpleSet: maplike has should return false"); + m1 = m.add("test"); + is(m, m1, "SimpleSet: return from set should be map object"); + is(m.size, 1, "SimpleSet: size should be 1"); + ok(m.has("test"), "SimpleSet: maplike has should return true"); + m.add("test2"); + is(m.size, 2, "SimpleSet: size should be 2"); + testSet = ["test", "test2"]; + testIndex = 0; + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "SimpleSet: foreach obj is correct"); + is(k, testSet[testIndex], "SimpleSet: foreach set key: " + k + " = " + testSet[testIndex]); + testIndex += 1; + }); + is(testIndex, 2, "SimpleSet: foreach ran correct number of times"); + ok(m.has("test2"), "SimpleSet: maplike has should return true"); + is(m.delete("test2"), true, "SimpleSet: maplike deletion should return true"); + is(m.size, 1, "SimpleSet: size should be 1"); + iterable = false; + for (let e of m) { + iterable = true; + is(e, "test", "SimpleSet: iterable first array element should be key"); + } + is(m[Symbol.iterator].length, 0, "SimpleSet: @@iterator symbol is correct length"); + is(m[Symbol.iterator].name, "values", "SimpleSet: @@iterator symbol has correct name"); + is(m[Symbol.iterator], m.values, 'SimpleSet: @@iterator is an alias for "values"'); + ok(iterable, "SimpleSet: @@iterator symbol resolved correctly"); + for (let k of m.keys()) { + is(k, "test", "SimpleSet: first keys element should be 'test'"); + } + for (let v of m.values()) { + is(v, "test", "SimpleSet: first values elements should be 'test'"); + } + for (let e of m.entries()) { + is(e[0], "test", "SimpleSet: Entries first array element should be 'test'"); + is(e[1], "test", "SimpleSet: Entries second array element should be 'test'"); + } + m.clear(); + is(m.size, 0, "SimpleSet: size should be 0 after clear"); + + // Map convenience function test + info("Testing map convenience functions"); + m = new TestInterfaceMaplike(); + ok(m, "MapConvenience: got a TestInterfaceMaplike object"); + is(m.size, 0, "MapConvenience: size should be zero"); + ok(!m.hasInternal("test"), "MapConvenience: maplike hasInternal should return false"); + // It's fine to let getInternal to return 0 if the key doesn't exist + // because this API can only be used internally in C++ and we'd throw + // an error if the key doesn't exist. + SimpleTest.doesThrow(() => m.getInternal("test"), 0, "MapConvenience: maplike getInternal should throw if the key doesn't exist"); + m.setInternal("test", 1); + is(m.size, 1, "MapConvenience: size should be 1"); + ok(m.hasInternal("test"), "MapConvenience: maplike hasInternal should return true"); + is(m.get("test"), 1, "MapConvenience: maplike get should return value entered"); + is(m.getInternal("test"), 1, "MapConvenience: maplike getInternal should return value entered"); + m.setInternal("test2", 2); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "MapConvenience: maplike hasInternal should return true"); + is(m.get("test2"), 2, "MapConvenience: maplike get should return value entered"); + is(m.getInternal("test2"), 2, "MapConvenience: maplike getInternal should return value entered"); + is(m.deleteInternal("test2"), true, "MapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "MapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "MapConvenience: size should be 0 after clearInternal"); + + // Map convenience function test using objects and readonly + + info("Testing Map convenience function test using objects and readonly"); + m = new TestInterfaceMaplikeObject(); + ok(m, "ReadOnlyMapConvenience: got a TestInterfaceMaplikeObject object"); + is(m.size, 0, "ReadOnlyMapConvenience: size should be zero"); + is(m.set, undefined, "ReadOnlyMapConvenience: readonly map, should be no set function"); + is(m.clear, undefined, "ReadOnlyMapConvenience: readonly map, should be no clear function"); + is(m.delete, undefined, "ReadOnlyMapConvenience: readonly map, should be no delete function"); + ok(!m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return false"); + SimpleTest.doesThrow(() => m.getInternal("test"), "ReadOnlyMapConvenience: maplike getInternal should throw when the key doesn't exist"); + m.setInternal("test"); + is(m.size, 1, "size should be 1"); + ok(m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); + ok(m.getInternal("test") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); + m.setInternal("test2"); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); + ok(m.getInternal("test2") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); + is(m.deleteInternal("test2"), true, "ReadOnlyMapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "ReadOnlyMapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "ReadOnlyMapConvenience: size should be 0 after clearInternal"); + + // Map convenience function test using JavaScript objects + info("Testing Map convenience function test using javascript objects"); + m = new TestInterfaceMaplikeJSObject(); + ok(m, "JSObjectMapConvenience: got a TestInterfaceMaplikeJSObject object"); + is(m.size, 0, "JSObjectMapConvenience: size should be zero"); + is(m.set, undefined, "JSObjectMapConvenience: readonly map, should be no set function"); + is(m.clear, undefined, "JSObjectMapConvenience: readonly map, should be no clear function"); + is(m.delete, undefined, "JSObjectMapConvenience: readonly map, should be no delete function"); + ok(!m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return false"); + SimpleTest.doesThrow(() => m.getInternal("test"), "JSObjectMapConvenience: maplike getInternal should throw when the key doesn't exist"); + let testObject = {"Hey1": 1}; + m.setInternal("test", testObject); + is(m.size, 1, "size should be 1"); + ok(m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return true"); + let addedObject = m.getInternal("test"); + is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); + testObject = {"Hey2": 2}; + m.setInternal("test2", testObject); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "JSObjectMapConvenience: maplike hasInternal should return true"); + addedObject = m.getInternal("test2"); + is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); + is(m.deleteInternal("test2"), true, "JSObjectMapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "JSObjectMapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "JSObjectMapConvenience: size should be 0 after clearInternal"); + // JS implemented map creation convenience function test + + // Test this override for forEach + info("ForEachThisOverride: Testing this override for forEach"); + m = new TestInterfaceMaplike(); + m.set("test", 1); + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "ForEachThisOverride: foreach obj is correct"); + is(this, 5, "ForEachThisOverride: 'this' value should be correct"); + }, 5); + + // Test defaulting arguments on maplike to undefined + info("MapArgsDefault: Testing maplike defaulting arguments to undefined"); + m = new TestInterfaceMaplike(); + m.set(); + is(m.size, 1, "MapArgsDefault: should have 1 entry"); + m.forEach(function(v, k) { + "use strict"; + is(typeof k, "string", "MapArgsDefault: key is a string"); + is(k, "undefined", "MapArgsDefault: key is the string undefined"); + is(v, 0, "MapArgsDefault: value is 0"); + }); + is(m.get(), 0, "MapArgsDefault: no argument to get() returns correct value"); + m.delete(); + is(m.size, 0, "MapArgsDefault: should have 0 entries"); + + // Test defaulting arguments on setlike to undefined + info("SetArgsDefault: Testing setlike defaulting arguments to undefined"); + m = new TestInterfaceSetlike(); + m.add(); + is(m.size, 1, "SetArgsDefault: should have 1 entry"); + m.forEach(function(v, k) { + "use strict"; + is(typeof k, "string", "SetArgsDefault: key is a string"); + is(k, "undefined", "SetArgsDefault: key is the string undefined"); + }); + m.delete(); + is(m.size, 0, "SetArgsDefault: should have 0 entries"); + + SimpleTest.finish(); + }); + </script> + </body> +</html> diff --git a/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml new file mode 100644 index 0000000000..724c40cbd3 --- /dev/null +++ b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xhtml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1123516 +--> +<window title="Mozilla Bug 1123516" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <iframe id="t"></iframe> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1123516" + target="_blank">Mozilla Bug 1123516</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /* global TestInterfaceSetlikeNode */ + + /** Test for Bug 1123516 **/ + function doTest() { + var win = $("t").contentWindow; + var sandbox = Cu.Sandbox(win, { sandboxPrototype: win }); + is(sandbox._content, undefined, "_content does nothing over Xray"); + // Test cross-compartment usage of maplike/setlike WebIDL structures. + SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() { + try { + var maplike = Cu.evalInSandbox("var m = new TestInterfaceMaplike(); m;", sandbox); + maplike.set("test2", 2); + is(maplike.get("test2"), 2, "Should be able to create and use maplike/setlike across compartments"); + var test = Cu.evalInSandbox("m.get('test2');", sandbox); + is(test, 2, "Maplike/setlike should still work in original compartment"); + is(maplike.size, 1, "Testing size retrieval across compartments"); + } catch(e) { + ok(false, "Shouldn't throw when working with cross-compartment maplike/setlike interfaces " + e) + }; + try { + var setlike = Cu.evalInSandbox("var m = new TestInterfaceSetlikeNode(); m.add(document.documentElement); m;", sandbox); + is(TestInterfaceSetlikeNode.prototype.has.call(setlike, win.document.documentElement), true, + "Cross-compartment unwrapping/comparison has works"); + // TODO: Should throw until iterators are handled by Xrays, Bug 1023984 + try { + TestInterfaceSetlikeNode.prototype.keys.call(setlike); + ok(false, "Calling iterators via xrays should fail"); + /* eslint-disable-next-line no-shadow */ + } catch(e) { + ok(true, "Calling iterators via xrays should fail"); + } + + setlike.forEach((v,k,t) => { 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"); }); + is(TestInterfaceSetlikeNode.prototype.delete.call(setlike, win.document.documentElement), true, + "Cross-compartment unwrapping/comparison delete works"); + /* eslint-disable-next-line no-shadow */ + } catch(e) { + ok(false, "Shouldn't throw when working with cross-compartment maplike/setlike interfaces " + e) + }; + SimpleTest.finish(); + }); + } + + SimpleTest.waitForExplicitFinish(); + addLoadEvent(doTest); + ]]> + </script> +</window> diff --git a/dom/bindings/test/test_bug1123875.html b/dom/bindings/test/test_bug1123875.html new file mode 100644 index 0000000000..383d14fe9f --- /dev/null +++ b/dom/bindings/test/test_bug1123875.html @@ -0,0 +1,15 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test for Bug 1123875</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +/* global test, assert_throws */ + test(() => { + assert_throws(new TypeError, () => { + "use strict"; + document.childNodes.length = 0; + }); + }, "setting a readonly attribute on a proxy in strict mode should throw a TypeError"); +</script> diff --git a/dom/bindings/test/test_bug1287912.html b/dom/bindings/test/test_bug1287912.html new file mode 100644 index 0000000000..310a53afc6 --- /dev/null +++ b/dom/bindings/test/test_bug1287912.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1287912 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1287912</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1287912">Mozilla Bug 1287912</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> +function test() { + var win = document.getElementById("t").contentWindow; + is(Object.getPrototypeOf(win.Image), win.Function.prototype, "The __proto__ of a named constructor is Function.prototype"); + is(win.Image.prototype, win.HTMLImageElement.prototype, "The prototype property of a named constructor is the interface prototype object"); + is(win.HTMLImageElement.foo, undefined, "Should not have a property named foo on the HTMLImageElement interface object"); + is(win.Image.foo, undefined, "Should not have a property named foo on the Image named constructor"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug1457051.html b/dom/bindings/test/test_bug1457051.html new file mode 100644 index 0000000000..2ed1bd16ec --- /dev/null +++ b/dom/bindings/test/test_bug1457051.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1457051 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1457051</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1457051 **/ + ok(Element.isInstance(document.documentElement), "Basic isInstance works"); + ok(!Element.isInstance(null), + "Passing null should return false without throwing"); + ok(!Element.isInstance(5), "Passing 5 should return false without throwing"); + var obj = Object.create(Element.prototype); + ok(obj instanceof Element, "instanceof should walk the proto chain"); + ok(!Element.isInstance(obj), "isInstance should be a pure brand check"); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1457051">Mozilla Bug 1457051</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug560072.html b/dom/bindings/test/test_bug560072.html new file mode 100644 index 0000000000..de2f8baec9 --- /dev/null +++ b/dom/bindings/test/test_bug560072.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=560072 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 560072</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=560072">Mozilla Bug 560072</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 560072 **/ +is(document.body, + Object.getOwnPropertyDescriptor(Document.prototype, "body").get.call(document), + "Should get body out of property descriptor"); + +is(document.body, + Object.getOwnPropertyDescriptor( + Object.getPrototypeOf(Object.getPrototypeOf(document)), "body").get.call(document), + "Should get body out of property descriptor this way too"); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug742191.html b/dom/bindings/test/test_bug742191.html new file mode 100644 index 0000000000..f991bf6f91 --- /dev/null +++ b/dom/bindings/test/test_bug742191.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742191 +--> +<head> + <meta charset="utf-8"> + <title>Test for invalid argument object</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742191">Mozilla Bug 742191</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742191 **/ +function doTest() { + var gotTypeError = false; + var ctx = document.createElement("canvas").getContext("2d"); + try { + ctx.drawImage({}, 0, 0); + } catch (e) { + if (e instanceof TypeError) { + gotTypeError = true; + } + } + + ok(gotTypeError, "passing an invalid argument should cause a type error!"); +} +doTest(); +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug759621.html b/dom/bindings/test/test_bug759621.html new file mode 100644 index 0000000000..7c47887d35 --- /dev/null +++ b/dom/bindings/test/test_bug759621.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=759621 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 759621</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759621">Mozilla Bug 759621</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 759621 **/ +var l = document.getElementsByTagName("*"); +l.namedItem = "pass"; +is(l.namedItem, "pass", "Should be able to set expando shadowing a proto prop"); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug773326.html b/dom/bindings/test/test_bug773326.html new file mode 100644 index 0000000000..cb21ae6916 --- /dev/null +++ b/dom/bindings/test/test_bug773326.html @@ -0,0 +1,13 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test for Bug 773326</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +/* global test */ + +test(function() { + new Worker("data:text/javascript,new XMLHttpRequest(42)"); +}, "Should not crash"); +</script> diff --git a/dom/bindings/test/test_bug775543.html b/dom/bindings/test/test_bug775543.html new file mode 100644 index 0000000000..d8fe8aaf2b --- /dev/null +++ b/dom/bindings/test/test_bug775543.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=775543 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 775543</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775543">Mozilla Bug 775543</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_bug775543.html" onload="test();"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> +/* global XPCNativeWrapper */ +/** Test for Bug 775543 **/ + +function test() { + var a = XPCNativeWrapper(document.getElementById("t").contentWindow.wrappedJSObject.worker); + isnot(XPCNativeWrapper.unwrap(a), a, "XPCNativeWrapper(Worker) should be an Xray wrapper"); + a.toString(); + ok(true, "Shouldn't crash when calling a method on an Xray wrapper around a worker"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug788369.html b/dom/bindings/test/test_bug788369.html new file mode 100644 index 0000000000..02d03ac199 --- /dev/null +++ b/dom/bindings/test/test_bug788369.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=788369 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 788369</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=788369">Mozilla Bug 788369</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 788369 **/ +try { + var xhr = new (window.ActiveXObject || XMLHttpRequest)("Microsoft.XMLHTTP"); + ok(xhr instanceof XMLHttpRequest, "Should have an XHR object"); +} catch (e) { + ok(false, "Should not throw exception when constructing: " + e); +} +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug852846.html b/dom/bindings/test/test_bug852846.html new file mode 100644 index 0000000000..19ec39dae5 --- /dev/null +++ b/dom/bindings/test/test_bug852846.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=852846 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 852846</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 852846 **/ + var elem = document.createElement("div"); + is(elem.style.color, "", "Shouldn't have color set on HTML element"); + elem.style = "color: green"; + is(elem.style.color, "green", "Should have color set on HTML element"); + + elem = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + is(elem.style.color, "", "Shouldn't have color set on SVG element"); + elem.style = "color: green"; + is(elem.style.color, "green", "Should have color set on SVG element"); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=852846">Mozilla Bug 852846</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_bug862092.html b/dom/bindings/test/test_bug862092.html new file mode 100644 index 0000000000..871252660a --- /dev/null +++ b/dom/bindings/test/test_bug862092.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=862092 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 862092</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 862092 **/ + + SimpleTest.waitForExplicitFinish(); + function runTest() { + var frameDoc = document.getElementById("f").contentDocument; + var a = document.createElement("select"); + a.expando = "test"; + a = frameDoc.adoptNode(a); + is(a.expando, "test", "adoptNode needs to preserve expandos"); + SimpleTest.finish(); + } + + </script> +</head> +<body onload="runTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=862092">Mozilla Bug 862092</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="f"></iframe> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_callback_across_document_open.html b/dom/bindings/test/test_callback_across_document_open.html new file mode 100644 index 0000000000..dee4445904 --- /dev/null +++ b/dom/bindings/test/test_callback_across_document_open.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for callback invocation for a callback that comes from a + no-longer-current window that still has an active document.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe srcdoc='<script>function f() { parent.callCount++; }</script>'></iframe> +<script> +/* global async_test, assert_equals */ + var callCount = 0; + var t = async_test("A test of callback invocation in a no-longer-current window with a still-active document"); + window.addEventListener("load", t.step_func_done(function() { + var d = document.createElement("div"); + d.addEventListener("xyz", frames[0].f); + frames[0].document.open(); + frames[0].document.write("All gone"); + frames[0].document.close(); + d.dispatchEvent(new Event("xyz")); + assert_equals(callCount, 1, "Callback should have been called"); + })); +</script> diff --git a/dom/bindings/test/test_callback_default_thisval.html b/dom/bindings/test/test_callback_default_thisval.html new file mode 100644 index 0000000000..337657b21f --- /dev/null +++ b/dom/bindings/test/test_callback_default_thisval.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=957929 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 957929</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 957929 **/ + SimpleTest.waitForExplicitFinish(); + + function f() { + "use strict"; + is(this, undefined, "Should have undefined this value"); + SimpleTest.finish(); + } + + addLoadEvent(function() { + requestAnimationFrame(f); + }); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=957929">Mozilla Bug 957929</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_callback_exceptions.html b/dom/bindings/test/test_callback_exceptions.html new file mode 100644 index 0000000000..93d4787774 --- /dev/null +++ b/dom/bindings/test/test_callback_exceptions.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for ...</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +/* global promise_test, promise_rejects */ + +promise_test(function(t) { + var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, JSON.parse); + return promise_rejects(t, new SyntaxError, + Promise.resolve().then(iterator.nextNode.bind(iterator))); +}, "Trying to use JSON.parse as filter should throw a catchable SyntaxError exception even when the filter is invoked async"); + +promise_test(function(t) { + return promise_rejects(t, new SyntaxError, Promise.resolve("{").then(JSON.parse)); +}, "Trying to use JSON.parse as a promise callback should allow the next promise to handle the resulting exception."); +</script> diff --git a/dom/bindings/test/test_cloneAndImportNode.html b/dom/bindings/test/test_cloneAndImportNode.html new file mode 100644 index 0000000000..4acfec82cd --- /dev/null +++ b/dom/bindings/test/test_cloneAndImportNode.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=882541 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 882541</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 882541 **/ + var div = document.createElement("div"); + div.appendChild(document.createElement("span")); + + var div2; + + div2 = div.cloneNode(); + is(div2.childNodes.length, 0, "cloneNode() should do a shallow clone"); + + div2 = div.cloneNode(undefined); + is(div2.childNodes.length, 0, "cloneNode(undefined) should do a shallow clone"); + + div2 = div.cloneNode(true); + is(div2.childNodes.length, 1, "cloneNode(true) should do a deep clone"); + + div2 = document.importNode(div); + is(div2.childNodes.length, 0, "importNode(node) should do a deep import"); + + div2 = document.importNode(div, undefined); + is(div2.childNodes.length, 0, "importNode(undefined) should do a shallow import"); + + div2 = document.importNode(div, true); + is(div2.childNodes.length, 1, "importNode(true) should do a deep import"); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=882541">Mozilla Bug 882541</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_crossOriginWindowSymbolAccess.html b/dom/bindings/test/test_crossOriginWindowSymbolAccess.html new file mode 100644 index 0000000000..0ece6c8f9d --- /dev/null +++ b/dom/bindings/test/test_crossOriginWindowSymbolAccess.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for accessing symbols on a cross-origin window</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe id="sameProc" src="http://test1.mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe> +<iframe id="crossProc" src="http://www1.w3c-test.org/common/blank.html"></iframe> +<script> +/* global async_test, assert_equals, assert_throws */ + +async_test(function(t) { + window.addEventListener("load", t.step_func( + function() { + assert_equals(document.getElementById("sameProc").contentDocument, null, "Should have a crossorigin frame"); + assert_equals(document.getElementById("crossProc").contentDocument, null, "Should have a crossorigin frame"); + for (let f of [0, 1]) { + assert_throws("SecurityError", function() { + frames[f][Symbol.iterator]; + }, "Should throw exception on cross-origin Window symbol-named get"); + assert_throws("SecurityError", function() { + frames[f].location[Symbol.iterator]; + }, "Should throw exception on cross-origin Location symbol-named get"); + } + t.done(); + } + )); +}, "Check Symbol access on load"); +</script> diff --git a/dom/bindings/test/test_defineProperty.html b/dom/bindings/test/test_defineProperty.html new file mode 100644 index 0000000000..391c6fcac8 --- /dev/null +++ b/dom/bindings/test/test_defineProperty.html @@ -0,0 +1,157 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=910220 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 910220</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910220">Mozilla Bug 910220</a> +<p id="display"></p> +<div id="content" style="display: none"> +<form name="x"></form> +</div> +<pre id="test"> +</pre> +<script type="application/javascript"> + +/** Test for Bug 910220 **/ + +function getX() { + return "x"; +} + +function namedSetStrict(obj) { + "use strict"; + var threw; + try { + obj.x = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when setting named property on " + obj); + + try { + obj[getX()] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when setting named property via SETELEM on " + obj); + + try { + Object.defineProperty(obj, "x", { value: 17 }); + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when defining named property on " + obj); +} +function namedSetNonStrict(obj) { + var threw; + try { + obj.x = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(!threw, + "Should not throw in non-strict mode when setting named property on " + obj); + + try { + obj[getX()] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(!threw, + "Should not throw in non-strict mode when setting named property via SETELEM on" + obj); + + try { + Object.defineProperty(obj, "x", { value: 17 }); + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in non-strict mode when defining named property on " + obj); +} +for (let obj of [ document, document.forms ]) { + namedSetStrict(obj); + namedSetNonStrict(obj); +} + +function indexedSetStrict(obj) { + "use strict"; + var threw; + try { + obj[0] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when setting indexed property on " + obj); + + try { + obj[1000] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when setting out of bounds indexed property on " + obj); + + try { + Object.defineProperty(obj, "0", { value: 17 }); + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in strict mode when defining indexed property on " + obj); +} +function indexedSetNonStrict(obj) { + var threw; + try { + obj[0] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(!threw, + "Should not throw in non-strict mode when setting indexed property on " + obj); + + try { + obj[1000] = 5; + threw = false; + } catch (e) { + threw = true; + } + ok(!threw, + "Should not throw in non-strict mode when setting out of bounds indexed property on " + obj); + + try { + Object.defineProperty(obj, "0", { value: 17 }); + threw = false; + } catch (e) { + threw = true; + } + ok(threw, + "Should throw in non-strict mode when defining indexed property on " + obj); +} +for (let obj of [ document.forms, document.childNodes ]) { + indexedSetStrict(obj); + indexedSetNonStrict(obj); +} +</script> +</body> +</html> diff --git a/dom/bindings/test/test_document_location_set_via_xray.html b/dom/bindings/test/test_document_location_set_via_xray.html new file mode 100644 index 0000000000..2c8d01aeda --- /dev/null +++ b/dom/bindings/test/test_document_location_set_via_xray.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=905493 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 905493</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=905493">Mozilla Bug 905493</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_document_location_set_via_xray.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 905493 **/ + +function test() { + var doc = document.getElementById("t").contentWindow.document; + ok(!("x" in doc), "Should have an Xray here"); + is(doc.x, undefined, "Really should have an Xray here"); + is(doc.wrappedJSObject.x, 5, "And wrapping the right thing"); + document.getElementById("t").onload = function() { + ok(true, "Load happened"); + SimpleTest.finish(); + }; + try { + // Test the forwarding location setter + doc.location = "chrome://mochikit/content/tests/SimpleTest/test.css"; + } catch (e) { + // Load failed + ok(false, "Load failed"); + SimpleTest.finish(); + } +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_document_location_via_xray_cached.html b/dom/bindings/test/test_document_location_via_xray_cached.html new file mode 100644 index 0000000000..f47f78cd55 --- /dev/null +++ b/dom/bindings/test/test_document_location_via_xray_cached.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1041731 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1041731</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1041731">Mozilla Bug 1041731</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_document_location_set_via_xray.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1041731 **/ + +function test() { + var loc = document.getElementById("t").contentWindow.document.location; + is(loc.toString, loc.toString, "Unforgeable method on the Xray should be cached"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_domProxyArrayLengthGetter.html b/dom/bindings/test/test_domProxyArrayLengthGetter.html new file mode 100644 index 0000000000..e2ce1fb870 --- /dev/null +++ b/dom/bindings/test/test_domProxyArrayLengthGetter.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1221421 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1221421</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript"> + + var x = document.documentElement.style; + x.__proto__ = [1, 2, 3]; + + var res = 0; + for (var h = 0; h < 5000; ++h) { + res += x.length; + } + is(res, 15000, "length getter should return array length"); + + </script> +</head> + +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1221421">Mozilla Bug 1221421</a> +</body> +</html> diff --git a/dom/bindings/test/test_dom_xrays.html b/dom/bindings/test/test_dom_xrays.html new file mode 100644 index 0000000000..12d8d230db --- /dev/null +++ b/dom/bindings/test/test_dom_xrays.html @@ -0,0 +1,339 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787070 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 787070</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787070">Mozilla Bug 787070</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_dom_xrays.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1021066 **/ + +// values should contain the values that the property should have on each of +// the objects on the prototype chain of obj. A value of undefined signals +// that the value should not be present on that prototype. +function checkXrayProperty(obj, name, values) { + var instance = obj; + do { + var value = values.shift(); + if (typeof value == "undefined") { + ok(!obj.hasOwnProperty(name), "hasOwnProperty shouldn't see \"" + String(name) + "\" through Xrays"); + is(Object.getOwnPropertyDescriptor(obj, name), undefined, "getOwnPropertyDescriptor shouldn't see \"" + String(name) + "\" through Xrays"); + ok(!Object.keys(obj).includes(name), "Enumerating the Xray should not return \"" + String(name) + "\""); + ok(!Object.getOwnPropertyNames(obj).includes(name), + `The Xray's property names should not include ${String(name)}`); + ok(!Object.getOwnPropertySymbols(obj).includes(name), + `The Xray's property symbols should not include ${String(name)}`); + } else { + ok(obj.hasOwnProperty(name), "hasOwnProperty should see \"" + String(name) + "\" through Xrays"); + var pd = Object.getOwnPropertyDescriptor(obj, name); + ok(pd, "getOwnPropertyDescriptor should see \"" + String(name) + "\" through Xrays"); + if (pd && pd.get) { + is(pd.get.call(instance), value, "Should get the right value for \"" + String(name) + "\" through Xrays"); + } else { + is(obj[name], value, "Should get the right value for \"" + String(name) + "\" through Xrays"); + } + if (pd) { + if (pd.enumerable) { + ok(Object.keys(obj).indexOf("" + name) > -1, "Enumerating the Xray should return \"" + String(name) + "\""); + } + if (typeof name == "symbol") { + ok(Object.getOwnPropertySymbols(obj).includes(name), + `The Xray's property symbols should include ${String(name)}`); + } else { + ok(Object.getOwnPropertyNames(obj).includes("" + name), + `The Xray's property names should include ${name}`); + } + } + } + } while ((obj = Object.getPrototypeOf(obj))); +} + +function checkWindowXrayProperty(obj, name, windowValue, windowPrototypeValue, namedPropertiesValue, eventTargetValue) { + checkXrayProperty(obj, name, [ windowValue, windowPrototypeValue, namedPropertiesValue, eventTargetValue ]); +} + +function test() { + // Window + var win = document.getElementById("t").contentWindow; + var doc = document.getElementById("t").contentDocument; + + var winProto = Object.getPrototypeOf(win); + is(winProto, win.Window.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + var namedPropertiesObject = Object.getPrototypeOf(winProto); + is(Cu.getClassName(namedPropertiesObject, /* unwrap = */ true), "WindowProperties", "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + var eventTargetProto = Object.getPrototypeOf(namedPropertiesObject); + is(eventTargetProto, win.EventTarget.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + // Xrays need to filter expandos. + checkWindowXrayProperty(win, "expando", undefined); + ok(!("expando" in win), "Xrays should filter expandos"); + + checkWindowXrayProperty(win, "shadowedIframe", undefined); + ok(!("shadowedIframe" in win), "Named properties should not be exposed through Xrays"); + + // Named properties live on the named properties object for global objects, + // but are not exposed via Xrays. + checkWindowXrayProperty(win, "iframe", undefined, undefined, undefined, undefined); + ok(!("iframe" in win), "Named properties should not be exposed through Xrays"); + + // Window properties live on the instance, shadowing the properties of the named property object. + checkWindowXrayProperty(win, "document", doc, undefined, undefined, undefined); + ok("document" in win, "WebIDL properties should be exposed through Xrays"); + + // Unforgeable properties live on the instance, shadowing the properties of the named property object. + checkWindowXrayProperty(win, "self", win, undefined, undefined, undefined); + ok("self" in win, "WebIDL properties should be exposed through Xrays"); + + // Object.prototype is at the end of the prototype chain. + var obj = win; + var proto; + while ((proto = Object.getPrototypeOf(obj))) { + obj = proto; + } + is(obj, win.Object.prototype, "Object.prototype should be at the end of the prototype chain"); + + // Named properties shouldn't shadow WebIDL- or ECMAScript-defined properties. + checkWindowXrayProperty(win, "addEventListener", undefined, undefined, undefined, eventTargetProto.addEventListener); + is(win.addEventListener, eventTargetProto.addEventListener, "Named properties shouldn't shadow WebIDL-defined properties"); + + is(win.toString, win.Object.prototype.toString, "Named properties shouldn't shadow ECMAScript-defined properties"); + + // WebIDL interface names should be exposed. + var waivedWin = Cu.waiveXrays(win); + checkWindowXrayProperty(win, "Element", Cu.unwaiveXrays(waivedWin.Element)); + + // JS standard classes should be exposed. + checkWindowXrayProperty(win, "Array", Cu.unwaiveXrays(waivedWin.Array)); + + // HTMLDocument + // Unforgeable properties live on the instance. + checkXrayProperty(doc, "location", [ win.location ]); + is(String(win.location), document.getElementById("t").src, + "Should have the right stringification"); + + // HTMLHtmlElement + var elem = doc.documentElement; + + var elemProto = Object.getPrototypeOf(elem); + is(elemProto, win.HTMLHtmlElement.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + elemProto = Object.getPrototypeOf(elemProto); + is(elemProto, win.HTMLElement.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + elemProto = Object.getPrototypeOf(elemProto); + is(elemProto, win.Element.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + elemProto = Object.getPrototypeOf(elemProto); + is(elemProto, win.Node.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + elemProto = Object.getPrototypeOf(elemProto); + is(elemProto, win.EventTarget.prototype, "The proto chain of the Xray should mirror the prototype chain of the Xrayed object"); + + // Xrays need to filter expandos. + ok(!("expando" in elem), "Xrays should filter expandos"); + + // WebIDL-defined properties live on the prototype. + checkXrayProperty(elem, "version", [ undefined, "" ]); + is(elem.version, "", "WebIDL properties should be exposed through Xrays"); + + // HTMLCollection + var coll = doc.getElementsByTagName("iframe"); + + // Named properties live on the instance for non-global objects. + checkXrayProperty(coll, "iframe", [ doc.getElementById("iframe") ]); + + // Indexed properties live on the instance. + checkXrayProperty(coll, 0, [ doc.getElementById("shadowedIframe") ]); + + // WebIDL-defined properties live on the prototype, overriding any named properties. + checkXrayProperty(coll, "item", [ undefined, win.HTMLCollection.prototype.item ]); + + // ECMAScript-defined properties live on the prototype, overriding any named properties. + checkXrayProperty(coll, "toString", [ undefined, undefined, win.Object.prototype.toString ]); + + // Frozen arrays should come from our compartment, not the target one. + var languages1 = win.navigator.languages; + isnot(languages1, undefined, "Must have .languages"); + ok(Array.isArray(languages1), ".languages should be an array"); + ok(Object.isFrozen(languages1), ".languages should be a frozen array"); + ok(!Cu.isXrayWrapper(languages1), "Should have our own version of array"); + is(Cu.getGlobalForObject(languages1), window, + "languages1 should come from our window"); + // We want to get .languages in the content compartment, but without waiving + // Xrays altogether. + var languages2 = win.eval("navigator.languages"); + isnot(languages2, undefined, "Must still have .languages"); + ok(Array.isArray(languages2), ".languages should still be an array"); + ok(Cu.isXrayWrapper(languages2), "Should have xray for content version of array"); + is(Cu.getGlobalForObject(languages2), win, + "languages2 come from the underlying window"); + ok(Object.isFrozen(languages2.wrappedJSObject), + ".languages should still be a frozen array underneath"); + isnot(languages1, languages2, "Must have distinct arrays"); + isnot(languages1, languages2.wrappedJSObject, + "Must have distinct arrays no matter how we slice it"); + + // Check that DataTransfer's .types has the hack to alias contains() + // to includes(). + var dataTransfer = new win.DataTransfer(); + is(dataTransfer.types.contains, dataTransfer.types.includes, + "Should have contains() set up as an alias to includes()"); + // Waive Xrays on the dataTransfer itself, since the .types we get is + // different over Xrays vs not. + is(dataTransfer.wrappedJSObject.types.contains, undefined, + "Underlying object should not have contains() set up as an alias to " + + "includes()"); + + // Check that deleters work correctly in the [OverrideBuiltins] case. + elem = win.document.documentElement; + var dataset = elem.dataset; + is(dataset.foo, undefined, "Should not have a 'foo' property"); + ok(!("foo" in dataset), "Really should not have a 'foo' property"); + is(elem.getAttribute("data-foo"), null, + "Should not have a 'data-foo' attribute"); + ok(!elem.hasAttribute("data-foo"), + "Really should not have a 'data-foo' attribute"); + dataset.foo = "bar"; + is(dataset.foo, "bar", "Should now have a 'foo' property"); + ok("foo" in dataset, "Really should have a 'foo' property"); + is(elem.getAttribute("data-foo"), "bar", + "Should have a 'data-foo' attribute"); + ok(elem.hasAttribute("data-foo"), + "Really should have a 'data-foo' attribute"); + delete dataset.foo; + is(dataset.foo, undefined, "Should not have a 'foo' property again"); + ok(!("foo" in dataset), "Really should not have a 'foo' property again"); + is(elem.getAttribute("data-foo"), null, + "Should not have a 'data-foo' attribute again"); + ok(!elem.hasAttribute("data-foo"), + "Really should not have a 'data-foo' attribute again"); + + // Check that deleters work correctly in the non-[OverrideBuiltins] case. + var storage = win.sessionStorage; + is(storage.foo, undefined, "Should not have a 'foo' property"); + ok(!("foo" in storage), "Really should not have a 'foo' property"); + is(storage.getItem("foo"), null, "Should not have an item named 'foo'"); + storage.foo = "bar"; + is(storage.foo, "bar", "Should have a 'foo' property"); + ok("foo" in storage, "Really should have a 'foo' property"); + is(storage.getItem("foo"), "bar", "Should have an item named 'foo'"); + delete storage.foo; + is(storage.foo, undefined, "Should not have a 'foo' property again"); + ok(!("foo" in storage), "Really should not have a 'foo' property again"); + is(storage.getItem("foo"), null, "Should not have an item named 'foo' again"); + + // Non-static properties are not exposed on interface objects or instances. + is(win.HTMLInputElement.checkValidity, undefined, + "Shouldn't see non-static property on interface objects"); + is(Object.getOwnPropertyDescriptor(win.HTMLInputElement, "checkValidity"), undefined, + "Shouldn't see non-static property on interface objects"); + is(Object.getOwnPropertyNames(win.HTMLInputElement).indexOf("checkValidity"), -1, + "Shouldn't see non-static property on interface objects"); + isnot(typeof doc.createElement("input").checkValidity, "undefined", + "Should see non-static property on prototype objects"); + is(Object.getOwnPropertyDescriptor(doc.createElement("input"), "checkValidity"), undefined, + "Shouldn't see non-static property on instances"); + isnot(typeof Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, "checkValidity"), "undefined", + "Should see non-static property on prototype objects"); + + // Static properties are not exposed on prototype objects or instances. + isnot(typeof win.URL.createObjectURL, "undefined", + "Should see static property on interface objects"); + isnot(typeof Object.getOwnPropertyDescriptor(win.URL, "createObjectURL"), "undefined", + "Should see static property on interface objects"); + isnot(Object.getOwnPropertyNames(win.URL).indexOf("createObjectURL"), -1, + "Should see static property on interface objects"); + is(new URL("http://example.org").createObjectURL, undefined, + "Shouldn't see static property on instances and prototype ojbects"); + is(Object.getOwnPropertyDescriptor(new URL("http://example.org"), "createObjectURL"), undefined, + "Shouldn't see static property on instances"); + is(Object.getOwnPropertyDescriptor(win.URL.prototype, "createObjectURL"), undefined, + "Shouldn't see static property on prototype objects"); + + // Unforgeable properties are not exposed on prototype objects or interface + // objects. + is(Window.document, undefined, + "Shouldn't see unforgeable property on interface objects"); + is(Object.getOwnPropertyDescriptor(Window, "document"), undefined, + "Shouldn't see unforgeable property on interface objects"); + is(Object.getOwnPropertyNames(Window).indexOf("document"), -1, + "Shouldn't see unforgeable property on interface objects"); + isnot(typeof win.document, "undefined", + "Should see unforgeable property on instances"); + isnot(typeof Object.getOwnPropertyDescriptor(win, "document"), "undefined", + "Should see unforgeable property on instances"); + is(Object.getOwnPropertyDescriptor(Window.prototype, "document"), undefined, + "Shouldn't see unforgeable property on prototype objects"); + + // Constant properties are not exposted on instances. + isnot(typeof win.Node.ELEMENT_NODE, "undefined", + "Should see constant property on interface objects"); + isnot(typeof Object.getOwnPropertyDescriptor(win.Node, "ELEMENT_NODE"), "undefined", + "Should see constant property on interface objects"); + isnot(Object.getOwnPropertyNames(win.Node).indexOf("ELEMENT_NODE"), -1, + "Should see constant property on interface objects"); + isnot(typeof elem.ELEMENT_NODE, "undefined", + "Should see constant property on prototype objects"); + is(Object.getOwnPropertyDescriptor(elem, "ELEMENT_NODE"), undefined, + "Shouldn't see constant property on instances"); + isnot(typeof Object.getOwnPropertyDescriptor(win.Node.prototype, "ELEMENT_NODE"), "undefined", + "Should see constant property on prototype objects"); + + // Adopting nodes should not lose expandos. + elem = document.createElement("span"); + elem.expando = 5; + is(elem.expando, 5, "We just set this property"); + document.adoptNode(elem); + is(elem.wrappedJSObject, undefined, "Shouldn't be an Xray anymore"); + is(elem.expando, 5, "Expando should not get lost"); + + // Instanceof tests + var img = doc.createElement("img"); + var img2 = document.createElement("img"); + ok(img instanceof win.HTMLImageElement, + "Should be an instance of HTMLImageElement from its global"); + ok(win.HTMLImageElement.isInstance(img), "isInstance should work"); + ok(HTMLImageElement.isInstance(img), "isInstance should work cross-global"); + ok(win.HTMLImageElement.isInstance(img2), + "isInstance should work cross-global in the other direction"); + ok(img instanceof win.Image, + "Should be an instance of Image, because Image.prototype == HTMLImageElement.prototype"); + ok(!win.Image.isInstance, "Shouldn't have an isInstance method here"); + // Image does not have a Symbol.hasInstance, but its proto + // (Function.prototype) does. + checkXrayProperty(win.Image, Symbol.hasInstance, + [undefined, win.Function.prototype[Symbol.hasInstance]]); + + // toString/@@toStringTag + let imageConstructor = win.Image; + is(win.Function.prototype.toString.apply(imageConstructor), + Function.prototype.toString.apply(Image), + "Applying Function.prototype.toString through an Xray should give the same result as applying it directly"); + isDeeply(Object.getOwnPropertyDescriptor(win.CSS, Symbol.toStringTag), + Object.getOwnPropertyDescriptor(CSS, Symbol.toStringTag), + "Getting @@toStringTag on a namespace object through an Xray should give the same result as getting it directly"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_enums.html b/dom/bindings/test/test_enums.html new file mode 100644 index 0000000000..95f23885bb --- /dev/null +++ b/dom/bindings/test/test_enums.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>Enums</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +/* global test, assert_equals */ +test(function() { + var xhr = new XMLHttpRequest(); + xhr.open("get", "foo"); + assert_equals(xhr.responseType, ""); + xhr.responseType = "foo"; + assert_equals(xhr.responseType, ""); +}, "Assigning an invalid value to an enum attribute should not throw."); +</script> diff --git a/dom/bindings/test/test_exceptionSanitization.html b/dom/bindings/test/test_exceptionSanitization.html new file mode 100644 index 0000000000..818d750136 --- /dev/null +++ b/dom/bindings/test/test_exceptionSanitization.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1295322 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1295322</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295322">Mozilla Bug 1295322</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + /* global TestFunctions */ + SimpleTest.waitForExplicitFinish(); + async function runTests() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); + + var t = new TestFunctions(); + + try { + t.testThrowNsresult(); + } catch (e) { + try { + is(e.name, "NS_BINDING_ABORTED", "Should have the right exception"); + is(e.filename, location.href, "Should not be seeing where the exception really came from"); + } catch (e2) { + ok(false, "Should be able to work with the exception"); + } + } + + try { + t.testThrowNsresultFromNative(); + } catch (e) { + try { + is(e.name, "NS_ERROR_UNEXPECTED", "Should have the right exception"); + is(e.filename, location.href, "Should not be seeing where the exception really came from"); + } catch (e2) { + ok(false, "Should be able to work with the exception"); + } + } + + SimpleTest.finish(); + } + + runTests(); + </script> +</body> +</html> diff --git a/dom/bindings/test/test_exceptionThrowing.html b/dom/bindings/test/test_exceptionThrowing.html new file mode 100644 index 0000000000..571d21b485 --- /dev/null +++ b/dom/bindings/test/test_exceptionThrowing.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=847119 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 847119</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 847119 **/ + + var xhr = new XMLHttpRequest(); + var domthrows = function() { xhr.open(); }; + + var count = 20000; + + function f() { + var k = 0; + for (var j = 0; j < count; ++j) { + try { domthrows(); } catch (e) { ++k; } + } + return k; + } + function g() { return count; } + + is(f(), count, "Should get count exceptions"); + for (let h of [f, g]) { + try { is(h(), count, "Should get count exceptions here too"); } catch (e) {} + } + ok(true, "We should get here"); + + domthrows = function() { xhr.withCredentials = false; }; + xhr.open("GET", ""); + xhr.send(); + + is(f(), count, "Should get count exceptions from getter"); + for (let h of [f, g]) { + try { is(h(), count, "Should get count exceptions from getter here too"); } catch (e) {} + } + ok(true, "We should get here too"); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=847119">Mozilla Bug 847119</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_exception_messages.html b/dom/bindings/test/test_exception_messages.html new file mode 100644 index 0000000000..ffa1937e7e --- /dev/null +++ b/dom/bindings/test/test_exception_messages.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=882653 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 882653</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 882653 **/ + // Each test is a string to eval, the expected exception message, and the + // test description. + var tests = [ + [ "document.documentElement.appendChild.call({}, new Image())", + "'appendChild' called on an object that does not implement interface Node.", + "bogus method this object" ], + [ 'Object.getOwnPropertyDescriptor(Document.prototype, "documentElement").get.call({})', + "'get documentElement' called on an object that does not implement interface Document.", + "bogus getter this object" ], + [ 'Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML").set.call({})', + "'set innerHTML' called on an object that does not implement interface Element.", + "bogus setter this object" ], + [ "document.documentElement.appendChild(5)", + "Node.appendChild: Argument 1 is not an object.", + "bogus interface argument" ], + [ "document.documentElement.appendChild(null)", + "Node.appendChild: Argument 1 is not an object.", + "null interface argument" ], + [ "document.createTreeWalker(document).currentNode = 5", + "TreeWalker.currentNode setter: Value being assigned is not an object.", + "interface setter call" ], + [ "document.documentElement.appendChild({})", + "Node.appendChild: Argument 1 does not implement interface Node.", + "wrong interface argument" ], + [ "document.createTreeWalker(document).currentNode = {}", + "TreeWalker.currentNode setter: Value being assigned does not implement interface Node.", + "wrong interface setter call" ], + [ 'document.createElement("canvas").getContext("2d").fill("bogus")', + "CanvasRenderingContext2D.fill: 'bogus' (value of argument 1) is not a valid value for enumeration CanvasWindingRule.", + "bogus enum value" ], + [ "document.createTreeWalker(document, 0xFFFFFFFF, { acceptNode: 5 }).nextNode()", + "Property 'acceptNode' is not callable.", + "non-callable callback interface operation property" ], + [ "(new TextDecoder).decode(new Uint8Array(), 5)", + "TextDecoder.decode: Argument 2 can't be converted to a dictionary.", + "primitive passed for a dictionary" ], + [ "URL.createObjectURL(null)", + "URL.createObjectURL: Argument 1 is not valid for any of the 1-argument overloads.", + "overload resolution failure" ], + [ 'document.createElement("select").add({})', + "HTMLSelectElement.add: Argument 1 could not be converted to any of: HTMLOptionElement, HTMLOptGroupElement.", + "invalid value passed for union" ], + [ 'document.createElement("canvas").getContext("2d").createLinearGradient(0, 1, 0, 1).addColorStop(NaN, "")', + "CanvasGradient.addColorStop: Argument 1 is not a finite floating-point value.", + "invalid float" ], + ]; + + for (var i = 0; i < tests.length; ++i) { + var msg = "Correct exception should be thrown for " + tests[i][2]; + try { + // eslint-disable-next-line no-eval + eval(tests[i][0]); + ok(false, msg); + } catch (e) { + is(e.message, tests[i][1], msg); + } + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=882653">Mozilla Bug 882653</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_exception_options_from_jsimplemented.html b/dom/bindings/test/test_exception_options_from_jsimplemented.html new file mode 100644 index 0000000000..d7d243b0d0 --- /dev/null +++ b/dom/bindings/test/test_exception_options_from_jsimplemented.html @@ -0,0 +1,166 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1107592 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1107592</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS */ + /** Test for Bug 1107592 **/ + + SimpleTest.waitForExplicitFinish(); + + function doTest() { + var file = location.href; + + var asyncFrame; + /* Async parent frames from pushPrefEnv don't show up in e10s. */ + if (!SpecialPowers.getBoolPref("javascript.options.asyncstack_capture_debuggee_only")) { + asyncFrame = `Async*@${file}:153:17 +`; + } else { + asyncFrame = ""; + } + + var t = new TestInterfaceJS(); + try { + t.testThrowError(); + } catch (e) { + ok(e instanceof Error, "Should have an Error here"); + ok(!(e instanceof DOMException), "Should not have DOMException here"); + ok(!("code" in e), "Should not have a 'code' property"); + is(e.name, "Error", "Should not have an interesting name here"); + is(e.message, "We are an Error", "Should have the right message"); + is(e.stack, + `doTest@${file}:31:9 +${asyncFrame}`, + "Exception stack should still only show our code"); + is(e.fileName, + file, + "Should have the right file name"); + is(e.lineNumber, 31, "Should have the right line number"); + is(e.columnNumber, 9, "Should have the right column number"); + } + + try { + t.testThrowDOMException(); + } catch (e) { + ok(e instanceof Error, "Should also have an Error here"); + ok(e instanceof DOMException, "Should have DOMException here"); + is(e.name, "NotSupportedError", "Should have the right name here"); + is(e.message, "We are a DOMException", + "Should also have the right message"); + is(e.code, DOMException.NOT_SUPPORTED_ERR, + "Should have the right 'code'"); + is(e.stack, + `doTest@${file}:50:9 +${asyncFrame}`, + "Exception stack should still only show our code"); + is(e.filename, + file, + "Should still have the right file name"); + is(e.lineNumber, 50, "Should still have the right line number"); + todo_isnot(e.columnNumber, 0, + "No column number support for DOMException yet"); + } + + try { + t.testThrowTypeError(); + } catch (e) { + ok(e instanceof TypeError, "Should have a TypeError here"); + ok(!(e instanceof DOMException), "Should not have DOMException here (2)"); + ok(!("code" in e), "Should not have a 'code' property (2)"); + is(e.name, "TypeError", "Should be named TypeError"); + is(e.message, "We are a TypeError", + "Should also have the right message (2)"); + is(e.stack, + `doTest@${file}:72:9 +${asyncFrame}`, + "Exception stack for TypeError should only show our code"); + is(e.fileName, + file, + "Should still have the right file name for TypeError"); + is(e.lineNumber, 72, "Should still have the right line number for TypeError"); + is(e.columnNumber, 9, "Should have the right column number for TypeError"); + } + + try { + t.testThrowCallbackError(function() { Array.prototype.forEach(); }); + } catch (e) { + ok(e instanceof TypeError, "Should have a TypeError here (3)"); + ok(!(e instanceof DOMException), "Should not have DOMException here (3)"); + ok(!("code" in e), "Should not have a 'code' property (3)"); + is(e.name, "TypeError", "Should be named TypeError (3)"); + is(e.message, "missing argument 0 when calling function Array.prototype.forEach", + "Should also have the right message (3)"); + is(e.stack, + `doTest/<@${file}:92:61 +doTest@${file}:92:9 +${asyncFrame}`, + "Exception stack for TypeError should only show our code (3)"); + is(e.fileName, + file, + "Should still have the right file name for TypeError (3)"); + is(e.lineNumber, 92, "Should still have the right line number for TypeError (3)"); + is(e.columnNumber, 61, "Should have the right column number for TypeError (3)"); + } + + try { + t.testThrowXraySelfHosted(); + } catch (e) { + ok(!(e instanceof Error), "Should have an Exception here (4)"); + ok(!(e instanceof DOMException), "Should not have DOMException here (4)"); + ok(!("code" in e), "Should not have a 'code' property (4)"); + is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (4)"); + is(e.message, "", "Message should be sanitized (5)"); + is(e.stack, + `doTest@${file}:113:9 +${asyncFrame}`, + "Exception stack for sanitized exception should only show our code (4)"); + is(e.filename, + file, + "Should still have the right file name for sanitized exception (4)"); + is(e.lineNumber, 113, "Should still have the right line number for sanitized exception (4)"); + todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (4)"); + } + + try { + t.testThrowSelfHosted(); + } catch (e) { + ok(!(e instanceof Error), "Should have an Exception here (5)"); + ok(!(e instanceof DOMException), "Should not have DOMException here (5)"); + ok(!("code" in e), "Should not have a 'code' property (5)"); + is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (5)"); + is(e.message, "", "Message should be sanitized (5)"); + is(e.stack, + `doTest@${file}:132:9 +${asyncFrame}`, + "Exception stack for sanitized exception should only show our code (5)"); + is(e.filename, + file, + "Should still have the right file name for sanitized exception (5)"); + is(e.lineNumber, 132, "Should still have the right line number for sanitized exception (5)"); + todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (5)"); + } + + SimpleTest.finish(); + } + + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, + doTest); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107592">Mozilla Bug 1107592</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_exceptions_from_jsimplemented.html b/dom/bindings/test/test_exceptions_from_jsimplemented.html new file mode 100644 index 0000000000..89faf0c46f --- /dev/null +++ b/dom/bindings/test/test_exceptions_from_jsimplemented.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=923010 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 923010</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /** Test for Bug 923010 **/ + try { + var conn = new RTCPeerConnection(); + + var candidate = new RTCIceCandidate({candidate: "x" }); + conn.addIceCandidate(candidate) + .then(function() { + ok(false, "addIceCandidate succeeded when it should have failed"); + }, function(reason) { + is(reason.lineNumber, 17, "Rejection should have been on line 17"); + is(reason.message, + "Invalid candidate (both sdpMid and sdpMLineIndex are null).", + "Should have the rejection we expect"); + }) + .catch(function(reason) { + ok(false, "unexpected error: " + reason); + }); + } catch (e) { + // b2g has no WebRTC, apparently + todo(false, "No WebRTC on b2g yet"); + } + + conn.close(); + try { + conn.setIdentityProvider("example.com", { protocol: "foo" }); + ok(false, "That call to setIdentityProvider should have thrown"); + } catch (e) { + is(e.lineNumber, 36, "Exception should have been on line 36"); + is(e.message, + "Peer connection is closed", + "Should have the exception we expect"); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=923010">Mozilla Bug 923010</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_forOf.html b/dom/bindings/test/test_forOf.html new file mode 100644 index 0000000000..1be2506a21 --- /dev/null +++ b/dom/bindings/test/test_forOf.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=725907 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 725907</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725907">Mozilla Bug 725907</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<div id="basket"> + <span id="egg0"></span> + <span id="egg1"><span id="duckling1"></span></span> + <span id="egg2"></span> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 725907 **/ + + +function runTestsForDocument(document, msgSuffix) { + function is(a, b, msg) { SimpleTest.is(a, b, msg + msgSuffix); } + + var basket = document.getElementById("basket"); + var egg3 = document.createElement("span"); + egg3.id = "egg3"; + + var log = ""; + for (let x of basket.childNodes) { + if (x.nodeType != x.TEXT_NODE) + log += x.id + ";"; + } + is(log, "egg0;egg1;egg2;", "'for (x of div.childNodes)' should iterate over child nodes"); + + log = ""; + for (let x of basket.childNodes) { + if (x.nodeType != x.TEXT_NODE) { + log += x.id + ";"; + if (x.id == "egg1") + basket.appendChild(egg3); + } + } + is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.childNodes)' should see elements added during iteration"); + + log = ""; + basket.appendChild(document.createTextNode("some text")); + for (let x of basket.children) + log += x.id + ";"; + is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.children)' should iterate over child elements"); + + var count = 0; + // eslint-disable-next-line no-unused-vars + for (let x of document.getElementsByClassName("hazardous-materials")) + count++; + is(count, 0, "'for (x of emptyNodeList)' loop should run zero times"); + + log = ""; + for (let x of document.querySelectorAll("span")) + log += x.id + ";"; + is(log, "egg0;egg1;duckling1;egg2;egg3;", "for-of loop should work with a querySelectorAll() NodeList"); +} + +/* All the tests run twice. First, in this document, so without any wrappers. */ +runTestsForDocument(document, ""); + +/* And once using the document of an iframe, so working with cross-compartment wrappers. */ +SimpleTest.waitForExplicitFinish(); +function iframeLoaded(iframe) { + runTestsForDocument(iframe.contentWindow.document, " (in iframe)"); + SimpleTest.finish(); +} + +</script> + +<iframe src="forOf_iframe.html" onload="iframeLoaded(this)"></iframe> + +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_integers.html b/dom/bindings/test/test_integers.html new file mode 100644 index 0000000000..765ed1993d --- /dev/null +++ b/dom/bindings/test/test_integers.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <canvas id="c" width="1" height="1"></canvas> +</div> +<pre id="test"> +<script type="application/javascript"> + + function testInt64NonFinite(arg) { + // We can use a WebGLRenderingContext to test conversion to 64-bit signed + // ints edge cases. + var gl = $("c").getContext("experimental-webgl"); + if (!gl) { + // No WebGL support on MacOS 10.5. Just skip this test + todo(false, "WebGL not supported"); + return; + } + var error = gl.getError(); + + // on the b2g emulator we get GL_INVALID_FRAMEBUFFER_OPERATION + if (error == 0x0506) // GL_INVALID_FRAMEBUFFER_OPERATION + return; + + is(error, 0, "Should not start in an error state"); + + var b = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, b); + + var a = new Float32Array(1); + gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW); + + gl.bufferSubData(gl.ARRAY_BUFFER, arg, a); + + is(gl.getError(), 0, "Should have treated non-finite double as 0"); + } + + testInt64NonFinite(NaN); + testInt64NonFinite(Infinity); + testInt64NonFinite(-Infinity); +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_interfaceLength.html b/dom/bindings/test/test_interfaceLength.html new file mode 100644 index 0000000000..30fde932ce --- /dev/null +++ b/dom/bindings/test/test_interfaceLength.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1776790 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1776790</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1776790">Mozilla Bug 1776790</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +/* global TestInterfaceLength */ + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +/** Test for Bug 1776790 **/ +add_task(function test_interface_length() { + is(TestInterfaceLength.length, 0, "TestInterfaceLength.length"); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_interfaceLength_chrome.html b/dom/bindings/test/test_interfaceLength_chrome.html new file mode 100644 index 0000000000..86ec985057 --- /dev/null +++ b/dom/bindings/test/test_interfaceLength_chrome.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1776790 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1776790</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1776790">Mozilla Bug 1776790</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +/* global TestInterfaceLength */ + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +/** Test for Bug 1776790 **/ +add_task(function test_interface_length() { + is(TestInterfaceLength.length, 1, "TestInterfaceLength.length"); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_interfaceName.html b/dom/bindings/test/test_interfaceName.html new file mode 100644 index 0000000000..bd06fc0cef --- /dev/null +++ b/dom/bindings/test/test_interfaceName.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1084001 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1084001</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1084001 **/ + is(Image.name, "Image", "Image name"); + is(Promise.name, "Promise", "Promise name"); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1084001">Mozilla Bug 1084001</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_interfaceToString.html b/dom/bindings/test/test_interfaceToString.html new file mode 100644 index 0000000000..0a7ae9337f --- /dev/null +++ b/dom/bindings/test/test_interfaceToString.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742156 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 742156</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742156">Mozilla Bug 742156</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742156 **/ + +var nativeToString = ("" + String).replace("String", "EventTarget"); +try { + var eventTargetToString = "" + EventTarget; + is(eventTargetToString, nativeToString, + "Stringifying a DOM interface object should return the same string" + + "as stringifying a native function."); +} catch (e) { + ok(false, "Stringifying a DOM interface object shouldn't throw."); +} + +try { + eventTargetToString = Function.prototype.toString.call(EventTarget); + is(eventTargetToString, nativeToString, + "Stringifying a DOM interface object via Function.prototype.toString " + + "should return the same string as stringifying a native function."); +} catch (e) { + ok(false, "Stringifying a DOM interface object shouldn't throw."); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_iterable.html b/dom/bindings/test/test_iterable.html new file mode 100644 index 0000000000..4c2dc0fc4e --- /dev/null +++ b/dom/bindings/test/test_iterable.html @@ -0,0 +1,241 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> + <head> + <title>Test Iterable Interface</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script class="testbody" type="application/javascript"> + /* global TestInterfaceIterableSingle, TestInterfaceIterableDouble, TestInterfaceIterableDoubleUnion */ + + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { + var base_properties = [["entries", "function", 0], + ["keys", "function", 0], + ["values", "function", 0], + ["forEach", "function", 1]]; + var testExistence = function testExistence(prefix, obj, properties) { + for (var [name, type, args] of properties) { + // Properties are somewhere up the proto chain, hasOwnProperty won't work + isnot(obj[name], undefined, + `${prefix} object has property ${name}`); + + is(typeof obj[name], type, + `${prefix} object property ${name} is a ${type}`); + // Check function length + if (type == "function") { + is(obj[name].length, args, + `${prefix} object property ${name} is length ${args}`); + is(obj[name].name, name, + `${prefix} object method name is ${name}`); + } + + // Find where property is on proto chain, check for enumerablility there. + var owner = obj; + while (owner) { + var propDesc = Object.getOwnPropertyDescriptor(owner, name); + if (propDesc) { + ok(propDesc.enumerable, + `${prefix} object property ${name} is enumerable`); + break; + } + owner = Object.getPrototypeOf(owner); + } + } + }; + + var itr; + info("IterableSingle: Testing simple iterable creation and functionality"); + itr = new TestInterfaceIterableSingle(); + testExistence("IterableSingle: ", itr, base_properties); + is(itr[Symbol.iterator], Array.prototype[Symbol.iterator], + "IterableSingle: Should be using %ArrayIterator% for @@iterator"); + is(itr.keys, Array.prototype.keys, + "IterableSingle: Should be using %ArrayIterator% for 'keys'"); + is(itr.entries, Array.prototype.entries, + "IterableSingle: Should be using %ArrayIterator% for 'entries'"); + is(itr.values, itr[Symbol.iterator], + "IterableSingle: Should be using @@iterator for 'values'"); + is(itr.forEach, Array.prototype.forEach, + "IterableSingle: Should be using %ArrayIterator% for 'forEach'"); + var keys = [...itr.keys()]; + var values = [...itr.values()]; + var entries = [...itr.entries()]; + var key_itr = itr.keys(); + var value_itr = itr.values(); + var entries_itr = itr.entries(); + for (let i = 0; i < 3; ++i) { + let key = key_itr.next(); + let value = value_itr.next(); + let entry = entries_itr.next(); + is(key.value, i, "IterableSingle: Key iterator value should be " + i); + is(key.value, keys[i], + "IterableSingle: Key iterator value should match destructuring " + i); + is(value.value, key.value, "IterableSingle: Value iterator value should be " + key.value); + is(value.value, values[i], + "IterableSingle: Value iterator value should match destructuring " + i); + is(entry.value[0], i, "IterableSingle: Entry iterator value 0 should be " + i); + is(entry.value[1], i, "IterableSingle: Entry iterator value 1 should be " + i); + is(entry.value[0], entries[i][0], + "IterableSingle: Entry iterator value 0 should match destructuring " + i); + is(entry.value[1], entries[i][1], + "IterableSingle: Entry iterator value 1 should match destructuring " + i); + } + + var callsToForEachCallback = 0; + var thisArg = {}; + itr.forEach(function(value1, index, obj) { + is(index, callsToForEachCallback, + `IterableSingle: Should have the right index at ${callsToForEachCallback} calls to forEach callback`); + is(value1, values[index], + `IterableSingle: Should have the right value at ${callsToForEachCallback} calls to forEach callback`); + is(this, thisArg, + "IterableSingle: Should have the right this value for forEach callback"); + is(obj, itr, + "IterableSingle: Should have the right third arg for forEach callback"); + ++callsToForEachCallback; + }, thisArg); + is(callsToForEachCallback, 3, + "IterableSingle: Should have right total number of calls to forEach callback"); + + let key = key_itr.next(); + let value = value_itr.next(); + let entry = entries_itr.next(); + is(key.value, undefined, "IterableSingle: Key iterator value should be undefined"); + is(key.done, true, "IterableSingle: Key iterator done should be true"); + is(value.value, undefined, "IterableSingle: Value iterator value should be undefined"); + is(value.done, true, "IterableSingle: Value iterator done should be true"); + is(entry.value, undefined, "IterableDouble: Entry iterator value should be undefined"); + is(entry.done, true, "IterableSingle: Entry iterator done should be true"); + is(Object.prototype.toString.call(Object.getPrototypeOf(key_itr)), + "[object Array Iterator]", + "iterator prototype should have the right brand"); + + // Simple dual type iterable creation and functionality test + info("IterableDouble: Testing simple iterable creation and functionality"); + itr = new TestInterfaceIterableDouble(); + testExistence("IterableDouble: ", itr, base_properties); + is(itr.entries, itr[Symbol.iterator], + "IterableDouble: Should be using @@iterator for 'entries'"); + var elements = [["a", "b"], ["c", "d"], ["e", "f"]]; + keys = [...itr.keys()]; + values = [...itr.values()]; + entries = [...itr.entries()]; + key_itr = itr.keys(); + value_itr = itr.values(); + entries_itr = itr.entries(); + for (let i = 0; i < 3; ++i) { + key = key_itr.next(); + value = value_itr.next(); + entry = entries_itr.next(); + is(key.value, elements[i][0], "IterableDouble: Key iterator value should be " + elements[i][0]); + is(key.value, keys[i], + "IterableDouble: Key iterator value should match destructuring " + i); + is(value.value, elements[i][1], "IterableDouble: Value iterator value should be " + elements[i][1]); + is(value.value, values[i], + "IterableDouble: Value iterator value should match destructuring " + i); + is(entry.value[0], elements[i][0], "IterableDouble: Entry iterator value 0 should be " + elements[i][0]); + is(entry.value[1], elements[i][1], "IterableDouble: Entry iterator value 1 should be " + elements[i][1]); + is(entry.value[0], entries[i][0], + "IterableDouble: Entry iterator value 0 should match destructuring " + i); + is(entry.value[1], entries[i][1], + "IterableDouble: Entry iterator value 1 should match destructuring " + i); + } + + callsToForEachCallback = 0; + thisArg = {}; + itr.forEach(function(value1, key1, obj) { + is(key1, keys[callsToForEachCallback], + `IterableDouble: Should have the right key at ${callsToForEachCallback} calls to forEach callback`); + is(value1, values[callsToForEachCallback], + `IterableDouble: Should have the right value at ${callsToForEachCallback} calls to forEach callback`); + is(this, thisArg, + "IterableDouble: Should have the right this value for forEach callback"); + is(obj, itr, + "IterableSingle: Should have the right third arg for forEach callback"); + ++callsToForEachCallback; + }, thisArg); + is(callsToForEachCallback, 3, + "IterableDouble: Should have right total number of calls to forEach callback"); + + key = key_itr.next(); + value = value_itr.next(); + entry = entries_itr.next(); + is(key.value, undefined, "IterableDouble: Key iterator value should be undefined"); + is(key.done, true, "IterableDouble: Key iterator done should be true"); + is(value.value, undefined, "IterableDouble: Value iterator value should be undefined"); + is(value.done, true, "IterableDouble: Value iterator done should be true"); + is(entry.value, undefined, "IterableDouble: Entry iterator value should be undefined"); + is(entry.done, true, "IterableDouble: Entry iterator done should be true"); + is(Object.prototype.toString.call(Object.getPrototypeOf(key_itr)), + "[object TestInterfaceIterableDouble Iterator]", + "iterator prototype should have the right brand"); + + // Simple dual type iterable creation and functionality test + info("IterableDoubleUnion: Testing simple iterable creation and functionality"); + itr = new TestInterfaceIterableDoubleUnion(); + testExistence("IterableDoubleUnion: ", itr, base_properties); + is(itr.entries, itr[Symbol.iterator], + "IterableDoubleUnion: Should be using @@iterator for 'entries'"); + elements = [["long", 1], ["string", "a"]]; + keys = [...itr.keys()]; + values = [...itr.values()]; + entries = [...itr.entries()]; + key_itr = itr.keys(); + value_itr = itr.values(); + entries_itr = itr.entries(); + for (let i = 0; i < elements.length; ++i) { + key = key_itr.next(); + value = value_itr.next(); + entry = entries_itr.next(); + is(key.value, elements[i][0], "IterableDoubleUnion: Key iterator value should be " + elements[i][0]); + is(key.value, keys[i], + "IterableDoubleUnion: Key iterator value should match destructuring " + i); + is(value.value, elements[i][1], "IterableDoubleUnion: Value iterator value should be " + elements[i][1]); + is(value.value, values[i], + "IterableDoubleUnion: Value iterator value should match destructuring " + i); + is(entry.value[0], elements[i][0], "IterableDoubleUnion: Entry iterator value 0 should be " + elements[i][0]); + is(entry.value[1], elements[i][1], "IterableDoubleUnion: Entry iterator value 1 should be " + elements[i][1]); + is(entry.value[0], entries[i][0], + "IterableDoubleUnion: Entry iterator value 0 should match destructuring " + i); + is(entry.value[1], entries[i][1], + "IterableDoubleUnion: Entry iterator value 1 should match destructuring " + i); + } + + callsToForEachCallback = 0; + thisArg = {}; + itr.forEach(function(value1, key1, obj) { + is(key1, keys[callsToForEachCallback], + `IterableDoubleUnion: Should have the right key at ${callsToForEachCallback} calls to forEach callback`); + is(value1, values[callsToForEachCallback], + `IterableDoubleUnion: Should have the right value at ${callsToForEachCallback} calls to forEach callback`); + is(this, thisArg, + "IterableDoubleUnion: Should have the right this value for forEach callback"); + is(obj, itr, + "IterableSingle: Should have the right third arg for forEach callback"); + ++callsToForEachCallback; + }, thisArg); + is(callsToForEachCallback, 2, + "IterableDoubleUnion: Should have right total number of calls to forEach callback"); + + key = key_itr.next(); + value = value_itr.next(); + entry = entries_itr.next(); + is(key.value, undefined, "IterableDoubleUnion: Key iterator value should be undefined"); + is(key.done, true, "IterableDoubleUnion: Key iterator done should be true"); + is(value.value, undefined, "IterableDoubleUnion: Value iterator value should be undefined"); + is(value.done, true, "IterableDoubleUnion: Value iterator done should be true"); + is(entry.value, undefined, "IterableDoubleUnion: Entry iterator value should be undefined"); + is(entry.done, true, "IterableDoubleUnion: Entry iterator done should be true"); + is(Object.prototype.toString.call(Object.getPrototypeOf(key_itr)), + "[object TestInterfaceIterableDoubleUnion Iterator]", + "iterator prototype should have the right brand"); + + SimpleTest.finish(); + }); + </script> + </body> +</html> diff --git a/dom/bindings/test/test_jsimplemented_cross_realm_this.html b/dom/bindings/test/test_jsimplemented_cross_realm_this.html new file mode 100644 index 0000000000..f44e3e02ae --- /dev/null +++ b/dom/bindings/test/test_jsimplemented_cross_realm_this.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1464374--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1464374</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1464374">Mozilla Bug 1464374</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + +<iframe></iframe> +<script type="application/javascript"> + /* global TestInterfaceJS */ + /** Test for Bug 1464374 **/ + SimpleTest.waitForExplicitFinish(); + + function doTest() { + var frame = frames[0]; + var obj = new frame.TestInterfaceJS(); + var ex; + try { + TestInterfaceJS.prototype.testThrowTypeError.call(obj); + } catch (e) { + ex = e; + } + ok(ex, "Should have an exception"); + SimpleTest.finish(); + } + + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, + doTest); +</script> + +</body> +</html> diff --git a/dom/bindings/test/test_jsimplemented_eventhandler.html b/dom/bindings/test/test_jsimplemented_eventhandler.html new file mode 100644 index 0000000000..7b77604744 --- /dev/null +++ b/dom/bindings/test/test_jsimplemented_eventhandler.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1186696 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1186696</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS */ + /** Test for Bug 1186696 **/ + SimpleTest.waitForExplicitFinish(); + + function doTest() { + var values = [ function() {}, 5, null, undefined, "some string", {} ]; + + while (values.length) { + var value = values.pop(); + var t = new TestInterfaceJS(); + t.onsomething = value; + var gottenValue = t.onsomething; + if (typeof value == "object" || typeof value == "function") { + is(gottenValue, value, "Should get back the object-or-null we put in"); + } else { + is(gottenValue, null, "Should get back null"); + } + } + + SimpleTest.finish(); + } + + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, + doTest); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1186696">Mozilla Bug 1186696</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_jsimplemented_subclassing.html b/dom/bindings/test/test_jsimplemented_subclassing.html new file mode 100644 index 0000000000..70be0d62aa --- /dev/null +++ b/dom/bindings/test/test_jsimplemented_subclassing.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1400275 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1400275</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1400275 **/ + class Foo extends RTCPeerConnection { + } + + var obj = new Foo(); + is(Object.getPrototypeOf(obj), Foo.prototype, + "Should have the right prototype"); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1400275">Mozilla Bug 1400275</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_large_arraybuffers.html b/dom/bindings/test/test_large_arraybuffers.html new file mode 100644 index 0000000000..64f6fc7276 --- /dev/null +++ b/dom/bindings/test/test_large_arraybuffers.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1688616 +--> +<head> + <meta charset="utf-8"> + <title>Test for large ArrayBuffers and views</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1688616">Mozilla Bug 1688616</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + /* global TestFunctions */ + + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go); + + function checkThrowsTooLarge(f) { + let ex; + try{ + f(); + ok(false, "Should have thrown!"); + } catch (e) { + ex = e; + } + ok(ex.toString().includes("larger than 2 GB"), "Got exception: " + ex); + } + + function go() { + let test = new TestFunctions(); + + const gb = 1 * 1024 * 1024 * 1024; + let ab = new ArrayBuffer(5 * gb); + checkThrowsTooLarge(() => test.testNotAllowShared(ab)); + checkThrowsTooLarge(() => test.testAllowShared(ab)); + checkThrowsTooLarge(() => test.testDictWithAllowShared({arrayBuffer: ab})); + checkThrowsTooLarge(() => test.testUnionOfBuffferSource(ab)); + checkThrowsTooLarge(() => { test.arrayBuffer = ab; }); + checkThrowsTooLarge(() => { test.allowSharedArrayBuffer = ab; }); + checkThrowsTooLarge(() => { test.sequenceOfArrayBuffer = [ab]; }); + checkThrowsTooLarge(() => { test.sequenceOfAllowSharedArrayBuffer = [ab]; }); + + let ta = new Int8Array(ab, 0, 3 * gb); + checkThrowsTooLarge(() => test.testNotAllowShared(ta)); + checkThrowsTooLarge(() => test.testAllowShared(ta)); + checkThrowsTooLarge(() => test.testDictWithAllowShared({arrayBufferView: ta})); + checkThrowsTooLarge(() => test.testUnionOfBuffferSource(ta)); + checkThrowsTooLarge(() => { test.arrayBufferView = ta; }); + checkThrowsTooLarge(() => { test.allowSharedArrayBufferView = ta; }); + checkThrowsTooLarge(() => { test.sequenceOfArrayBufferView = [ta]; }); + checkThrowsTooLarge(() => { test.sequenceOfAllowSharedArrayBufferView = [ta]; }); + + let dv = new DataView(ab); + checkThrowsTooLarge(() => test.testNotAllowShared(dv)); + checkThrowsTooLarge(() => test.testAllowShared(dv)); + checkThrowsTooLarge(() => test.testDictWithAllowShared({arrayBufferView: dv})); + checkThrowsTooLarge(() => test.testUnionOfBuffferSource(dv)); + checkThrowsTooLarge(() => { test.arrayBufferView = dv; }); + checkThrowsTooLarge(() => { test.allowSharedArrayBufferView = dv; }); + checkThrowsTooLarge(() => { test.sequenceOfArrayBufferView = [dv]; }); + checkThrowsTooLarge(() => { test.sequenceOfAllowSharedArrayBufferView = [dv]; }); + + if (this.SharedArrayBuffer) { + let sab = new SharedArrayBuffer(5 * gb); + checkThrowsTooLarge(() => test.testAllowShared(sab)); + checkThrowsTooLarge(() => test.testDictWithAllowShared({allowSharedArrayBuffer: sab})); + checkThrowsTooLarge(() => test.testUnionOfAllowSharedBuffferSource(sab)); + checkThrowsTooLarge(() => { test.allowSharedArrayBuffer = sab; }); + checkThrowsTooLarge(() => { test.sequenceOfAllowSharedArrayBuffer = [sab]; }); + + let sta = new Int8Array(sab); + checkThrowsTooLarge(() => test.testAllowShared(sta)); + checkThrowsTooLarge(() => test.testDictWithAllowShared({allowSharedArrayBufferView: sta})); + checkThrowsTooLarge(() => test.testUnionOfAllowSharedBuffferSource(sta)); + checkThrowsTooLarge(() => { test.allowSharedArrayBufferView = sta; }); + checkThrowsTooLarge(() => { test.sequenceOfAllowSharedArrayBufferView = [sta]; }); + } + + // Small views on large buffers are fine. + let ta2 = new Int8Array(ab, 4 * gb); + is(ta2.byteLength, 1 * gb, "Small view on large ArrayBuffer"); + test.testNotAllowShared(ta2); + test.arrayBufferView = ta2; + + SimpleTest.finish(); + } + </script> +</body> +</html> diff --git a/dom/bindings/test/test_large_imageData.html b/dom/bindings/test/test_large_imageData.html new file mode 100644 index 0000000000..68cb4bd50b --- /dev/null +++ b/dom/bindings/test/test_large_imageData.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1716622 +--> +<head> + <meta charset="utf-8"> + <title>Test for large ImageData</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1716622">Mozilla Bug 1716622</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + <canvas id="canvas" width="800" height="800"></canvas> + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + function go() { + var ctx = document.getElementById("canvas").getContext("2d"); + + var ex = null; + try { + ctx.createImageData(23175, 23175); + } catch (e) { + ex = e; + } + ok(ex.toString().includes("Invalid width or height"), + "Expected createImageData exception"); + + ex = null; + try { + ctx.createImageData(33000, 33000); + } catch (e) { + ex = e; + } + ok(ex.toString().includes("Invalid width or height"), + "Expected createImageData exception"); + + ex = null; + try { + ctx.getImageData(0, 0, 23175, 23175); + } catch (e) { + ex = e; + } + ok(ex.toString().includes("negative or greater than the allowed amount"), + "Expected getImageData exception"); + + ex = null; + try { + new ImageData(23175, 23175); + } catch (e) { + ex = e; + } + ok(ex.toString().includes("negative or greater than the allowed amount"), + "Expected ImageData constructor exception"); + + SimpleTest.finish(); + } + go(); + </script> +</body> +</html> diff --git a/dom/bindings/test/test_lenientThis.html b/dom/bindings/test/test_lenientThis.html new file mode 100644 index 0000000000..f4fb4200a5 --- /dev/null +++ b/dom/bindings/test/test_lenientThis.html @@ -0,0 +1,28 @@ +<!doctype html> +<meta charset=utf-8> +<title>[LenientThis]</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +/* global test, assert_equals */ +function noop1() { } +function noop2() { } + +test(function() { + var desc = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange"); + + document.onreadystatechange = noop1; + assert_equals(document.onreadystatechange, noop1, "document.onreadystatechange == noop1"); + assert_equals(desc.get.call({ }), undefined, "document.onreadystatechange getter.call({}) == undefined"); +}, "invoking Document.onreadystatechange's getter with an invalid this object returns undefined"); + +test(function() { + var desc = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange"); + + document.onreadystatechange = noop1; + assert_equals(document.onreadystatechange, noop1, "document.onreadystatechange == noop1"); + assert_equals(desc.set.call({ }, noop2), undefined, "document.onreadystatechange setter.call({}) == undefined"); + assert_equals(document.onreadystatechange, noop1, "document.onreadystatechange == noop1 (still)"); +}, "invoking Document.onreadystatechange's setter with an invalid this object does nothing and returns undefined"); +</script> diff --git a/dom/bindings/test/test_lookupGetter.html b/dom/bindings/test/test_lookupGetter.html new file mode 100644 index 0000000000..5fe15059b7 --- /dev/null +++ b/dom/bindings/test/test_lookupGetter.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=462428 +--> +<head> + <title>Test for Bug 462428</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462428">Mozilla Bug 462428</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 462428 **/ +var x = new XMLHttpRequest; +x.open("GET", ""); +var getter = x.__lookupGetter__("readyState"); +ok(getter !== undefined, "But able to look it up the normal way"); +ok(!x.hasOwnProperty("readyState"), "property should still be on the prototype"); + +var sawProp = false; +for (var i in x) { + if (i === "readyState") { + sawProp = true; + } +} + +ok(sawProp, "property should be enumerable"); + +is(getter.call(x), 1, "the getter actually works"); + +Object.getPrototypeOf(x).__defineSetter__("readyState", function() {}); +is(getter.call(x), 1, "the getter works after defineSetter"); + +is(x.responseType, "", "Should have correct responseType up front"); +var setter = x.__lookupSetter__("responseType"); +setter.call(x, "document"); +is(x.responseType, "document", "the setter is bound correctly"); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_namedNoIndexed.html b/dom/bindings/test/test_namedNoIndexed.html new file mode 100644 index 0000000000..73a79d3894 --- /dev/null +++ b/dom/bindings/test/test_namedNoIndexed.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=808991 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 808991</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=808991">Mozilla Bug 808991</a> +<p id="display"></p> +<div id="content" style="display: none" data-1="foo" data-bar="baz"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 808991 **/ +is($("content").dataset[1], "foo", + "Indexed props should work like named on dataset"); +is($("content").dataset["1"], "foo", + "Indexed props as strings should work like named on dataset"); +is($("content").dataset.bar, "baz", + "Named props should work on dataset"); +is($("content").dataset.bar, "baz", + "Named props as strings should work on dataset"); + + + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_named_getter_enumerability.html b/dom/bindings/test/test_named_getter_enumerability.html new file mode 100644 index 0000000000..3894633a3b --- /dev/null +++ b/dom/bindings/test/test_named_getter_enumerability.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for named getter enumerability</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +/* global test, assert_equals, assert_true, assert_false, assert_not_equals */ +test(function() { + var list = document.getElementsByTagName("div"); + var desc = Object.getOwnPropertyDescriptor(list, "0"); + assert_equals(typeof desc, "object", "Should have a '0' property"); + assert_true(desc.enumerable, "'0' property should be enumerable"); + desc = Object.getOwnPropertyDescriptor(list, "log"); + assert_equals(typeof desc, "object", "Should have a 'log' property"); + assert_false(desc.enumerable, "'log' property should not be enumerable"); +}, "Correct getOwnPropertyDescriptor behavior"); +test(function() { + var list = document.getElementsByTagName("div"); + var props = []; + for (var prop in list) { + props.push(prop); + } + assert_not_equals(props.indexOf("0"), -1, "Should enumerate '0'"); + assert_equals(props.indexOf("log"), -1, "Should not enumerate 'log'"); +}, "Correct enumeration behavior"); +test(function() { + var list = document.getElementsByTagName("div"); + var props = Object.keys(list); + assert_not_equals(props.indexOf("0"), -1, "Keys should contain '0'"); + assert_equals(props.indexOf("log"), -1, "Keys should not contain 'log'"); +}, "Correct keys() behavior"); +test(function() { + var list = document.getElementsByTagName("div"); + var props = Object.getOwnPropertyNames(list); + assert_not_equals(props.indexOf("0"), -1, + "own prop names should contain '0'"); + assert_not_equals(props.indexOf("log"), -1, + "own prop names should contain 'log'"); +}, "Correct getOwnPropertyNames() behavior"); +</script> diff --git a/dom/bindings/test/test_observablearray.html b/dom/bindings/test/test_observablearray.html new file mode 100644 index 0000000000..313fb67622 --- /dev/null +++ b/dom/bindings/test/test_observablearray.html @@ -0,0 +1,546 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> +<head> +<title>Test Observable Array Type</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> +/* global TestInterfaceObservableArray */ + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +add_task(function testObservableArray_length() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + m.observableArrayBoolean = [true, true, true, true, true]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 5, "length of observable array should be 5"); + + [ + // [length, shouldThrow, expectedResult] + ["invalid", true, false], + [b.length + 1, false, false], + [b.length, false, true], + [b.length - 1, false, true], + [0, false, true], + ].forEach(function([length, shouldThrow, expectedResult]) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + let shouldSuccess = !shouldThrow && expectedResult; + setCallbackCount = 0; + deleteCallbackCount = 0; + deleteCallbackTests = null; + if (shouldSuccess) { + let deleteCallbackIndex = b.length - 1; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument"); + is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument"); + deleteCallbackIndex--; + }; + } + + // Test + info(`setting length to ${length}`); + try { + b.length = length; + ok(!shouldThrow, `setting length should throw`); + } catch(e) { + ok(shouldThrow, `setting length throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, shouldSuccess ? (oldLen - length) : 0, "deleteCallback count"); + isDeeply(b, shouldSuccess ? oldValues.slice(0, length) : oldValues, "property values"); + is(b.length, shouldSuccess ? length : oldLen, `length of observable array`); + }); +}); + +add_task(function testObservableArray_length_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (value) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [true, true, false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 5, "length of observable array should be 5"); + + // Initialize + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting length to 0`); + try { + b.length = 0; + ok(false, `setting length should throw`); + } catch(e) { + ok(true, `setting length throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 4, "deleteCallback should be called"); + isDeeply(b, [true, true], "property values"); + is(b.length, 2, `length of observable array`); +}); + +add_task(function testObservableArray_setter() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [ + // [values, shouldThrow] + ["invalid", true], + [[1,[],{},"invalid"], false], + [[0,NaN,null,undefined,""], false], + [[true,true], false], + [[false,false,false], false], + ].forEach(function([values, shouldThrow]) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = null; + deleteCallbackTests = null; + if (!shouldThrow) { + let setCallbackIndex = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, !!values[setCallbackIndex], "setCallbackTests: test value argument"); + is(_index, setCallbackIndex, "setCallbackTests: test index argument"); + setCallbackIndex++; + }; + + let deleteCallbackIndex = b.length - 1; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument"); + is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument"); + deleteCallbackIndex--; + }; + } + + // Test + info(`setting value to ${JSON.stringify(values)}`); + try { + m.observableArrayBoolean = values; + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, shouldThrow ? 0 : values.length, "setCallback count"); + is(deleteCallbackCount, oldLen, "deleteCallback should be called"); + isDeeply(b, shouldThrow ? [] : values.map(v => !!v), "property values"); + is(b.length, shouldThrow ? 0 : values.length, `length of observable array`); + }); +}); + +add_task(function testObservableArray_setter_invalid_item() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setInterfaceCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteInterfaceCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + + let b = m.observableArrayInterface; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [ + // [values, shouldThrow] + [[m,m,m,m], false], + [["invalid"], true], + [[m,m], false], + [[m,"invalid"], true], + [[m,m,m], false], + ].forEach(function([values, shouldThrow]) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + let setCallbackIndex = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, values[setCallbackIndex], "setCallbackTests: test value argument"); + is(_index, setCallbackIndex, "setCallbackTests: test index argument"); + setCallbackIndex++; + }; + let deleteCallbackIndex = b.length - 1; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument"); + is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument"); + deleteCallbackIndex--; + }; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting value to ${values}`); + try { + m.observableArrayInterface = values; + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, shouldThrow ? 0 : values.length, "setCallback count"); + is(deleteCallbackCount, shouldThrow ? 0 : oldLen, "deleteCallback should be called"); + isDeeply(b, shouldThrow ? oldValues : values, "property values"); + is(b.length, shouldThrow ? oldLen : values.length, `length of observable array`); + }); +}); + +add_task(function testObservableArray_setter_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (index >= 3) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (value) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 3"); + + [ + // [values, shouldThrow, expectedLength, expectedSetCbCount, expectedDeleteCbCount] + [[false,false], false, 2, 2, 3], + [[false,true,false,false], true, 3, 4, 2], + [[false,false,true], true, 2, 0, 2], + ].forEach(function([values, shouldThrow, expectedLength, expectedSetCbCount, + expectedDeleteCbCount]) { + // Initialize + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting value to ${values}`); + try { + m.observableArrayBoolean = values; + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting length throws ${e}`); + } + is(setCallbackCount, expectedSetCbCount, "setCallback should be called"); + is(deleteCallbackCount, expectedDeleteCbCount, "deleteCallback should be called"); + is(b.length, expectedLength, `length of observable array`); + }); +}); + +add_task(function testObservableArray_indexed_setter() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [ + // [index, value, expectedResult] + [b.length + 1, false, false], + [b.length, false, true], + [b.length + 1, false, true], + [b.length + 1, true, true], + ].forEach(function([index, value, expectedResult]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`setting value of property ${index} to ${value}`); + try { + b[index] = value; + ok(true, `setting value should not throw`); + } catch(e) { + ok(false, `setting value throws ${e}`); + } + is(setCallbackCount, expectedResult ? 1 : 0, "setCallback should be called"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback should be called"); + is(b[index], expectedResult ? value : oldValue, `property value`); + is(b.length, expectedResult ? Math.max(oldLen, index + 1) : oldLen, `length of observable array`); + }); +}); + +add_task(function testObservableArray_indexed_setter_invalid() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setInterfaceCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteInterfaceCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + + let b = m.observableArrayInterface; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [ + // [index, value, shouldThrow] + [b.length, "invalid", true], + [b.length, m, false], + [b.length + 1, m, false], + [b.length + 1, "invalid", true], + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`setting value of property ${index} to ${value}`); + try { + b[index] = value; + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, shouldThrow ? 0 : 1, "setCallback count"); + is(deleteCallbackCount, ((oldLen > index) && !shouldThrow) ? 1 : 0, "deleteCallback count"); + is(b[index], shouldThrow ? oldValue : value, `property value`); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); + }); +}); + +add_task(function testObservableArray_indexed_setter_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (value) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (index < 2) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 3"); + + [ + // [index, value, shouldThrow] + [b.length, true, true], + [b.length, false, false], + [b.length, true, true], + [0, false, true], + [0, true, true] + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting value of property ${index} to ${value}`); + try { + b[index] = value; + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, (shouldThrow && index < 2) ? 0 : 1, "setCallback should be called"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback should be called"); + is(b[index], shouldThrow ? oldValue : value, "property value"); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); + }); +}); + +add_task(function testObservableArray_object() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let callbackIndex = 0; + + let values = [ + {property1: false, property2: "property2"}, + {property1: [], property2: 2}, + ]; + + let m = new TestInterfaceObservableArray({ + setObjectCallback(value, index) { + setCallbackCount++; + is(index, callbackIndex++, "setCallbackTests: test index argument"); + isDeeply(values[index], value, "setCallbackTests: test value argument"); + }, + deleteObjectCallback(value, index) { + deleteCallbackCount++; + }, + }); + + m.observableArrayObject = values; + + let b = m.observableArrayObject; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + is(setCallbackCount, values.length, "setCallback should be called"); + is(deleteCallbackCount, 0, "deleteCallback should not be called"); + + for(let i = 0; i < values.length; i++) { + isDeeply(values[i], b[i], `check index ${i}`); + } +}); + +add_task(function testObservableArray_xrays() { + let m = new TestInterfaceObservableArray({ + setObjectCallback(value, index) { + ok(false, "Shouldn't reach setObjectCallback"); + }, + deleteObjectCallback(value, index) { + ok(false, "Shouldn't reach deleteObjectCallback"); + }, + }); + + let wrapper = SpecialPowers.wrap(m); + ok(SpecialPowers.Cu.isXrayWrapper(wrapper), "Should be a wrapper"); + let observableArray = wrapper.observableArrayBoolean; + ok(!!observableArray, "Should not throw"); + is("length" in observableArray, false, "Should be opaque"); + + try { + wrapper.observableArrayBoolean = [true, false, false]; + ok(false, "Expected to throw, for now"); + } catch (ex) {} +}); + +</script> +</body> +</html> diff --git a/dom/bindings/test/test_observablearray_helper.html b/dom/bindings/test/test_observablearray_helper.html new file mode 100644 index 0000000000..d2b4897cac --- /dev/null +++ b/dom/bindings/test/test_observablearray_helper.html @@ -0,0 +1,376 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> +<head> +<title>Test Helpers of Observable Array Type</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> +/* global TestInterfaceObservableArray */ + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +add_task(function testObservableArray_helper_elementAt() { + let m = new TestInterfaceObservableArray(); + + [ + // [values, property, helper] + [[true, false], "observableArrayBoolean", m.booleanElementAtInternal.bind(m)], + [[new TestInterfaceObservableArray(), new TestInterfaceObservableArray()], + "observableArrayInterface", m.interfaceElementAtInternal.bind(m)], + [[{property: "test"}, {property: 2}], "observableArrayObject", + m.objectElementAtInternal.bind(m)], + ].forEach(function([values, property, helper]) { + m[property] = values; + + let t = m[property]; + ok(Array.isArray(t), "observable array should be an array type"); + is(t.length, values.length, "length of observable array"); + + for (let i = 0; i < values.length; i++) { + isDeeply(values[i], helper(i), `check index ${i}`); + } + + SimpleTest.doesThrow(() => { + helper(values.length); + }, `getting element outside the range should throw`); + }); +}); + +add_task(function testObservableArray_helper_replaceElementAt() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [ + // [index, value, shouldThrow] + [b.length + 1, false, true], + [b.length, false, false], + [b.length + 1, false, false], + [b.length + 1, true, false], + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`setting value of property ${index} to ${value}`); + try { + m.booleanReplaceElementAtInternal(index, value); + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, shouldThrow ? 0 : 1, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], shouldThrow ? oldValue : value, `property value`); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); + }); +}); + +add_task(function testObservableArray_helper_replaceElementAt_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (value) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (index < 2) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 3"); + + [ + // [index, value, shouldThrow] + [b.length, true, true], + [b.length, false, false], + [b.length, true, true], + [0, false, true], + [0, true, true] + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting value of property ${index} to ${value}`); + try { + m.booleanReplaceElementAtInternal(index, value); + ok(!shouldThrow, `setting value should not throw`); + } catch(e) { + ok(shouldThrow, `setting value throws ${e}`); + } + is(setCallbackCount, (shouldThrow && index < 2) ? 0 : 1, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], shouldThrow ? oldValue : value, "property value"); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), `length of observable array`); + }); +}); + +add_task(function testObservableArray_helper_appendElement() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + }, + }); + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + [true, false, true, false].forEach(function(value) { + // Initialize + let oldLen = b.length; + let index = oldLen; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + info(`set callback for ${_index}`); + is(_value, value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + + // Test + info(`append ${value}`); + try { + m.booleanAppendElementInternal(value); + ok(true, `appending value should not throw`); + } catch(e) { + ok(false, `appending value throws ${e}`); + } + is(setCallbackCount, 1, "setCallback should be called"); + is(deleteCallbackCount, 0, "deleteCallback should not be called"); + is(b[index], value, `property value`); + is(b.length, oldLen + 1, `length of observable array`); + }); +}); + +add_task(function testObservableArray_helper_appendElement_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (value) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + }, + }); + m.observableArrayBoolean = [false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 3"); + + [true, false, true, false].forEach(function(value) { + // Initialize + let oldLen = b.length; + let index = oldLen; + let oldValue = b[index]; + let shouldThrow = value; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`append ${value}`); + try { + m.booleanAppendElementInternal(value); + ok(!shouldThrow, `appending value should not throw`); + } catch(e) { + ok(shouldThrow, `appending value throws ${e}`); + } + is(setCallbackCount, 1, "setCallback should be called"); + is(deleteCallbackCount, 0, "deleteCallback should not be called"); + is(b[index], shouldThrow ? oldValue : value, "property value"); + is(b.length, shouldThrow ? oldLen : oldLen + 1, `length of observable array`); + }); +}); + +add_task(function testObservableArray_helper_removeLastElement() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + m.observableArrayBoolean = [true, false, true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 4, "length of observable array should be 4"); + + let oldValues = b.slice(); + while (oldValues.length) { + // Initialize + let oldValue = oldValues.pop(); + let index = oldValues.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + deleteCallbackTests = function(_value, _index) { + info(`delete callback for ${_index}`); + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`remove last element`); + try { + m.booleanRemoveLastElementInternal(); + ok(true, `removing last element should not throw`); + } catch(e) { + ok(false, `removing last element throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 1, "deleteCallback should be called"); + isDeeply(b, oldValues, `property value`); + is(b.length, oldValues.length, `length of observable array`); + } + + // test when array is empty + setCallbackCount = 0; + deleteCallbackCount = 0; + SimpleTest.doesThrow(() => { + m.booleanRemoveLastElementInternal(); + }, `removing last element should throw when array is empty`); + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 0, "deleteCallback should not be called"); + is(b.length, 0, `length of observable array`); +}); + +add_task(function testObservableArray_helper_removeLastElement_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (value) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, true, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 4, "length of observable array should be 4"); + + let shouldThrow = false; + while (!shouldThrow && b.length) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + shouldThrow = oldValues[oldLen - 1]; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`remove last element`); + try { + m.booleanRemoveLastElementInternal(); + ok(!shouldThrow, `removing last element should not throw`); + } catch(e) { + ok(shouldThrow, `removing last element throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 1, "deleteCallback should be called"); + isDeeply(b, shouldThrow ? oldValues : oldValues.slice(0, oldLen - 1), `property value`); + is(b.length, shouldThrow ? oldLen : oldLen - 1, `length of observable array`); + } +}); + +add_task(function testObservableArray_helper_length() { + let m = new TestInterfaceObservableArray(); + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array"); + + [ + [false, true, false, true], + [true, false], + [false, true, false], + ].forEach(function(values) { + m.observableArrayBoolean = values; + is(b.length, m.booleanLengthInternal(), "length helper function"); + }); +}); +</script> +</body> +</html> diff --git a/dom/bindings/test/test_observablearray_proxyhandler.html b/dom/bindings/test/test_observablearray_proxyhandler.html new file mode 100644 index 0000000000..d7d8810981 --- /dev/null +++ b/dom/bindings/test/test_observablearray_proxyhandler.html @@ -0,0 +1,859 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> +<head> +<title>Test Observable Array Type</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> +/* global TestInterfaceObservableArray */ + +add_task(async function init() { + await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); +}); + +add_task(function testObservableArrayExoticObjects_defineProperty() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + m.observableArrayBoolean = [true, true, true]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 0"); + + // Test length + [ + // [descriptor, shouldThrow, expectedResult] + // Invalid descriptor + [{configurable: true, value: 0}, false, false], + [{enumerable: true, value: 0}, false, false], + [{writable: false, value: 0}, false, false], + [{get: ()=>{}}, false, false], + [{set: ()=>{}}, false, false], + [{get: ()=>{}, set: ()=>{}}, false, false], + [{get: ()=>{}, value: 0}, true], + // Invalid length value + [{value: 1.9}, true], + [{value: "invalid"}, true], + [{value: {}}, true], + // length value should not greater than current length + [{value: b.length + 1}, false, false], + // descriptor without value + [{configurable: false, enumerable: false, writable: true}, false, true], + // Success + [{value: b.length}, false, true], + [{value: b.length - 1}, false, true], + [{value: 0}, false, true], + ].forEach(function([descriptor, shouldThrow, expectedResult]) { + // Initialize + let oldLen = b.length; + let oldValues = b.slice(); + let deleteCallbackIndex = oldLen - 1; + let success = expectedResult && "value" in descriptor; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = null; + deleteCallbackTests = function(_value, _index) { + is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument"); + is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument"); + deleteCallbackIndex--; + }; + + // Test + info(`defining "length" property with ${JSON.stringify(descriptor)}`); + try { + is(Reflect.defineProperty(b, "length", descriptor), expectedResult, + `Reflect.defineProperty should return ${expectedResult}`); + ok(!shouldThrow, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, success ? oldLen - descriptor.value : 0, "deleteCallback count"); + isDeeply(b, success ? oldValues.slice(0, descriptor.value) : oldValues, "property values"); + is(b.length, success ? descriptor.value : oldLen, "length of observable array"); + }); + + // Test indexed value + [ + // [index, descriptor, shouldThrow, expectedResult] + // Invalid descriptor + [0, {configurable: false, value: true}, false, false], + [0, {enumerable: false, value: true}, false, false], + [0, {writable: false, value: true}, false, false], + [0, {get: ()=>{}}, false, false], + [0, {set: ()=>{}}, false, false], + [0, {get: ()=>{}, set: ()=>{}}, false, false], + [0, {get: ()=>{}, value: true}, true], + // Index could not greater than last index + 1. + [b.length + 1, {configurable: true, enumerable: true, value: true}, false, false], + // descriptor without value + [b.length, {configurable: true, enumerable: true}, false, true], + // Success + [b.length, {configurable: true, enumerable: true, value: true}, false, true], + [b.length + 1, {configurable: true, enumerable: true, value: true}, false, true], + ].forEach(function([index, descriptor, shouldThrow, expectedResult]) { + // Initialize + let oldLen = b.length; + let oldValue = b[index]; + let success = expectedResult && "value" in descriptor; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + is(_value, descriptor.value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + deleteCallbackTests = function(_value, _index) { + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`defining ${index} property with ${JSON.stringify(descriptor)}`); + try { + is(Reflect.defineProperty(b, index, descriptor), expectedResult, + `Reflect.defineProperty should return ${expectedResult}`); + ok(!shouldThrow, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, success ? 1 : 0, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], success ? descriptor.value : oldValue, "property value"); + is(b.length, success ? Math.max(index + 1, oldLen) : oldLen, "length of observable array"); + }); + + // Test other property + [ + // [property, descriptor, shouldThrow, expectedResult] + ["prop1", {configurable: false, value: "value1"}, false, true], + ["prop1", {configurable: true, value: "value2"}, false, false], + ["prop2", {enumerable: false, value: 5}, false, true], + ["prop3", {enumerable: false, value: []}, false, true], + ["prop4", {enumerable: false, value: {}}, false, true], + ["prop5", {get: ()=>{}, value: true}, true, false], + ["prop6", {get: ()=>{}, set: ()=>{}}, false, true], + ].forEach(function([property, descriptor, shouldThrow, expectedResult]) { + // Initialize + let oldValue = b[property]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = null; + deleteCallbackTests = null; + + // Test + info(`defining ${property} property with ${JSON.stringify(descriptor)}`); + try { + is(Reflect.defineProperty(b, property, descriptor), expectedResult, + `Reflect.defineProperty should return ${expectedResult}`); + ok(!shouldThrow, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 0, "deleteCallback count"); + is(b[property], expectedResult ? descriptor.value : oldValue, "property value"); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_defineProperty_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + const minLen = 3; + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (value) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (index < minLen) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, false, false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 5, "length of observable array should be 3"); + + // Test length + [ + // [length, shouldThrow] + [b.length, false], + [b.length - 1, false], + [0, true], + ].forEach(function([length, shouldThrow]) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + let descriptor = {value: length}; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`defining "length" property with ${JSON.stringify(descriptor)}`); + try { + ok(Reflect.defineProperty(b, "length", descriptor), + "Reflect.defineProperty should return true"); + ok(!shouldThrow, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, oldLen - (shouldThrow ? minLen - 1 : length), "deleteCallback count"); + isDeeply(b, oldValues.slice(0, shouldThrow ? minLen : length), "property values"); + is(b.length, shouldThrow ? minLen : length, "length of observable array"); + }); + + // Test indexed value + [ + // [index, value, shouldThrow] + [b.length, true, true], + [b.length, false, false], + [b.length + 1, false, false], + [b.length + 1, true, true], + [0, true, true], + [0, false, true], + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + let descriptor = {configurable: true, enumerable: true, value}; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`defining ${index} property with ${JSON.stringify(descriptor)}`); + try { + ok(Reflect.defineProperty(b, index, descriptor), "Reflect.defineProperty should return true"); + ok(!shouldThrow, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, (index < minLen) ? 0 : 1, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], shouldThrow ? oldValue : value, "property value"); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), "length of observable array"); + }); + + // Test other property + [ + // [property, descriptor, expectedResult] + ["prop1", {configurable: false, value: "value1"}, true], + ["prop1", {configurable: true, value: "value2"}, false], + ["prop2", {enumerable: false, value: 5}, true], + ["prop3", {enumerable: false, value: []}, true], + ["prop4", {enumerable: false, value: {}}, true], + ].forEach(function([property, descriptor, expectedResult]) { + // Initialize + let oldValue = b[property]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`defining ${property} property with ${JSON.stringify(descriptor)}`); + try { + is(Reflect.defineProperty(b, property, descriptor), expectedResult, + `Reflect.defineProperty should return ${expectedResult}`); + ok(true, "Reflect.defineProperty should not throw"); + } catch(e) { + ok(false, `Reflect.defineProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 0, "deleteCallback count"); + is(b[property], expectedResult ? descriptor.value : oldValue, "property value"); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_deleteProperty() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + m.observableArrayBoolean = [true, true]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Test length + setCallbackCount = 0; + deleteCallbackCount = 0; + info("deleting length property"); + ok(!Reflect.deleteProperty(b, "length"), "test result of deleting length property"); + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 0, "deleteCallback should not be called"); + is(b.length, 2, "length should still be 2"); + + // Test indexed value + [ + // [index, expectedResult] + [2, false], + [0, false], + [1, true], + ].forEach(function([index, expectedResult]) { + // Initialize + let oldLen = b.length; + let oldValue = b[index]; + setCallbackCount = 0; + deleteCallbackCount = 0; + deleteCallbackTests = function(_value, _index) { + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`deleting ${index} property`); + is(Reflect.deleteProperty(b, index), expectedResult, + `Reflect.deleteProperty should return ${expectedResult}`); + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, expectedResult ? 1 : 0, "deleteCallback count"); + is(b[index], expectedResult ? undefined : oldValue, "property value"); + is(b.length, expectedResult ? oldLen - 1 : oldLen, + "length of observable array"); + }); + + // Test other property + [ + // [property, value] + ["prop1", "value1"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ].forEach(function([property, value]) { + // Initialize + b[property] = value; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + deleteCallbackTests = null; + + // Test + info(`deleting ${property} property`); + is(b[property], value, `property value should be ${value} before deleting`); + ok(Reflect.deleteProperty(b, property), "Reflect.deleteProperty should return true"); + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 0, "deleteCallback count"); + is(b[property], undefined, "property value should be undefined after deleting"); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_deleteProperty_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (value) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Test indexed value + let index = b.length; + while (index--) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`deleting index ${index}`); + try { + ok(Reflect.deleteProperty(b, index), "Reflect.deleteProperty should return true"); + ok(!oldValue, "Reflect.deleteProperty should not throw"); + } catch(e) { + ok(oldValue, `Reflect.deleteProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 1, "deleteCallback count"); + is(b[index], oldValue ? oldValue : undefined, "property value"); + is(b.length, oldValue ? oldLen : oldLen - 1, "length of observable array"); + } + + // Test other property + [ + // [property, value] + ["prop1", "value1"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ["prop5", false], + ].forEach(function([property, value]) { + // Initialize + b[property] = value; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`deleting ${property} property`); + is(b[property], value, `property value should be ${JSON.stringify(value)} before deleting`); + try { + ok(Reflect.deleteProperty(b, property), `Reflect.deleteProperty should return true`); + ok(true, "Reflect.deleteProperty should not throw"); + } catch(e) { + ok(false, `Reflect.deleteProperty throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 0, "deleteCallback count"); + is(b[property], undefined, `property value should be undefined after deleting`); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_get() { + let m = new TestInterfaceObservableArray(); + m.observableArrayBoolean = [true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Test length + is(Reflect.get(b, "length"), 2, "test result of getting length property"); + + // Test indexed value + is(Reflect.get(b, 0), true, "test result of getting index 0"); + is(Reflect.get(b, 1), false, "test result of getting index 1"); + is(Reflect.get(b, 2), undefined, "test result of getting index 2"); + + // Test other property + [ + // [property, value] + ["prop1", "value1"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ].forEach(function([property, value]) { + is(Reflect.get(b, property), undefined, `test ${property} property before setting property value`); + b[property] = value; + is(Reflect.get(b, property), value, `test ${property} property after setting property value`); + }); +}); + +add_task(function testObservableArrayExoticObjects_getOwnPropertyDescriptor() { + function TestDescriptor(object, property, exist, configurable, enumerable, + writable, value) { + let descriptor = Reflect.getOwnPropertyDescriptor(object, property); + if (!exist) { + is(descriptor, undefined, `descriptor of ${property} property should be undefined`); + return; + } + + is(descriptor.configurable, configurable, `test descriptor of ${property} property (configurable)`); + is(descriptor.enumerable, enumerable, `test descriptor of ${property} property (enumerable)`); + is(descriptor.writable, writable, `test descriptor of ${property} property (writable)`); + is(descriptor.value, value, `test descriptor of ${property} property (value)`); + } + + let m = new TestInterfaceObservableArray(); + m.observableArrayBoolean = [true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Test length + TestDescriptor(b, "length", true, false /* configurable */, + false /* enumerable */, true /* writable */ , 2 /* value */); + + // Test indexed value + TestDescriptor(b, 0, true, true /* configurable */, true /* enumerable */, + true /* writable */ , true /* value */); + TestDescriptor(b, 1, true, true /* configurable */, true /* enumerable */, + true /* writable */ , false /* value */); + TestDescriptor(b, 2, false); + + // Test other property + [ + // [property, value, configurable, enumerable, writable] + ["prop1", "value1", true, true, true], + ["prop2", 5, true, true, false], + ["prop3", [], true, false, false], + ["prop4", {}, false, false, false], + ].forEach(function([property, value, configurable, enumerable, writable]) { + Object.defineProperty(b, property, { + value, + configurable, + enumerable, + writable, + }); + TestDescriptor(b, property, true, configurable, enumerable, writable , value); + }); +}); + +add_task(function testObservableArrayExoticObjects_has() { + let m = new TestInterfaceObservableArray(); + m.observableArrayBoolean = [true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Test length + ok(Reflect.has(b, "length"), `test length property`); + + // Test indexed value + ok(Reflect.has(b, 0), `test 0 property`); + ok(Reflect.has(b, 1), `test 1 property`); + ok(!Reflect.has(b, 2), `test 2 property`); + + // Test other property + [ + // [property, value] + ["prop1", "value1"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ].forEach(function([property, value]) { + ok(!Reflect.has(b, property), `test ${property} property before setting property value`); + b[property] = value; + ok(Reflect.has(b, property), `test ${property} property after setting property value`); + }); +}); + +add_task(function testObservableArrayExoticObjects_ownKeys() { + let m = new TestInterfaceObservableArray(); + m.observableArrayBoolean = [true, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 2, "length of observable array should be 2"); + + // Add other properties + b.prop1 = "value1"; + b.prop2 = 5; + b.prop3 = []; + b.prop4 = {}; + + let keys = Reflect.ownKeys(b); + SimpleTest.isDeeply(keys, ["0", "1", "length", "prop1", "prop2", "prop3", "prop4"], `test property keys`); +}); + +add_task(function testObservableArrayExoticObjects_preventExtensions() { + let m = new TestInterfaceObservableArray(); + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 0, "length of observable array should be 0"); + + // Test preventExtensions + ok(Reflect.isExtensible(b), "test isExtensible before preventExtensions"); + ok(!Reflect.preventExtensions(b), "test preventExtensions"); + ok(Reflect.isExtensible(b), "test isExtensible after preventExtensions"); +}); + +add_task(function testObservableArrayExoticObjects_set() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + let setCallbackTests = null; + let deleteCallbackTests = null; + + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (typeof setCallbackTests === 'function') { + setCallbackTests(value, index); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (typeof deleteCallbackTests === 'function') { + deleteCallbackTests(value, index); + } + }, + }); + m.observableArrayBoolean = [true, true, true]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 3, "length of observable array should be 3"); + + // Test length + [ + // [length, shouldThrow, expectedResult] + // Invalid length value + [1.9, true], + ['invalid', true], + [{}, true], + // length value should not greater than current length + [b.length + 1, false, false], + // Success + [b.length, false, true], + [b.length - 1, false, true], + [0, false, true], + ].forEach(function([length, shouldThrow, expectedResult]) { + // Initialize + let oldLen = b.length; + let oldValues = b.slice(); + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = null; + let deleteCallbackIndex = oldLen - 1; + deleteCallbackTests = function(_value, _index) { + is(_value, oldValues[deleteCallbackIndex], "deleteCallbackTests: test value argument"); + is(_index, deleteCallbackIndex, "deleteCallbackTests: test index argument"); + deleteCallbackIndex--; + }; + + // Test + info(`setting "length" property value to ${length}`); + try { + is(Reflect.set(b, "length", length), expectedResult, `Reflect.set should return ${expectedResult}`); + ok(!shouldThrow, "Reflect.set should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.set throws ${e}`); + } + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, expectedResult ? oldLen - length : 0, "deleteCallback count"); + isDeeply(b, expectedResult ? oldValues.slice(0, length) : oldValues, "property values"); + is(b.length, expectedResult ? length : oldLen, "length of observable array"); + }); + + // Test indexed value + [ + // [index, value, shouldThrow, expectedResult] + // Index could not greater than last index. + [b.length + 1, true, false, false], + // Success + [b.length, true, false, true], + [b.length + 1, true, false, true], + ].forEach(function([index, value, shouldThrow, expectedResult]) { + // Initialize + let oldLen = b.length; + let oldValue = b[index]; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = function(_value, _index) { + is(_value, value, "setCallbackTests: test value argument"); + is(_index, index, "setCallbackTests: test index argument"); + }; + deleteCallbackTests = function(_value, _index) { + is(_value, oldValue, "deleteCallbackTests: test value argument"); + is(_index, index, "deleteCallbackTests: test index argument"); + }; + + // Test + info(`setting ${index} property to ${value}`); + try { + is(Reflect.set(b, index, value), expectedResult, `Reflect.set should return ${expectedResult}`); + ok(!shouldThrow, "Reflect.set should not throw"); + } catch(e) { + ok(shouldThrow, `Reflect.set throws ${e}`); + } + is(setCallbackCount, expectedResult ? 1 : 0, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], expectedResult ? value : oldValue, "property value"); + is(b.length, expectedResult ? Math.max(index + 1, oldLen) : oldLen, "length of observable array"); + }); + + // Test other property + [ + // [property, value] + ["prop1", "value1"], + ["prop1", "value2"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ].forEach(function([property, value]) { + // Initialize + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + setCallbackTests = null; + deleteCallbackTests = null; + + // Test + info(`setting ${property} property to ${value}`); + ok(Reflect.set(b, property, value), "Reflect.defineProperty should return true"); + is(setCallbackCount, 0, "setCallback count"); + is(deleteCallbackCount, 0, "deleteCallback count"); + is(b[property], value, "property value"); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_set_callback_throw() { + let setCallbackCount = 0; + let deleteCallbackCount = 0; + + const minLen = 3; + let m = new TestInterfaceObservableArray({ + setBooleanCallback(value, index) { + setCallbackCount++; + if (value) { + throw new Error("setBooleanCallback"); + } + }, + deleteBooleanCallback(value, index) { + deleteCallbackCount++; + if (index < minLen) { + throw new Error("deleteBooleanCallback"); + } + }, + }); + m.observableArrayBoolean = [false, false, false, false, false]; + + let b = m.observableArrayBoolean; + ok(Array.isArray(b), "observable array should be an array type"); + is(b.length, 5, "length of observable array should be 3"); + + // Test length + [ + // [value, shouldThrow] + [b.length, false], + [b.length - 1, false], + [0, true], + ].forEach(function([length, shouldThrow]) { + // Initialize + let oldValues = b.slice(); + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting "length" property to ${length}`); + try { + ok(Reflect.set(b, "length", length), "Reflect.set should return true"); + ok(!shouldThrow, `Reflect.set should not throw`); + } catch(e) { + ok(shouldThrow, `Reflect.set throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, oldLen - (shouldThrow ? minLen - 1 : length), "deleteCallback count"); + isDeeply(b, oldValues.slice(0, shouldThrow ? minLen : length), "property values"); + is(b.length, shouldThrow ? minLen : length, "length of observable array"); + }); + + // Test indexed value + [ + // [index, value, shouldThrow] + [b.length, true, true], + [b.length, false, false], + [b.length + 1, false, false], + [b.length + 1, true, true], + [0, false, true], + [0, true, true], + ].forEach(function([index, value, shouldThrow]) { + // Initialize + let oldValue = b[index]; + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting ${index} property to ${value}`); + try { + ok(Reflect.set(b, index, value), "Reflect.set should return true"); + ok(!shouldThrow, `Reflect.set should not throw`); + } catch(e) { + ok(shouldThrow, `Reflect.set throws ${e}`); + } + is(setCallbackCount, (index < minLen) ? 0 : 1, "setCallback count"); + is(deleteCallbackCount, (oldLen > index) ? 1 : 0, "deleteCallback count"); + is(b[index], shouldThrow ? oldValue : value, "property value"); + is(b.length, shouldThrow ? oldLen : Math.max(oldLen, index + 1), "length of observable array"); + }); + + // Test other property + [ + ["prop1", "value1"], + ["prop1", "value2"], + ["prop2", 5], + ["prop3", []], + ["prop4", {}], + ].forEach(function([property, value]) { + // Initialize + let oldLen = b.length; + setCallbackCount = 0; + deleteCallbackCount = 0; + + // Test + info(`setting ${property} property to ${JSON.stringify(value)}`); + try { + ok(Reflect.set(b, property, value), "Reflect.set should return true"); + ok(true, `Reflect.set should not throw`); + } catch(e) { + ok(false, `Reflect.set throws ${e}`); + } + is(setCallbackCount, 0, "setCallback should not be called"); + is(deleteCallbackCount, 0, "deleteCallback should be called"); + is(b[property], value, "property value"); + is(b.length, oldLen, "length of observable array"); + }); +}); + +add_task(function testObservableArrayExoticObjects_invalidtype() { + let m = new TestInterfaceObservableArray(); + let i = m.observableArrayInterface; + ok(Array.isArray(i), "Observable array should be an array type"); + is(i.length, 0, "length should be 0"); + + [true, "invalid"].forEach(function(value) { + SimpleTest.doesThrow(() => { + let descriptor = {configurable: true, enumerable: true, writable: true, value}; + Reflect.defineProperty(i, i.length, descriptor); + }, `defining ${i.length} property with ${JSON.stringify(value)} should throw`); + + SimpleTest.doesThrow(() => { + Reflect.set(i, i.length, value); + }, `setting ${i.length} property to ${JSON.stringify(value)} should throw`); + }); + + is(i.length, 0, "length should still be 0"); +}); +</script> +</body> +</html> diff --git a/dom/bindings/test/test_oom_reporting.html b/dom/bindings/test/test_oom_reporting.html new file mode 100644 index 0000000000..3a9d734ba6 --- /dev/null +++ b/dom/bindings/test/test_oom_reporting.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id= +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug </title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug **/ + SimpleTest.waitForExplicitFinish(); + + SimpleTest.expectUncaughtException(); + setTimeout(function() { + SpecialPowers.Cu.getJSTestingFunctions().throwOutOfMemory(); + }, 0); + + addEventListener("error", function(e) { + is(e.type, "error", "Should have an error event"); + is(e.message, "uncaught exception: out of memory", + "Should have the right error message"); + // Make sure we finish async, in case the expectUncaughtException assertion + // about having seen the exception runs after our listener + SimpleTest.executeSoon(SimpleTest.finish); + }); + + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_prefOnConstructor.html b/dom/bindings/test/test_prefOnConstructor.html new file mode 100644 index 0000000000..0d8213476e --- /dev/null +++ b/dom/bindings/test/test_prefOnConstructor.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1604340 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1604340</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global WrapperCachedNonISupportsTestInterface */ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go); + + async function go() { + await SpecialPowers.pushPrefEnv({set: [["dom.webidl.test1", false]]}); + let result = null; + let constructorThrew = false; + + try { + result = new WrapperCachedNonISupportsTestInterface(); + } catch { + constructorThrew = true; + } + + is(result, null, "The result value should remain null if the constructor threw an exception as intended."); + ok(constructorThrew, "The constructor should throw an exception if its pref is not set to true."); + + await SpecialPowers.pushPrefEnv({set: [["dom.webidl.test1", true]]}); + result = null; + constructorThrew = false; + + try { + result = new WrapperCachedNonISupportsTestInterface(); + } catch { + constructorThrew = true; + } + + isnot(result, null, "Constructor should have executed successfully."); + ok(!constructorThrew, "The constructor should not throw an exception if its pref is set."); + + SimpleTest.finish(); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1604340">Mozilla Bug 1604340</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_primitive_this.html b/dom/bindings/test/test_primitive_this.html new file mode 100644 index 0000000000..086ce0f3f2 --- /dev/null +++ b/dom/bindings/test/test_primitive_this.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=603201 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 603201</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 603201 **/ + + SimpleTest.waitForExplicitFinish(); + function runTest() { + var nodes = document.body.childNodes; + + Object.setPrototypeOf(Number.prototype, nodes); + + Object.defineProperty(nodes, "getter", {get() { + "use strict"; + is(this, 1); + return "getter"; + }}); + Object.defineProperty(Object.getPrototypeOf(nodes), "getter2", {get() { + "use strict"; + is(this, 1); + return "getter2"; + }}); + + var number = 1; + is(number.getter, "getter"); + is(number.getter2, "getter2"); + + SimpleTest.finish(); + } + + </script> +</head> +<body onload="runTest();"> +<pre>Test</pre> +</body> +</html> diff --git a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html new file mode 100644 index 0000000000..ab7e15dc57 --- /dev/null +++ b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1107592 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1107592</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS, thereIsNoSuchContentFunction1, thereIsNoSuchContentFunction2, thereIsNoSuchContentFunction3 */ + /** Test for Bug 1107592 **/ + + SimpleTest.waitForExplicitFinish(); + + function checkExn(lineNumber, name, message, code, filename, testNumber, stack, exn) { + is(exn.lineNumber, lineNumber, + "Should have the right line number in test " + testNumber); + is(exn.name, name, + "Should have the right exception name in test " + testNumber); + is("filename" in exn ? exn.filename : exn.fileName, filename, + "Should have the right file name in test " + testNumber); + is(exn.message, message, + "Should have the right message in test " + testNumber); + is(exn.code, code, "Should have the right .code in test " + testNumber); + if (message === "") { + is(exn.name, "InternalError", + "Should have one of our synthetic exceptions in test " + testNumber); + } + is(exn.stack, stack, "Should have the right stack in test " + testNumber); + } + + function ensurePromiseFail(testNumber, value) { + ok(false, "Test " + testNumber + " should not have a fulfilled promise"); + } + + function doTest() { + var t = new TestInterfaceJS(); + + + var asyncStack = !SpecialPowers.getBoolPref("javascript.options.asyncstack_capture_debuggee_only"); + var ourFile = location.href; + var unwrapError = "Promise rejection value is a non-unwrappable cross-compartment wrapper."; + var parentFrame = asyncStack ? `Async*@${ourFile}:130:17 +` : ""; + + Promise.all([ + t.testPromiseWithThrowingChromePromiseInit().then( + ensurePromiseFail.bind(null, 1), + checkExn.bind(null, 49, "InternalError", unwrapError, + undefined, ourFile, 1, + `doTest@${ourFile}:49:9 +` + + parentFrame)), + t.testPromiseWithThrowingContentPromiseInit(function() { + thereIsNoSuchContentFunction1(); + }).then( + ensurePromiseFail.bind(null, 2), + checkExn.bind(null, 57, "ReferenceError", + "thereIsNoSuchContentFunction1 is not defined", + undefined, ourFile, 2, + `doTest/<@${ourFile}:57:11 +doTest@${ourFile}:56:9 +` + + parentFrame)), + t.testPromiseWithThrowingChromeThenFunction().then( + ensurePromiseFail.bind(null, 3), + checkExn.bind(null, 0, "InternalError", unwrapError, undefined, "", 3, asyncStack ? (`Async*doTest@${ourFile}:67:9 +` + + parentFrame) : "")), + t.testPromiseWithThrowingContentThenFunction(function() { + thereIsNoSuchContentFunction2(); + }).then( + ensurePromiseFail.bind(null, 4), + checkExn.bind(null, 73, "ReferenceError", + "thereIsNoSuchContentFunction2 is not defined", + undefined, ourFile, 4, + `doTest/<@${ourFile}:73:11 +` + + (asyncStack ? `Async*doTest@${ourFile}:72:9 +` : "") + + parentFrame)), + t.testPromiseWithThrowingChromeThenable().then( + ensurePromiseFail.bind(null, 5), + checkExn.bind(null, 0, "InternalError", unwrapError, undefined, "", 5, asyncStack ? (`Async*doTest@${ourFile}:84:9 +` + + parentFrame) : "")), + t.testPromiseWithThrowingContentThenable({ + then() { thereIsNoSuchContentFunction3(); }, + }).then( + ensurePromiseFail.bind(null, 6), + checkExn.bind(null, 90, "ReferenceError", + "thereIsNoSuchContentFunction3 is not defined", + undefined, ourFile, 6, + `then@${ourFile}:90:22 +` + (asyncStack ? `Async*doTest@${ourFile}:89:9\n` + parentFrame : ""))), + t.testPromiseWithDOMExceptionThrowingPromiseInit().then( + ensurePromiseFail.bind(null, 7), + checkExn.bind(null, 98, "NotFoundError", + "We are a second DOMException", + DOMException.NOT_FOUND_ERR, ourFile, 7, + `doTest@${ourFile}:98:9 +` + + parentFrame)), + t.testPromiseWithDOMExceptionThrowingThenFunction().then( + ensurePromiseFail.bind(null, 8), + checkExn.bind(null, asyncStack ? 106 : 0, "NetworkError", + "We are a third DOMException", + DOMException.NETWORK_ERR, asyncStack ? ourFile : "", 8, + (asyncStack ? `Async*doTest@${ourFile}:106:9 +` + + parentFrame : ""))), + t.testPromiseWithDOMExceptionThrowingThenable().then( + ensurePromiseFail.bind(null, 9), + checkExn.bind(null, asyncStack ? 114 : 0, "TypeMismatchError", + "We are a fourth DOMException", + DOMException.TYPE_MISMATCH_ERR, + asyncStack ? ourFile : "", 9, + (asyncStack ? `Async*doTest@${ourFile}:114:9 +` + + parentFrame : ""))), + ]).then(SimpleTest.finish, + function(err) { + ok(false, "One of our catch statements totally failed with err" + err + ", stack: " + (err ? err.stack : "")); + SimpleTest.finish(); + }); + } + + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, + doTest); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107592">Mozilla Bug 1107592</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_proxies_via_xray.html b/dom/bindings/test/test_proxies_via_xray.html new file mode 100644 index 0000000000..d7d5dc2d1e --- /dev/null +++ b/dom/bindings/test/test_proxies_via_xray.html @@ -0,0 +1,98 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1021066 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1021066</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1021066">Mozilla Bug 1021066</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_proxies_via_xray.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1021066 **/ + +function test() { + "use strict"; // So we'll get exceptions on sets + var doc = document.getElementById("t").contentWindow.document; + ok(!("x" in doc), "Should have an Xray here"); + is(doc.x, undefined, "Really should have an Xray here"); + is(doc.wrappedJSObject.x, 5, "And wrapping the right thing"); + + // Test overridebuiltins binding without named setter + is(doc.y, doc.getElementById("y"), + "Named getter should work on Document"); + try { + doc.z = 5; + ok(false, "Should have thrown on set of readonly property on Document"); + } catch (e) { + ok(/read-only/.test(e.message), + "Threw the right exception on set of readonly property on Document"); + } + + doc.w = 5; + is(doc.w, 5, "Should be able to set things that are not named props"); + + // Test non-overridebuiltins binding without named setter + var l = doc.getElementsByTagName("img"); + is(l.y, doc.getElementById("y"), + "Named getter should work on HTMLCollection"); + try { + l.z = 5; + ok(false, "Should have thrown on set of readonly property on HTMLCollection"); + } catch (e) { + ok(/read-only/.test(e.message), + "Should throw the right exception on set of readonly property on HTMLCollection"); + } + try { + l[10] = 5; + ok(false, "Should have thrown on set of indexed property on HTMLCollection"); + } catch (e) { + ok(/doesn't have an indexed property setter/.test(e.message), + "Should throw the right exception on set of indexed property on HTMLCollection"); + } + + // Test overridebuiltins binding with named setter + var d = doc.documentElement.dataset; + d.foo = "bar"; + // Check that this actually got passed on to the underlying object. + is(d.wrappedJSObject.foo, "bar", + "Set should get forwarded to the underlying object"); + is(doc.documentElement.getAttribute("data-foo"), "bar", + "Attribute setter should have been called"); + d.foo = "baz"; + // Check that this actually got passed on to the underlying object. + is(d.wrappedJSObject.foo, "baz", + "Set should get forwarded to the underlying object again"); + is(doc.documentElement.getAttribute("data-foo"), "baz", + "Attribute setter should have been called again"); + + // Test non-overridebuiltins binding with named setter + var s = doc.defaultView.localStorage; + s.test_proxies_via_xray = "bar"; + // Check that this actually got passed on to the underlying object. + is(s.wrappedJSObject.test_proxies_via_xray, "bar", + "Set should get forwarded to the underlying object without overridebuiltins"); + s.test_proxies_via_xray = "baz"; + // Check that this actually got passed on to the underlying object. + is(s.wrappedJSObject.test_proxies_via_xray, "baz", + "Set should get forwarded to the underlying object again without overridebuiltins"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_proxy_accessors.html b/dom/bindings/test/test_proxy_accessors.html new file mode 100644 index 0000000000..9474369688 --- /dev/null +++ b/dom/bindings/test/test_proxy_accessors.html @@ -0,0 +1,78 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1700052 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1700052</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1700052">Mozilla Bug 1700052</a> +<p id="display"></p> +<form id="theform"></form> +<pre id="test"> +<script> +function expandoTests() { + // Get a DOM proxy with an expando object. Define/redefine a "foo" getter/setter + // and ensure the right function is called. + + var obj = document.getElementById("theform"); + var count1 = 0, count2 = 0, count3 = 0; + var fun1 = function() { count1++; }; + var fun2 = function() { count2++; }; + var fun3 = function() { count3++; }; + + Object.defineProperty(obj, "foo", {configurable: true, get: fun1, set: fun1}); + + for (var i = 0; i < 100; i++) { + obj.foo; + obj.foo = i; + if (i === 50) { + Object.defineProperty(obj, "foo", {configurable: true, get: fun2, set: fun2}); + } else if (i === 80) { + Object.defineProperty(obj, "foo", {configurable: true, get: fun3, set: fun3}); + } + } + + is(count1, 102, "call count for fun1 must match"); + is(count2, 60, "call count for fun2 must match"); + is(count3, 38, "call count for fun3 must match"); +} +expandoTests(); + +function unshadowedTests() { + // Same as above, but for non-shadowing properties on the prototype. + + var obj = document.getElementById("theform"); + var proto = Object.getPrototypeOf(obj); + + var count1 = 0, count2 = 0; + var fun1 = function() { count1++; }; + var fun2 = function() { count2++; }; + + for (var i = 0; i < 100; i++) { + obj.name; + obj.name = "test"; + if (i === 50) { + let desc = Object.getOwnPropertyDescriptor(proto, "name"); + desc.get = desc.set = fun1; + Object.defineProperty(proto, "name", desc); + } + if (i === 90) { + let desc = Object.getOwnPropertyDescriptor(proto, "name"); + desc.get = desc.set = fun2; + Object.defineProperty(proto, "name", desc); + } + } + + is(count1, 80, "call count for fun1 must match"); + is(count2, 18, "call count for fun2 must match"); +} +unshadowedTests(); +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_proxy_expandos.html b/dom/bindings/test/test_proxy_expandos.html new file mode 100644 index 0000000000..bfe6ab598c --- /dev/null +++ b/dom/bindings/test/test_proxy_expandos.html @@ -0,0 +1,86 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=965992 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 965992</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=965992">Mozilla Bug 965992</a> +<p id="display"></p> +<form id="theform"></form> +<pre id="test"> +<script type="application/javascript"> + +// Ensure we are in JIT code and attach IC stubs. +const iterations = 50; + +function testFoo(obj, kind, expected) { + for (var i = 0; i < iterations; i++) { + obj.foo = i; + is(obj.foo, (expected === undefined) ? i : expected, + "Looking up an expando should work - " + kind); + } +} + +function getPropTests(obj) { + // Start with a plain data property. + obj.foo = "bar"; + testFoo(obj, "plain"); + + // Now change it to a scripted getter/setter. + var count = 0; + var getterSetterVal = 0; + Object.defineProperty(obj, "foo", {configurable: true, get() { + is(this, obj, "Getter should have the proxy as |this|"); + is(arguments.length, 0, "Shouldn't pass arguments to getters"); + count++; + return getterSetterVal; + }, set(v) { + is(this, obj, "Setter should have the proxy as |this|"); + is(arguments.length, 1, "Should pass 1 argument to setters"); + getterSetterVal = v; + count++; + }}); + testFoo(obj, "scripted getter/setter"); + is(count, iterations * 2, "Should have called the getter/setter enough times"); + + // Now try a native getter/setter. + Object.defineProperty(obj, "foo", {get: Math.abs, set: Math.abs, configurable: true}); + testFoo(obj, "native getter/setter", NaN); +} + +function getElemTests(obj) { + // Define two expando properties, then test inline caches for obj[prop] + // correctly guard on prop being the same. + var count = 0, getterSetterVal = 0; + obj.elem1 = 1; + Object.defineProperty(obj, "elem2", { + get() { count++; return getterSetterVal; }, + set(v) { getterSetterVal = v; count++; }, + }); + for (var i = 0; i < iterations; i++) { + var prop = ((i & 1) == 0) ? "elem1" : "elem2"; + obj[prop] = i; + is(obj[prop], i, "Should return correct property value"); + } + is(count, iterations, "Should have called the getter/setter enough times"); +} + +var directExpando = document.getElementsByTagName("*"); +var indirectExpando = document.getElementById("theform"); + +getPropTests(directExpando); +getPropTests(indirectExpando); + +getElemTests(indirectExpando); +getElemTests(directExpando); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_remoteProxyAsPrototype.html b/dom/bindings/test/test_remoteProxyAsPrototype.html new file mode 100644 index 0000000000..3c5216a443 --- /dev/null +++ b/dom/bindings/test/test_remoteProxyAsPrototype.html @@ -0,0 +1,33 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> +<head> +<title>Test for bug 1773732</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> + +SimpleTest.waitForExplicitFinish(); + +function go() { + let frame = document.createElement("iframe"); + frame.onload = () => { + let win = frame.contentWindow; + is(SpecialPowers.Cu.isRemoteProxy(win), SpecialPowers.useRemoteSubframes, + "win is a remote proxy if Fission is enabled"); + let o = {}; + Object.setPrototypeOf(o, win); + is(Object.getPrototypeOf(o), win, "should have expected proto"); + SimpleTest.finish(); + }; + frame.src = "https://example.com"; + document.body.appendChild(frame); +}; +go(); + +</script> +</body> +</html> diff --git a/dom/bindings/test/test_returnUnion.html b/dom/bindings/test/test_returnUnion.html new file mode 100644 index 0000000000..eca681068a --- /dev/null +++ b/dom/bindings/test/test_returnUnion.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1048659 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1048659</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS */ + /** Test for returning unions from JS-implemented WebIDL. **/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go); + + function go() { + var t = new TestInterfaceJS(); + var t2 = new TestInterfaceJS(); + + is(t.pingPongUnion(t2), t2, "ping pong union for left case should be identity"); + is(t.pingPongUnion(12), 12, "ping pong union for right case should be identity"); + + is(t.pingPongUnionContainingNull("this is not a string"), "this is not a string", + "ping pong union containing union for left case should be identity"); + is(t.pingPongUnionContainingNull(null), null, + "ping pong union containing null for right case null should be identity"); + is(t.pingPongUnionContainingNull(t2), t2, + "ping pong union containing null for right case should be identity"); + + is(t.pingPongNullableUnion(t2), t2, "ping pong nullable union for left case should be identity"); + is(t.pingPongNullableUnion(12), 12, "ping pong nullable union for right case should be identity"); + is(t.pingPongNullableUnion(null), null, "ping pong nullable union for null case should be identity"); + + var rejectedBadUnion = false; + var result = null; + try { + result = t.returnBadUnion(); + } catch (e) { + rejectedBadUnion = true; + } + is(result, null, "bad union should not set a value for result"); + ok(rejectedBadUnion, "bad union should throw an exception"); + + SimpleTest.finish(); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1048659">Mozilla Bug 1048659</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_sequence_detection.html b/dom/bindings/test/test_sequence_detection.html new file mode 100644 index 0000000000..714d9a5cb1 --- /dev/null +++ b/dom/bindings/test/test_sequence_detection.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1066432 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1066432</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /* global TestInterfaceJS */ + /** Test for Bug 1066432 **/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { + var testInterfaceJS = new TestInterfaceJS(); + ok(testInterfaceJS, "got a TestInterfaceJS object"); + + var nonIterableObject = {[Symbol.iterator]: 5}; + + try { + testInterfaceJS.testSequenceOverload(nonIterableObject); + ok(false, "Should have thrown in the overload case"); // see long comment above! + } catch (e) { + is(e.name, "TypeError", "Should get a TypeError for the overload case"); + ok(e.message.includes("not iterable"), + "Should have a message about being non-iterable in the overload case"); + } + + try { + testInterfaceJS.testSequenceUnion(nonIterableObject); + ok(false, "Should have thrown in the union case"); + } catch (e) { + is(e.name, "TypeError", "Should get a TypeError for the union case"); + ok(e.message.includes("not iterable"), + "Should have a message about being non-iterable in the union case"); + } + + SimpleTest.finish(); + }); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1066432">Mozilla Bug 1066432</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_sequence_wrapping.html b/dom/bindings/test/test_sequence_wrapping.html new file mode 100644 index 0000000000..bac95e01d3 --- /dev/null +++ b/dom/bindings/test/test_sequence_wrapping.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=775852 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 775852</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=775852">Mozilla Bug 775852</a> +<p id="display"></p> +<div id="content" style="display: none"> + <canvas width="1" height="1" id="c"></canvas> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 775852 **/ +function doTest() { + var gl = $("c").getContext("experimental-webgl"); + if (!gl) { + // No WebGL support on MacOS 10.5. Just skip this test + todo(false, "WebGL not supported"); + return; + } + var setterCalled = false; + + var extLength = gl.getSupportedExtensions().length; + ok(extLength > 0, + "This test won't work right if we have no supported extensions"); + + Object.defineProperty(Array.prototype, "0", + { + set(val) { + setterCalled = true; + }, + }); + + // Test that our property got defined correctly + var arr = []; + arr[0] = 5; + is(setterCalled, true, "Setter should be called when setting prop on array"); + + setterCalled = false; + + is(gl.getSupportedExtensions().length, extLength, + "We should still have the same number of extensions"); + + is(setterCalled, false, + "Setter should not be called when getting supported extensions"); +} +doTest(); +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html b/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html new file mode 100644 index 0000000000..ec5b048987 --- /dev/null +++ b/dom/bindings/test/test_setWithNamedGetterNoNamedSetter.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1043690 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1043690</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1043690">Mozilla Bug 1043690</a> +<p id="display"></p> +<div id="content" style="display: none"> +<form> + <input name="action"> +</form> +</div> + <script type="application/javascript"> + + /** Test for Bug 1043690 **/ + var f = document.querySelector("form"); + var i = document.querySelector("input"); + is(f.getAttribute("action"), null, "Should have no action attribute"); + is(f.action, i, "form.action should be the input"); + f.action = "http://example.org"; + is(f.getAttribute("action"), "http://example.org", + "Should have an action attribute now"); + is(f.action, i, "form.action should still be the input"); + i.remove(); + is(f.action, "http://example.org/", + "form.action should no longer be shadowed"); + + + </script> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_stringBindings.html b/dom/bindings/test/test_stringBindings.html new file mode 100644 index 0000000000..ad8b60df07 --- /dev/null +++ b/dom/bindings/test/test_stringBindings.html @@ -0,0 +1,109 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1334537 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1334537</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1334537 **/ + SimpleTest.waitForExplicitFinish(); + + function go() { + // Need a new global that will pick up our pref. + var ifr = document.createElement("iframe"); + document.body.appendChild(ifr); + + var t = new ifr.contentWindow.TestFunctions(); + var testString = "abcdefghijklmnopqrstuvwxyz"; + const substringLength = 10; + var shortTestString = testString.substring(0, substringLength); + + t.setStringData(testString); + // Note: we want to do all our gets before we start running code we don't + // control inside the test harness, if we really want to exercise the string + // cache in controlled ways. + + var asShortDOMString = t.getStringDataAsDOMString(substringLength); + var asFullDOMString = t.getStringDataAsDOMString(); + var asShortAString = t.getStringDataAsAString(substringLength); + var asAString = t.getStringDataAsAString(); + + is(asShortDOMString, shortTestString, "Short DOMString should be short"); + is(asFullDOMString, testString, "Full DOMString should be test string"); + is(asShortAString, shortTestString, "Short AString should be short"); + is(asAString, testString, "Full AString should be test string"); + + // These strings should match the strings used in TestFunctions.cpp, but we + // want to launder them through something on the JS side that will convert + // them into strings stored in the JS heap. + function launder(str) { + // This should be sufficient, but if the JIT gets too smart we may need + // to get more clever. + return str.split("").join(""); + } + var shortString = launder(t.getShortLiteralString()); + var mediumString = launder(t.getMediumLiteralString()); + var longString = launder(t.getLongLiteralString()); + + // A short or medium non-external string will become an inline FakeString. + is(t.getStringType(shortString), "inline", + "Short string should become inline"); + is(t.getStringType(mediumString), "inline", + "Medium string should become inline"); + // A long string will become a stringbuffer FakeString on the way in. + is(t.getStringType(longString), "stringbuffer", + "Long string should become a stringbuffer"); + + // A short literal string will become an inline JS string on the way out + // and then become an inline FakeString on the way in. + is(t.getStringType(t.getShortLiteralString()), "inline", + "Short literal string should become inline"); + // A medium or long literal string will become an external JS string on the + // way out and then become a literal FakeString on the way in. + is(t.getStringType(t.getMediumLiteralString()), "literal", + "Medium literal string should become literal"); + is(t.getStringType(t.getLongLiteralString()), "literal", + "Long literal string should become literal"); + + // A short stringbuffer string will become an inline JS string on the way + // out and then become an inline FakeString on the way in. + is(t.getStringType(t.getStringbufferString(shortString)), "inline", + "Short stringbuffer string should become inline"); + // A medium or long stringbuffer string will become an external JS string + // on the way out and then become a stringbuffer FakeString on the way in. + is(t.getStringType(t.getStringbufferString(mediumString)), "stringbuffer", + "Medium stringbuffer string should become stringbuffer"); + is(t.getStringType(t.getStringbufferString(longString)), "stringbuffer", + "Long stringbuffer string should become stringbuffer"); + + // Now test that roundtripping works fine. We need to make sure the string + // we are storing is not equal to any of the ones we have used above, to + // avoid the external string cache interfering. + t.setStringData(longString + "unique"); // Should store with stringbuffer. + ok(t.stringbufferMatchesStored(t.getStringDataAsAString()), + "Stringbuffer should have roundtripped"); + + SimpleTest.finish(); + } + + addLoadEvent(function() { + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, + go); + }); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1334537">Mozilla Bug 1334537</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_throwing_method_noDCE.html b/dom/bindings/test/test_throwing_method_noDCE.html new file mode 100644 index 0000000000..92d1a0b7f9 --- /dev/null +++ b/dom/bindings/test/test_throwing_method_noDCE.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test that we don't DCE functions that can throw</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +/* global test, assert_true */ +test(function() { + function test(root) { + var threw = false; + try { + root.querySelectorAll(""); + } catch (e) { threw = true; } + // Hot loop to make sure the JIT heuristics ion-compile this function even + // though it's throwing exceptions (which would normally make us back off + // of ion compilation). + for (var i = 0; i < 1500; i++) { + // empty + } + return threw; + } + + var threw = false; + var el = document.createElement("div"); + for (var i = 0; i < 200; i++) + threw = test(el); + assert_true(threw); +}, "Shouldn't optimize away throwing functions"); +</script> diff --git a/dom/bindings/test/test_toJSON.html b/dom/bindings/test/test_toJSON.html new file mode 100644 index 0000000000..9bd9a5989a --- /dev/null +++ b/dom/bindings/test/test_toJSON.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1465602 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1465602</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1465602">Mozilla Bug 1465602</a> +<p id="display"></p> +<div id="content" style="display: none"> + <iframe></iframe> +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + /* global TestFunctions */ + /** Test for Bug 1465602 **/ + + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go); + + function go() { + var ourObj = new TestFunctions(); + is(ourObj.one, 1, "Basic sanity check for our 'one'"); + is(ourObj.two, undefined, "Basic sanity check for our 'two'"); + + var otherObj = new frames[0].TestFunctions(); + is(otherObj.one, 1, "Basic sanity check for subframe 'one'"); + is(otherObj.two, 2, "Basic sanity check for subframe 'two'"); + + var ourToJSON = ourObj.toJSON(); + is(ourToJSON.one, 1, "We should have correct value for 'one'"); + is(ourToJSON.two, undefined, "We should have correct value for 'two'"); + ok(!Object.hasOwnProperty(ourToJSON, "two"), + "We should not have a property named 'two'"); + + var otherToJSON = otherObj.toJSON(); + is(otherToJSON.one, 1, "Subframe should have correct value for 'one'"); + is(otherToJSON.two, 2, "Subframe should have correct value for 'two'"); + + var mixedToJSON = ourObj.toJSON.call(otherObj); + is(mixedToJSON.one, 1, "First test should have correct value for 'one'"); + is(mixedToJSON.two, 2, "First test should have correct value for 'two'"); + + mixedToJSON = otherObj.toJSON.call(ourObj); + is(mixedToJSON.one, 1, "Second test should have correct value for 'one'"); + is(mixedToJSON.two, undefined, + "Second test should have correct value for 'two'"); + + SimpleTest.finish(); + } + </script> +</body> +</html> diff --git a/dom/bindings/test/test_traceProtos.html b/dom/bindings/test/test_traceProtos.html new file mode 100644 index 0000000000..b649b6ec8c --- /dev/null +++ b/dom/bindings/test/test_traceProtos.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=744772 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 744772</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=744772">Mozilla Bug 744772</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 744772 **/ + +SimpleTest.waitForExplicitFinish(); + +function callback() { + new XMLHttpRequest().upload; + ok(true, "Accessing unreferenced DOM interface objects shouldn't crash"); + SimpleTest.finish(); +} + +delete window.XMLHttpRequestUpload; +SpecialPowers.exactGC(callback); + +</script> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_treat_non_object_as_null.html b/dom/bindings/test/test_treat_non_object_as_null.html new file mode 100644 index 0000000000..785a2ebc71 --- /dev/null +++ b/dom/bindings/test/test_treat_non_object_as_null.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=952365 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 952365</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 952365 **/ + + var onvolumechange; + var x = {}; + + (function() { + onvolumechange = x; + is(onvolumechange, x, + "Should preserve an object value when assigning to event handler"); + // Test that we don't try to actually call the non-callable object + window.dispatchEvent(new Event("volumechange")); + onvolumechange = 5; + is(onvolumechange, null, + "Non-object values should become null when assigning to event handler"); + })(); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=952365">Mozilla Bug 952365</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/bindings/test/test_unforgeablesonexpando.html b/dom/bindings/test/test_unforgeablesonexpando.html new file mode 100644 index 0000000000..3db4350c9a --- /dev/null +++ b/dom/bindings/test/test_unforgeablesonexpando.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for making sure named getters don't override the unforgeable location on HTMLDocument</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<img name="location"> +<script> +/* global test, assert_equals */ +test(function() { + assert_equals(document.location, window.location, + 'The <img name="location"> should not override the location getter'); +}, "document.location is the right thing"); +test(function() { + var doc = new DOMParser().parseFromString("<img name='location'>", "text/html"); + assert_equals(doc.location, null, + 'The <img name="location"> should not override the location getter on a data document'); +}, "document.location is the right thing on non-rendered document"); +</script> diff --git a/dom/bindings/test/test_usvstring.html b/dom/bindings/test/test_usvstring.html new file mode 100644 index 0000000000..bef4d5e1fa --- /dev/null +++ b/dom/bindings/test/test_usvstring.html @@ -0,0 +1,43 @@ +<!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> +<head> + <title>Test USVString</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script class="testbody" type="application/javascript"> +/* global TestInterfaceJS */ + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { + var testInterfaceJS = new TestInterfaceJS(); + ok(testInterfaceJS, "got a TestInterfaceJS object"); + // For expected values, see algorithm definition here: + // http://heycam.github.io/webidl/#dfn-obtain-unicode + var testList = [ + { string: "foo", + expected: "foo" }, + { string: "This is U+2070E: \ud841\udf0e", + expected: "This is U+2070E: \ud841\udf0e" }, + { string: "Missing low surrogate: \ud841", + expected: "Missing low surrogate: \ufffd" }, + { string: "Missing low surrogate with trailer: \ud841!!", + expected: "Missing low surrogate with trailer: \ufffd!!" }, + { string: "Missing high surrogate: \udf0e", + expected: "Missing high surrogate: \ufffd" }, + { string: "Missing high surrogate with trailer: \udf0e!!", + expected: "Missing high surrogate with trailer: \ufffd!!" }, + { string: "U+2070E after malformed: \udf0e\ud841\udf0e", + expected: "U+2070E after malformed: \ufffd\ud841\udf0e" }, + ]; + testList.forEach(function(test) { + is(testInterfaceJS.convertSVS(test.string), test.expected, "Convert '" + test.string + "'"); + }); + SimpleTest.finish(); +}); +</script> +</body> +</html> diff --git a/dom/bindings/test/test_worker_UnwrapArg.html b/dom/bindings/test/test_worker_UnwrapArg.html new file mode 100644 index 0000000000..8bc23fa630 --- /dev/null +++ b/dom/bindings/test/test_worker_UnwrapArg.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1127206 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1127206</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1127206 **/ + SimpleTest.waitForExplicitFinish(); + var blob = new Blob([ + `try { new File({}); } + catch (e) { + postMessage("throwing on random object"); + } + try { new File(new Blob(["abc"])); } + catch (e) { + postMessage("throwing on Blob"); + } + try { new File("abc"); } + catch (e) { + postMessage("throwing on string"); + } + postMessage('finishTest')`]); + var url = URL.createObjectURL(blob); + var w = new Worker(url); + var expectedResults = [ + "throwing on random object", + "throwing on Blob", + "throwing on string", + ]; + var curIndex = 0; + w.onmessage = function(e) { + if (curIndex == expectedResults.length) { + is(e.data, "finishTest", "What message is this?"); + SimpleTest.finish(); + } else { + is(e.data, expectedResults[curIndex], + "Message " + (curIndex + 1) + " should be correct"); + ++curIndex; + } + }; + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1127206">Mozilla Bug 1127206</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> |