Bug 1290021 - Implement a prototype version of Houdini "Worklets Level 1" spec - part 1 - WebIDL interface, r=smaug

This commit is contained in:
Andrea Marchesini 2016-11-06 09:53:34 +01:00
Родитель 100e73de5a
Коммит 31cddcde1d
13 изменённых файлов: 303 добавлений и 0 удалений

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

@ -237,6 +237,7 @@
#include "mozilla/dom/ServiceWorkerRegistration.h"
#include "mozilla/dom/U2F.h"
#include "mozilla/dom/WebIDLGlobalNameHash.h"
#include "mozilla/dom/Worklet.h"
#ifdef HAVE_SIDEBAR
#include "mozilla/dom/ExternalBinding.h"
#endif
@ -14848,6 +14849,13 @@ nsGlobalWindow::TemporarilyDisableDialogs::~TemporarilyDisableDialogs()
}
}
already_AddRefed<Worklet>
nsGlobalWindow::CreateWorklet(ErrorResult& aRv)
{
RefPtr<Worklet> worklet = new Worklet(this);
return worklet.forget();
}
template class nsPIDOMWindow<mozIDOMWindowProxy>;
template class nsPIDOMWindow<mozIDOMWindow>;
template class nsPIDOMWindow<nsISupports>;

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

@ -136,6 +136,7 @@ class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
#endif
class Worklet;
namespace cache {
class CacheStorage;
} // namespace cache
@ -926,6 +927,10 @@ public:
static void
ConvertDialogOptions(const nsAString& aOptions, nsAString& aResult);
// Exposed only for testing
already_AddRefed<mozilla::dom::Worklet>
CreateWorklet(mozilla::ErrorResult& aRv);
protected:
bool AlertOrConfirm(bool aAlert, const nsAString& aMessage,
nsIPrincipal& aSubjectPrincipal,

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

@ -101,6 +101,7 @@ DIRS += [
'console',
'performance',
'xhr',
'worklet',
]
if CONFIG['OS_ARCH'] == 'WINNT':

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

@ -486,6 +486,12 @@ partial interface Window {
attribute EventHandler onvrdisplaypresentchange;
};
// For testing worklet only
partial interface Window {
[Pref="dom.worklet.testing.enabled", Throws]
Worklet createWorklet();
};
Window implements ChromeWindow;
Window implements WindowOrWorkerGlobalScope;

14
dom/webidl/Worklet.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://drafts.css-houdini.org/worklets/#idl-index
*/
[Pref="dom.worklet.enabled"]
interface Worklet {
[NewObject, Throws]
Promise<void> import(USVString moduleURL);
};

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

@ -581,6 +581,7 @@ WEBIDL_FILES = [
'WorkerGlobalScope.webidl',
'WorkerLocation.webidl',
'WorkerNavigator.webidl',
'Worklet.webidl',
'XMLDocument.webidl',
'XMLHttpRequest.webidl',
'XMLHttpRequestEventTarget.webidl',

121
dom/worklet/Worklet.cpp Normal file
Просмотреть файл

@ -0,0 +1,121 @@
/* -*- 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 "Worklet.h"
#include "mozilla/dom/WorkletBinding.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/Response.h"
namespace mozilla {
namespace dom {
namespace {
class WorkletFetchHandler : public PromiseNativeHandler
{
public:
NS_DECL_ISUPPORTS
static already_AddRefed<Promise>
Fetch(Worklet* aWorklet, const nsAString& aModuleURL, ErrorResult& aRv)
{
RefPtr<Promise> promise = Promise::Create(aWorklet->GetParentObject(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RequestOrUSVString request;
request.SetAsUSVString().Rebind(aModuleURL.Data(), aModuleURL.Length());
RequestInit init;
RefPtr<Promise> fetchPromise =
FetchRequest(aWorklet->GetParentObject(), request, init, aRv);
if (NS_WARN_IF(aRv.Failed())) {
promise->MaybeReject(aRv);
return promise.forget();
}
RefPtr<WorkletFetchHandler> handler =
new WorkletFetchHandler(aWorklet, promise);
fetchPromise->AppendNativeHandler(handler);
return promise.forget();
}
virtual void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
if (!aValue.isObject()) {
mPromise->MaybeReject(NS_ERROR_FAILURE);
return;
}
RefPtr<Response> response;
nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPromise->MaybeReject(rv);
return;
}
if (!response->Ok()) {
mPromise->MaybeReject(NS_ERROR_DOM_NETWORK_ERR);
return;
}
// TODO: do something with this response...
mPromise->MaybeResolveWithUndefined();
}
virtual void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
mPromise->MaybeReject(aCx, aValue);
}
private:
WorkletFetchHandler(Worklet* aWorklet, Promise* aPromise)
: mWorklet(aWorklet)
, mPromise(aPromise)
{}
~WorkletFetchHandler()
{}
RefPtr<Worklet> mWorklet;
RefPtr<Promise> mPromise;
};
NS_IMPL_ISUPPORTS0(WorkletFetchHandler)
} // anonymous namespace
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Worklet, mGlobal)
NS_IMPL_CYCLE_COLLECTING_ADDREF(Worklet)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Worklet)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Worklet)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
JSObject*
Worklet::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return WorkletBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
Worklet::Import(const nsAString& aModuleURL, ErrorResult& aRv)
{
return WorkletFetchHandler::Fetch(this, aModuleURL, aRv);
}
} // dom namespace
} // mozilla namespace

54
dom/worklet/Worklet.h Normal file
Просмотреть файл

@ -0,0 +1,54 @@
/* -*- 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_Worklet_h
#define mozilla_dom_Worklet_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
class nsIGlobalObject;
namespace mozilla {
namespace dom {
class Promise;
class Worklet final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Worklet)
explicit Worklet(nsIGlobalObject* aGlobal)
: mGlobal(aGlobal)
{}
nsIGlobalObject* GetParentObject() const
{
return mGlobal;
}
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<Promise>
Import(const nsAString& aModuleURL, ErrorResult& aRv);
private:
~Worklet()
{}
nsCOMPtr<nsIGlobalObject> mGlobal;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_Worklet_h

19
dom/worklet/moz.build Normal file
Просмотреть файл

@ -0,0 +1,19 @@
# -*- 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/.
EXPORTS.mozilla.dom += [
'Worklet.h'
]
UNIFIED_SOURCES += [
'Worklet.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
FINAL_LIBRARY = 'xul'

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

@ -0,0 +1,14 @@
function loadTest(file) {
var iframe = document.createElement('iframe');
iframe.src = file;
document.body.appendChild(iframe);
}
function setupTest() {
window.SimpleTest = parent.SimpleTest;
window.is = parent.is;
window.isnot = parent.isnot;
window.ok = parent.ok;
window.info = parent.info;
}

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

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Worklet</title>
<script type="application/javascript" src="common.js"></script>
</head>
<body>
<script type="application/javascript">
setupTest();
var worklet = window.createWorklet();
ok(!!worklet, "We have a Worklet");
worklet.import("common.js")
.then(() => {
ok(true, "Import should load a resource.");
})
.then(() => {
return worklet.import("404.js");
})
.then(() => {
ok(false, "The loading should fail.");
}, () => {
ok(true, "The loading should fail.");
}).then(() => {
SimpleTest.finish();
});
</script>
</body>
</html>

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

@ -0,0 +1,6 @@
[DEFAULT]
support-files =
common.js
file_basic.html
[test_basic.html]

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

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Worklet</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="common.js"></script>
</head>
<body>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{"set": [["dom.worklet.testing.enabled", true],
["dom.worklet.enabled", true]]},
function() { loadTest("file_basic.html"); });
</script>
</body>
</html>