mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1669552 - Add TestUtils support for WPT r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D135942
This commit is contained in:
parent
af8f04a00d
commit
624a3640bf
58
dom/base/TestUtils.cpp
Normal file
58
dom/base/TestUtils.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- 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/TestUtils.h"
|
||||
#include "mozilla/dom/TestUtilsBinding.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestUtils, mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(TestUtils)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(TestUtils)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestUtils)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject* TestUtils::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return TestUtils_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> TestUtils::Gc(ErrorResult& aRv) {
|
||||
RefPtr<Promise> promise = Promise::Create(mOwner, aRv);
|
||||
|
||||
// TODO(krosylight): Ideally we could use nsJSContext::IncrementalGC to make
|
||||
// it actually async, but that's not required right now.
|
||||
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewCancelableRunnableFunction("TestUtils::Gc", [promise] {
|
||||
if (NS_IsMainThread()) {
|
||||
nsJSContext::GarbageCollectNow(JS::GCReason::DOM_TESTUTILS,
|
||||
nsJSContext::NonIncrementalGC,
|
||||
nsJSContext::NonShrinkingGC);
|
||||
nsJSContext::CycleCollectNow(CCReason::API);
|
||||
} else {
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
workerPrivate->GarbageCollectInternal(workerPrivate->GetJSContext(),
|
||||
false /* shrinking */,
|
||||
false /* collect children */);
|
||||
workerPrivate->CycleCollectInternal(false);
|
||||
}
|
||||
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
43
dom/base/TestUtils.h
Normal file
43
dom/base/TestUtils.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- 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 DOM_TESTING_TESTUTILS_H_
|
||||
#define DOM_TESTING_TESTUTILS_H_
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class TestUtils final : public nsISupports, public nsWrapperCache {
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestUtils)
|
||||
|
||||
explicit TestUtils(nsIGlobalObject* aGlobal) : mOwner(aGlobal) {}
|
||||
|
||||
nsIGlobalObject* GetParentObject() const { return mOwner; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
already_AddRefed<Promise> Gc(ErrorResult& aRv);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
~TestUtils() = default;
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // DOM_TESTING_TESTUTILS_H_
|
@ -272,6 +272,7 @@ EXPORTS.mozilla.dom += [
|
||||
"StyleSheetList.h",
|
||||
"SubtleCrypto.h",
|
||||
"SyncMessageSender.h",
|
||||
"TestUtils.h",
|
||||
"Text.h",
|
||||
"Timeout.h",
|
||||
"TimeoutHandler.h",
|
||||
@ -446,6 +447,7 @@ UNIFIED_SOURCES += [
|
||||
"StyledRange.cpp",
|
||||
"StyleSheetList.cpp",
|
||||
"SubtleCrypto.cpp",
|
||||
"TestUtils.cpp",
|
||||
"Text.cpp",
|
||||
"TextInputProcessor.cpp",
|
||||
"ThirdPartyUtil.cpp",
|
||||
|
@ -164,6 +164,7 @@
|
||||
#include "mozilla/dom/StorageNotifierService.h"
|
||||
#include "mozilla/dom/StorageUtils.h"
|
||||
#include "mozilla/dom/TabMessageTypes.h"
|
||||
#include "mozilla/dom/TestUtils.h"
|
||||
#include "mozilla/dom/Timeout.h"
|
||||
#include "mozilla/dom/TimeoutHandler.h"
|
||||
#include "mozilla/dom/TimeoutManager.h"
|
||||
@ -1429,6 +1430,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTestUtils)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)
|
||||
|
||||
@ -1535,6 +1537,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTestUtils)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)
|
||||
|
||||
@ -7479,6 +7482,15 @@ void nsGlobalWindowInner::StructuredClone(
|
||||
nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError);
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::TestUtils> nsGlobalWindowInner::TestUtils() {
|
||||
if (!mTestUtils) {
|
||||
mTestUtils = new class TestUtils(AsGlobal());
|
||||
}
|
||||
|
||||
RefPtr<class TestUtils> ref = mTestUtils;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsresult nsGlobalWindowInner::Dispatch(
|
||||
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
@ -129,6 +129,7 @@ class SharedWorker;
|
||||
class Selection;
|
||||
class SpeechSynthesis;
|
||||
class Timeout;
|
||||
class TestUtils;
|
||||
class U2F;
|
||||
class VisualViewport;
|
||||
class VRDisplay;
|
||||
@ -914,6 +915,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<mozilla::dom::TestUtils> TestUtils();
|
||||
|
||||
// ChromeWindow bits. Do NOT call these unless your window is in
|
||||
// fact chrome.
|
||||
uint16_t WindowState();
|
||||
@ -1440,6 +1443,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
||||
|
||||
RefPtr<mozilla::dom::VisualViewport> mVisualViewport;
|
||||
|
||||
RefPtr<mozilla::dom::TestUtils> mTestUtils;
|
||||
|
||||
// The document's principals and CSP are only stored if
|
||||
// FreeInnerObjects has been called.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
14
dom/webidl/TestUtils.webidl
Normal file
14
dom/webidl/TestUtils.webidl
Normal file
@ -0,0 +1,14 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://testutils.spec.whatwg.org/#the-testutils-object
|
||||
*/
|
||||
|
||||
[Exposed=(Window,Worker),
|
||||
Pref="dom.testing.testutils.enabled"]
|
||||
interface TestUtils {
|
||||
[NewObject, Throws] Promise<void> gc();
|
||||
};
|
@ -79,3 +79,9 @@ partial interface mixin WindowOrWorkerGlobalScope {
|
||||
[Throws, Pref="dom.caches.enabled", SameObject]
|
||||
readonly attribute CacheStorage caches;
|
||||
};
|
||||
|
||||
// https://testutils.spec.whatwg.org/#the-testutils-object
|
||||
partial interface mixin WindowOrWorkerGlobalScope {
|
||||
[Pref="dom.testing.testutils.enabled", SameObject]
|
||||
readonly attribute TestUtils testUtils;
|
||||
};
|
||||
|
@ -933,6 +933,7 @@ WEBIDL_FILES = [
|
||||
"TCPSocket.webidl",
|
||||
"TCPSocketErrorEvent.webidl",
|
||||
"TCPSocketEvent.webidl",
|
||||
"TestUtils.webidl",
|
||||
"Text.webidl",
|
||||
"TextClause.webidl",
|
||||
"TextDecoder.webidl",
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
|
||||
#include "mozilla/dom/SimpleGlobalObject.h"
|
||||
#include "mozilla/dom/TimeoutHandler.h"
|
||||
#include "mozilla/dom/TestUtils.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
|
||||
#include "mozilla/dom/WorkerGlobalScopeBinding.h"
|
||||
@ -363,6 +364,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTestUtils)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
@ -374,6 +376,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTestUtils)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
@ -404,6 +407,15 @@ already_AddRefed<CacheStorage> WorkerGlobalScope::GetCaches(ErrorResult& aRv) {
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::TestUtils> WorkerGlobalScope::TestUtils() {
|
||||
if (!mTestUtils) {
|
||||
mTestUtils = new class TestUtils(this);
|
||||
}
|
||||
|
||||
RefPtr<class TestUtils> ref = mTestUtils;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
bool WorkerGlobalScope::IsSecureContext() const {
|
||||
bool globalSecure = JS::GetIsSecureContext(
|
||||
js::GetNonCCWObjectRealm(GetWrapperPreserveColor()));
|
||||
|
@ -71,6 +71,7 @@ class ServiceWorkerDescriptor;
|
||||
class ServiceWorkerRegistration;
|
||||
class ServiceWorkerRegistrationDescriptor;
|
||||
struct StructuredSerializeOptions;
|
||||
class TestUtils;
|
||||
class WorkerDocumentListener;
|
||||
class WorkerLocation;
|
||||
class WorkerNavigator;
|
||||
@ -298,6 +299,8 @@ class WorkerGlobalScope : public WorkerGlobalScopeBase,
|
||||
|
||||
already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<mozilla::dom::TestUtils> TestUtils();
|
||||
|
||||
bool WindowInteractionAllowed() const;
|
||||
|
||||
void AllowWindowInteraction();
|
||||
@ -332,6 +335,7 @@ class WorkerGlobalScope : public WorkerGlobalScopeBase,
|
||||
RefPtr<Performance> mPerformance;
|
||||
RefPtr<IDBFactory> mIndexedDB;
|
||||
RefPtr<cache::CacheStorage> mCacheStorage;
|
||||
RefPtr<class TestUtils> mTestUtils;
|
||||
RefPtr<DebuggerNotificationManager> mDebuggerNotificationManager;
|
||||
uint32_t mWindowInteractionsAllowed = 0;
|
||||
};
|
||||
|
@ -586,6 +586,7 @@ namespace JS {
|
||||
D(XPCONNECT_SHUTDOWN, 53) \
|
||||
D(DOCSHELL, 54) \
|
||||
D(HTML_PARSER, 55) \
|
||||
D(DOM_TESTUTILS, 56) \
|
||||
\
|
||||
/* Reasons reserved for embeddings. */ \
|
||||
D(RESERVED1, FIRST_RESERVED_REASON) \
|
||||
|
@ -3532,6 +3532,12 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# To enable TestUtils interface on WPT
|
||||
- name: dom.testing.testutils.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: dom.textMetrics.actualBoundingBox.enabled
|
||||
type: bool
|
||||
value: true
|
||||
|
@ -11,6 +11,8 @@ user_pref("browser.sessionstore.resume_from_crash", false);
|
||||
// Don't show the Bookmarks Toolbar on any tab (the above pref that
|
||||
// disables the New Tab Page ends up showing the toolbar on about:blank).
|
||||
user_pref("browser.toolbars.bookmarks.visibility", "never");
|
||||
// Expose TestUtils interface
|
||||
user_pref("dom.testing.testutils.enabled", true);
|
||||
// Only install add-ons from the profile and the application scope
|
||||
// Also ensure that those are not getting disabled.
|
||||
// see: https://developer.mozilla.org/en/Installing_extensions
|
||||
|
@ -7,8 +7,9 @@
|
||||
// if perform_gc is true.
|
||||
async function read_and_gc(reader, perform_gc) {
|
||||
const read_promise = reader.read();
|
||||
if (perform_gc)
|
||||
garbageCollect();
|
||||
if (perform_gc) {
|
||||
await garbageCollect();
|
||||
}
|
||||
return read_promise;
|
||||
}
|
||||
|
||||
@ -65,7 +66,7 @@ promise_test(async() => {
|
||||
let blob = new Blob([typed_arr]);
|
||||
const stream = blob.stream();
|
||||
blob = null;
|
||||
garbageCollect();
|
||||
await garbageCollect();
|
||||
const chunks = await read_all_chunks(stream, /*perform_gc=*/true);
|
||||
assert_array_equals(chunks, input_arr);
|
||||
}, "Blob.stream() garbage collection of blob shouldn't break stream" +
|
||||
|
@ -11,8 +11,8 @@
|
||||
* @return {undefined}
|
||||
*/
|
||||
async function maybeGarbageCollectAsync() {
|
||||
if (typeof TestUtils !== 'undefined' && TestUtils.gc) {
|
||||
await TestUtils.gc();
|
||||
if (typeof testUtils !== 'undefined' && testUtils.gc) {
|
||||
await testUtils.gc();
|
||||
} else if (self.gc) {
|
||||
// Use --expose_gc for V8 (and Node.js)
|
||||
// to pass this flag at chrome launch use: --js-flags="--expose-gc"
|
||||
|
@ -2,7 +2,7 @@
|
||||
// META: script=../resources/test-utils.js
|
||||
'use strict';
|
||||
|
||||
promise_test(() => {
|
||||
promise_test(async () => {
|
||||
|
||||
let controller;
|
||||
new ReadableStream({
|
||||
@ -11,7 +11,7 @@ promise_test(() => {
|
||||
}
|
||||
});
|
||||
|
||||
garbageCollect();
|
||||
await garbageCollect();
|
||||
|
||||
return delay(50).then(() => {
|
||||
controller.close();
|
||||
@ -22,7 +22,7 @@ promise_test(() => {
|
||||
}, 'ReadableStreamController methods should continue working properly when scripts lose their reference to the ' +
|
||||
'readable stream');
|
||||
|
||||
promise_test(() => {
|
||||
promise_test(async () => {
|
||||
|
||||
let controller;
|
||||
|
||||
@ -32,13 +32,13 @@ promise_test(() => {
|
||||
}
|
||||
}).getReader().closed;
|
||||
|
||||
garbageCollect();
|
||||
await garbageCollect();
|
||||
|
||||
return delay(50).then(() => controller.close()).then(() => closedPromise);
|
||||
|
||||
}, 'ReadableStream closed promise should fulfill even if the stream and reader JS references are lost');
|
||||
|
||||
promise_test(t => {
|
||||
promise_test(async t => {
|
||||
|
||||
const theError = new Error('boo');
|
||||
let controller;
|
||||
@ -49,20 +49,20 @@ promise_test(t => {
|
||||
}
|
||||
}).getReader().closed;
|
||||
|
||||
garbageCollect();
|
||||
await garbageCollect();
|
||||
|
||||
return delay(50).then(() => controller.error(theError))
|
||||
.then(() => promise_rejects_exactly(t, theError, closedPromise));
|
||||
|
||||
}, 'ReadableStream closed promise should reject even if stream and reader JS references are lost');
|
||||
|
||||
promise_test(() => {
|
||||
promise_test(async () => {
|
||||
|
||||
const rs = new ReadableStream({});
|
||||
|
||||
rs.getReader();
|
||||
|
||||
garbageCollect();
|
||||
await garbageCollect();
|
||||
|
||||
return delay(50).then(() => assert_throws_js(TypeError, () => rs.getReader(),
|
||||
'old reader should still be locking the stream even after garbage collection'));
|
||||
|
@ -47,8 +47,11 @@ self.constructorThrowsForAll = (constructor, firstArgs) => {
|
||||
'constructor should throw a TypeError'));
|
||||
};
|
||||
|
||||
self.garbageCollect = () => {
|
||||
if (self.gc) {
|
||||
self.garbageCollect = async () => {
|
||||
if (self.testUtils?.gc) {
|
||||
// https://testutils.spec.whatwg.org/#the-testutils-object
|
||||
await testUtils.gc();
|
||||
} else if (self.gc) {
|
||||
// Use --expose_gc for V8 (and Node.js)
|
||||
// to pass this flag at chrome launch use: --js-flags="--expose-gc"
|
||||
// Exposed in SpiderMonkey shell as well
|
||||
|
Loading…
Reference in New Issue
Block a user