Merge m-c to autoland. a=merge

This commit is contained in:
Ryan VanderMeulen 2017-03-29 09:43:00 -04:00
Родитель 70fc77dcd9 f4a0d77ffc
Коммит 7e1a57cfa4
205 изменённых файлов: 5630 добавлений и 2004 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1343682 - backing out a previous version didn't stop the failures from it, so it appears to need a clobber both out and in
Bug 1265818 - deleted an exported header and added a new .idl to regenerate that same header; and this unfortunately produces an untracked generated header in your source dir whenever you build (probably due to a dangling symlink), unless you clobber

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

@ -867,7 +867,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
continue;
}
ipcDoc = new DocAccessibleChild(childDoc);
ipcDoc = new DocAccessibleChild(childDoc, parentIPCDoc->Manager());
childDoc->SetIPCDoc(ipcDoc);
#if defined(XP_WIN)

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

@ -1482,7 +1482,7 @@ DocAccessible::DoInitialUpdate()
if (IPCAccessibilityActive()) {
nsIDocShell* docShell = mDocumentNode->GetDocShell();
if (RefPtr<dom::TabChild> tabChild = dom::TabChild::GetFrom(docShell)) {
DocAccessibleChild* ipcDoc = new DocAccessibleChild(this);
DocAccessibleChild* ipcDoc = new DocAccessibleChild(this, tabChild);
SetIPCDoc(ipcDoc);
#if defined(XP_WIN)

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

@ -26,10 +26,11 @@ class TableCellAccessible;
class DocAccessibleChild : public DocAccessibleChildBase
{
public:
explicit DocAccessibleChild(DocAccessible* aDoc)
DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager)
: DocAccessibleChildBase(aDoc)
{
MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
SetManager(aManager);
}
~DocAccessibleChild()

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

@ -16,7 +16,7 @@ namespace a11y {
static StaticAutoPtr<PlatformChild> sPlatformChild;
DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager)
: DocAccessibleChildBase(aDoc)
, mEmulatedWindowHandle(nullptr)
, mIsRemoteConstructed(false)
@ -26,6 +26,8 @@ DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
sPlatformChild = new PlatformChild();
ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown);
}
SetManager(aManager);
}
DocAccessibleChild::~DocAccessibleChild()

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

@ -22,7 +22,7 @@ namespace a11y {
class DocAccessibleChild : public DocAccessibleChildBase
{
public:
explicit DocAccessibleChild(DocAccessible* aDoc);
DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager);
~DocAccessibleChild();
virtual void Shutdown() override;

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

@ -361,8 +361,6 @@
@RESPATH@/components/PeerConnection.js
@RESPATH@/components/PeerConnection.manifest
#endif
@RESPATH@/components/SiteSpecificUserAgent.js
@RESPATH@/components/SiteSpecificUserAgent.manifest
@RESPATH@/components/storage-json.js
@RESPATH@/components/crypto-SDR.js
@RESPATH@/components/Downloads.manifest

11
browser/extensions/e10srollout/bootstrap.js поставляемый
Просмотреть файл

@ -18,7 +18,7 @@ const TEST_THRESHOLD = {
};
const ADDON_ROLLOUT_POLICY = {
"beta": "51alladdons", // Any WebExtension or addon except with mpc = false
"beta": "50allmpc",
"release": "50allmpc",
"esr": "esrA", // WebExtensions and Addons with mpc=true
};
@ -84,7 +84,8 @@ function defineCohort() {
let userOptedOut = optedOut();
let userOptedIn = optedIn();
let disqualified = (Services.appinfo.multiprocessBlockPolicy != 0);
let testGroup = (getUserSample() < TEST_THRESHOLD[updateChannel]);
let testThreshold = TEST_THRESHOLD[updateChannel];
let testGroup = (getUserSample() < testThreshold);
let hasNonExemptAddon = Preferences.get(PREF_E10S_HAS_NONEXEMPT_ADDON, false);
let temporaryDisqualification = getTemporaryDisqualification();
let temporaryQualification = getTemporaryQualification();
@ -111,7 +112,11 @@ function defineCohort() {
// here will be accumulated as "2 - Disabled", which is fine too.
setCohort(`temp-disqualified-${temporaryDisqualification}`);
Preferences.reset(PREF_TOGGLE_E10S);
} else if (!disqualified && temporaryQualification != "") {
} else if (!disqualified && testThreshold < 1.0 &&
temporaryQualification != "") {
// Users who are qualified for e10s and on channels where some population
// would not receive e10s can be pushed into e10s anyway via a temporary
// qualification which overrides the user sample value when non-empty.
setCohort(`temp-qualified-${temporaryQualification}`);
Preferences.set(PREF_TOGGLE_E10S, true);
} else if (testGroup) {

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

@ -10,7 +10,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>e10srollout@mozilla.org</em:id>
<em:version>1.12</em:version>
<em:version>1.14</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

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

@ -387,8 +387,6 @@
@RESPATH@/components/BrowserPageThumbs.manifest
@RESPATH@/components/crashmonitor.manifest
@RESPATH@/components/nsCrashMonitor.js
@RESPATH@/components/SiteSpecificUserAgent.js
@RESPATH@/components/SiteSpecificUserAgent.manifest
@RESPATH@/components/toolkitsearch.manifest
@RESPATH@/components/nsSearchService.js
@RESPATH@/components/nsSearchSuggestions.js

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

@ -119,6 +119,7 @@ MACH_MODULES = [
'python/mozbuild/mozbuild/frontend/mach_commands.py',
'services/common/tests/mach_commands.py',
'taskcluster/mach_commands.py',
'testing/awsy/mach_commands.py',
'testing/firefox-ui/mach_commands.py',
'testing/mach_commands.py',
'testing/marionette/mach_commands.py',

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

@ -52,7 +52,7 @@ function createSpan(doc) {
span.style.display = "inline-block";
span.style.width = "100px";
span.style.border = "1px solid red";
span.style.fontFamily = "monospace";
span.style.fontFamily = "Courier New";
div.style.height = "100%";
div.style.position = "absolute";

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

@ -50,7 +50,6 @@
#include "mozilla/dom/WebAuthentication.h"
#include "mozilla/dom/workers/RuntimeService.h"
#include "mozilla/Hal.h"
#include "nsISiteSpecificUserAgent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SSE.h"
#include "mozilla/StaticPtr.h"
@ -314,7 +313,6 @@ void
Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
ErrorResult& aRv) const
{
nsCOMPtr<nsIURI> codebaseURI;
nsCOMPtr<nsPIDOMWindowInner> window;
if (mWindow) {
@ -328,15 +326,10 @@ Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
aUserAgent = customUserAgent;
return;
}
nsIDocument* doc = mWindow->GetExtantDoc();
if (doc) {
doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
}
}
}
nsresult rv = GetUserAgent(window, codebaseURI,
nsresult rv = GetUserAgent(window,
aCallerType == CallerType::System,
aUserAgent);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -1885,7 +1878,7 @@ Navigator::ClearUserAgentCache()
}
nsresult
Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow,
bool aIsCallerChrome,
nsAString& aUserAgent)
{
@ -1916,19 +1909,30 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
CopyASCIItoUTF16(ua, aUserAgent);
if (!aWindow || !aURI) {
if (!aWindow) {
return NS_OK;
}
MOZ_ASSERT(aWindow->GetDocShell());
nsCOMPtr<nsISiteSpecificUserAgent> siteSpecificUA =
do_GetService("@mozilla.org/dom/site-specific-user-agent;1");
if (!siteSpecificUA) {
// Copy the User-Agent header from the document channel which has already been
// subject to UA overrides.
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
if (!doc) {
return NS_OK;
}
return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent);
nsCOMPtr<nsIHttpChannel> httpChannel =
do_QueryInterface(doc->GetChannel());
if (httpChannel) {
nsAutoCString userAgent;
rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("User-Agent"),
userAgent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
CopyASCIItoUTF16(userAgent, aUserAgent);
}
return NS_OK;
}
static nsCString

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

@ -158,7 +158,6 @@ public:
bool aUsePrefOverriddenValue);
static nsresult GetUserAgent(nsPIDOMWindowInner* aWindow,
nsIURI* aURI,
bool aIsCallerChrome,
nsAString& aUserAgent);

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

@ -1,88 +0,0 @@
/* 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/. */
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const MAX_CACHE_SIZE = 250;
const PREF_UPDATE = "general.useragent.updates.";
const PREF_OVERRIDE = "general.useragent.override.";
const XPCOM_SHUTDOWN = "xpcom-shutdown";
const HTTP_PROTO_HANDLER = Cc["@mozilla.org/network/protocol;1?name=http"]
.getService(Ci.nsIHttpProtocolHandler);
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
function SiteSpecificUserAgent() {
this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
if (this.inParent) {
Cu.import("resource://gre/modules/UserAgentOverrides.jsm");
} else {
Cu.import("resource://gre/modules/Services.jsm");
Services.prefs.addObserver(PREF_OVERRIDE, this, false);
Services.prefs.addObserver(PREF_UPDATE, this, false);
Services.obs.addObserver(this, XPCOM_SHUTDOWN, false);
this.userAgentCache = new Map;
}
}
SiteSpecificUserAgent.prototype = {
getUserAgentForURIAndWindow: function ssua_getUserAgentForURIAndWindow(aURI, aWindow) {
if (this.inParent) {
return UserAgentOverrides.getOverrideForURI(aURI) || HTTP_PROTO_HANDLER.userAgent;
}
let host = aURI.asciiHost;
let cachedResult = this.userAgentCache.get(host);
if (cachedResult) {
return cachedResult;
}
let data = { uri: aURI.spec };
let result = cpmm.sendRpcMessage("Useragent:GetOverride", data)[0] || HTTP_PROTO_HANDLER.userAgent;
if (this.userAgentCache.size >= MAX_CACHE_SIZE) {
this.userAgentCache.clear();
}
this.userAgentCache.set(host, result);
return result;
},
invalidateCache: function() {
this.userAgentCache.clear();
},
clean: function() {
this.userAgentCache.clear();
if (!this.inParent) {
Services.obs.removeObserver(this, XPCOM_SHUTDOWN);
Services.prefs.removeObserver(PREF_OVERRIDE, this);
Services.prefs.removeObserver(PREF_UPDATE, this);
}
},
observe: function(subject, topic, data) {
switch (topic) {
case "nsPref:changed":
this.invalidateCache();
break;
case XPCOM_SHUTDOWN:
this.clean();
break;
}
},
classID: Components.ID("{506c680f-3d1c-4954-b351-2c80afbc37d3}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsISiteSpecificUserAgent])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SiteSpecificUserAgent]);

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

@ -1,2 +0,0 @@
component {506c680f-3d1c-4954-b351-2c80afbc37d3} SiteSpecificUserAgent.js
contract @mozilla.org/dom/site-specific-user-agent;1 {506c680f-3d1c-4954-b351-2c80afbc37d3}

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

@ -308,6 +308,7 @@ StructuredCloneHolder::Read(nsISupports* aParent,
// If we are tranferring something, we cannot call 'Read()' more than once.
if (mSupportsTransferring) {
mBlobImplArray.Clear();
mWasmModuleArray.Clear();
mClonedSurfaces.Clear();
Clear();
}

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

@ -34,7 +34,6 @@ XPIDL_SOURCES += [
'nsISelectionListener.idl',
'nsISelectionPrivate.idl',
'nsISimpleContentPolicy.idl',
'nsISiteSpecificUserAgent.idl',
'nsISlowScriptDebug.idl',
]
@ -418,13 +417,6 @@ EXTRA_COMPONENTS += [
'SlowScriptDebug.manifest',
]
# Firefox for Android provides an alternate version of this component
if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
EXTRA_COMPONENTS += [
'SiteSpecificUserAgent.js',
'SiteSpecificUserAgent.manifest',
]
EXTRA_JS_MODULES += [
'DOMRequestHelper.jsm',
'IndexedDBHelper.jsm',

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

@ -1,28 +0,0 @@
/* 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"
interface nsIURI;
interface mozIDOMWindow;
/**
* nsISiteSpecificUserAgent provides you with site/window-specific User Agent strings.
*/
[scriptable, uuid(0f0ace30-9ab1-4175-9d60-fd26c0324adc)]
interface nsISiteSpecificUserAgent : nsISupports
{
/**
* Get the User Agent string for a given URI.
*
* @param aURI is the URI of the page the UA string is used for.
*
* @param aWindow is the window this UA is being requested for
*
* @returns the User Agent string for the given URI. If no override applies,
* the default User Agent string is used.
*/
AString getUserAgentForURIAndWindow(in nsIURI aURI, in mozIDOMWindow aWindow);
};

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

@ -9,7 +9,7 @@
</head>
<body>
<p id="display"></p>
<div id="scrollable" style="font-family:monospace; font-size: 18px; line-height: 1; overflow: auto; width: 200px; height: 200px;">
<div id="scrollable" style="font-family:'Courier New'; font-size: 18px; line-height: 1; overflow: auto; width: 200px; height: 200px;">
<div id="scrolled" style="font-size: 64px; width: 5000px; height: 5000px;">
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
@ -44,6 +44,7 @@
</div>
<pre id="test">
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests, window);

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

@ -7,71 +7,27 @@
#include "MemoryBlobImpl.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/SHA1.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsPrintfCString.h"
namespace mozilla {
namespace dom {
// XXXkhuey the input stream that we pass out of a File
// can outlive the actual File object. Thus, we must
// ensure that the buffer underlying the stream we get
// from NS_NewByteInputStream is held alive as long as the
// stream is. We do that by passing back this class instead.
class DataOwnerAdapter final : public nsIInputStream,
public nsISeekableStream,
public nsIIPCSerializableInputStream
{
typedef MemoryBlobImpl::DataOwner DataOwner;
public:
static nsresult Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval);
NS_IMPL_ADDREF(MemoryBlobImpl::DataOwnerAdapter)
NS_IMPL_RELEASE(MemoryBlobImpl::DataOwnerAdapter)
NS_DECL_THREADSAFE_ISUPPORTS
// These are mandatory.
NS_FORWARD_NSIINPUTSTREAM(mStream->)
NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
// This is optional. We use a conditional QI to keep it from being called
// if the underlying stream doesn't support it.
NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
private:
~DataOwnerAdapter() {}
DataOwnerAdapter(DataOwner* aDataOwner,
nsIInputStream* aStream)
: mDataOwner(aDataOwner), mStream(aStream),
mSeekableStream(do_QueryInterface(aStream)),
mSerializableInputStream(do_QueryInterface(aStream))
{
MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
}
RefPtr<DataOwner> mDataOwner;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsISeekableStream> mSeekableStream;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
};
NS_IMPL_ADDREF(DataOwnerAdapter)
NS_IMPL_RELEASE(DataOwnerAdapter)
NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
NS_INTERFACE_MAP_BEGIN(MemoryBlobImpl::DataOwnerAdapter)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval)
nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval)
{
nsresult rv;
MOZ_ASSERT(aDataOwner, "Uh ...");
@ -85,7 +41,8 @@ nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
NS_ASSIGNMENT_DEPEND);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
NS_ADDREF(*_retval =
new MemoryBlobImpl::DataOwnerAdapter(aDataOwner, stream));
return NS_OK;
}
@ -110,7 +67,8 @@ MemoryBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
return;
}
aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
aRv = MemoryBlobImpl::DataOwnerAdapter::Create(mDataOwner, mStart, mLength,
aStream);
}
/* static */ StaticMutex

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

@ -11,7 +11,11 @@
#include "mozilla/LinkedList.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "nsICloneableInputStream.h"
#include "nsIInputStream.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIMemoryReporter.h"
#include "nsISeekableStream.h"
namespace mozilla {
namespace dom {
@ -94,6 +98,50 @@ public:
uint64_t mLength;
};
class DataOwnerAdapter final : public nsIInputStream
, public nsISeekableStream
, public nsIIPCSerializableInputStream
, public nsICloneableInputStream
{
typedef MemoryBlobImpl::DataOwner DataOwner;
public:
static nsresult Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval);
NS_DECL_THREADSAFE_ISUPPORTS
// These are mandatory.
NS_FORWARD_NSIINPUTSTREAM(mStream->)
NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
NS_FORWARD_NSICLONEABLEINPUTSTREAM(mCloneableInputStream->)
// This is optional. We use a conditional QI to keep it from being called
// if the underlying stream doesn't support it.
NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
private:
~DataOwnerAdapter() {}
DataOwnerAdapter(DataOwner* aDataOwner,
nsIInputStream* aStream)
: mDataOwner(aDataOwner)
, mStream(aStream)
, mSeekableStream(do_QueryInterface(aStream))
, mSerializableInputStream(do_QueryInterface(aStream))
, mCloneableInputStream(do_QueryInterface(aStream))
{
MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
}
RefPtr<DataOwner> mDataOwner;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsISeekableStream> mSeekableStream;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
nsCOMPtr<nsICloneableInputStream> mCloneableInputStream;
};
private:
// Create slice
MemoryBlobImpl(const MemoryBlobImpl* aOther, uint64_t aStart,

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

@ -25,6 +25,8 @@
#include "mozilla/dom/PBlobStreamChild.h"
#include "mozilla/dom/PBlobStreamParent.h"
#include "mozilla/dom/indexedDB/FileSnapshot.h"
#include "mozilla/dom/ipc/MemoryStreamChild.h"
#include "mozilla/dom/ipc/MemoryStreamParent.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/IPCStreamUtils.h"
@ -617,6 +619,108 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata final
}
};
template<class M>
PMemoryStreamChild*
SerializeInputStreamInChunks(nsIInputStream* aInputStream, uint64_t aLength,
M* aManager)
{
MOZ_ASSERT(aInputStream);
PMemoryStreamChild* child = aManager->SendPMemoryStreamConstructor(aLength);
MOZ_ASSERT(child);
const uint64_t kMaxChunk = 1024 * 1024;
while (aLength) {
FallibleTArray<uint8_t> buffer;
uint64_t size = XPCOM_MIN(aLength, kMaxChunk);
if (NS_WARN_IF(!buffer.SetLength(size, fallible))) {
return nullptr;
}
uint32_t read;
nsresult rv = aInputStream->Read(reinterpret_cast<char*>(buffer.Elements()),
size, &read);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
if (NS_WARN_IF(read == 0)) {
// We were not expecting a read==0 here.
return nullptr;
}
MOZ_ASSERT(read <= size);
aLength -= read;
if (NS_WARN_IF(!buffer.SetLength(read, fallible))) {
return nullptr;
}
child->SendAddChunk(buffer);
}
return child;
}
void
DeleteStreamMemoryFromBlobDataStream(BlobDataStream& aStream)
{
PMemoryStreamChild* actor = aStream.streamChild();
if (actor) {
actor->Send__delete__(actor);
}
}
void
DeleteStreamMemoryFromBlobData(BlobData& aBlobData)
{
switch (aBlobData.type()) {
case BlobData::TBlobDataStream:
DeleteStreamMemoryFromBlobDataStream(aBlobData.get_BlobDataStream());
return;
case BlobData::TArrayOfBlobData: {
nsTArray<BlobData>& arrayBlobData = aBlobData.get_ArrayOfBlobData();
for (uint32_t i = 0; i < arrayBlobData.Length(); ++i) {
DeleteStreamMemoryFromBlobData(arrayBlobData[i]);
}
return;
}
default:
// Nothing to do here.
return;
}
}
void
DeleteStreamMemoryFromOptionalBlobData(OptionalBlobData& aParams)
{
if (aParams.type() == OptionalBlobData::Tvoid_t) {
return;
}
DeleteStreamMemoryFromBlobData(aParams.get_BlobData());
}
void
DeleteStreamMemory(AnyBlobConstructorParams& aParams)
{
if (aParams.type() == AnyBlobConstructorParams::TFileBlobConstructorParams) {
FileBlobConstructorParams& fileParams = aParams.get_FileBlobConstructorParams();
DeleteStreamMemoryFromOptionalBlobData(fileParams.optionalBlobData());
return;
}
if (aParams.type() == AnyBlobConstructorParams::TNormalBlobConstructorParams) {
NormalBlobConstructorParams& normalParams = aParams.get_NormalBlobConstructorParams();
DeleteStreamMemoryFromOptionalBlobData(normalParams.optionalBlobData());
return;
}
}
} // namespace
already_AddRefed<BlobImpl>
@ -645,7 +749,11 @@ CreateBlobImpl(const BlobDataStream& aStream,
{
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
nsCOMPtr<nsIInputStream> inputStream = DeserializeIPCStream(aStream.stream());
MemoryStreamParent* actor =
static_cast<MemoryStreamParent*>(aStream.streamParent());
nsCOMPtr<nsIInputStream> inputStream;
actor->GetStream(getter_AddRefs(inputStream));
if (!inputStream) {
ASSERT_UNLESS_FUZZING();
return nullptr;
@ -837,10 +945,9 @@ CreateBlobImpl(const ParentBlobConstructorParams& aParams,
}
template <class ChildManagerType>
void
bool
BlobDataFromBlobImpl(ChildManagerType* aManager, BlobImpl* aBlobImpl,
BlobData& aBlobData,
nsTArray<UniquePtr<AutoIPCStream>>& aIPCStreams)
BlobData& aBlobData)
{
MOZ_ASSERT(gProcessType != GeckoProcessType_Default);
MOZ_ASSERT(aBlobImpl);
@ -858,11 +965,13 @@ BlobDataFromBlobImpl(ChildManagerType* aManager, BlobImpl* aBlobImpl,
for (uint32_t count = subBlobs->Length(), index = 0;
index < count;
index++) {
BlobDataFromBlobImpl(aManager, subBlobs->ElementAt(index),
subBlobDatas[index], aIPCStreams);
if (!BlobDataFromBlobImpl(aManager, subBlobs->ElementAt(index),
subBlobDatas[index])) {
return false;
}
}
return;
return true;
}
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlobImpl);
@ -871,7 +980,7 @@ BlobDataFromBlobImpl(ChildManagerType* aManager, BlobImpl* aBlobImpl,
MOZ_ASSERT(actor);
aBlobData = actor->ParentID();
return;
return true;
}
ErrorResult rv;
@ -882,11 +991,14 @@ BlobDataFromBlobImpl(ChildManagerType* aManager, BlobImpl* aBlobImpl,
aBlobImpl->GetInternalStream(getter_AddRefs(inputStream), rv);
MOZ_ALWAYS_TRUE(!rv.Failed());
UniquePtr<AutoIPCStream> autoStream(new AutoIPCStream());
autoStream->Serialize(inputStream, aManager);
aBlobData = BlobDataStream(autoStream->TakeValue(), length);
PMemoryStreamChild* streamActor =
SerializeInputStreamInChunks(inputStream, length, aManager);
if (!streamActor) {
return false;
}
aIPCStreams.AppendElement(Move(autoStream));
aBlobData = BlobDataStream(nullptr, streamActor, length);
return true;
}
RemoteInputStream::RemoteInputStream(BlobImpl* aBlobImpl,
@ -3477,7 +3589,6 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
MOZ_ASSERT(!aBlobImpl->IsDateUnknown());
AnyBlobConstructorParams blobParams;
nsTArray<UniquePtr<AutoIPCStream>> autoIPCStreams;
if (gProcessType == GeckoProcessType_Default) {
RefPtr<BlobImpl> sameProcessImpl = aBlobImpl;
@ -3489,7 +3600,9 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
// BlobData is going to be populate here and it _must_ be send via IPC in
// order to avoid leaks.
BlobData blobData;
BlobDataFromBlobImpl(aManager, aBlobImpl, blobData, autoIPCStreams);
if (NS_WARN_IF(!BlobDataFromBlobImpl(aManager, aBlobImpl, blobData))) {
return nullptr;
}
nsString contentType;
aBlobImpl->GetType(contentType);
@ -3524,7 +3637,8 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
return nullptr;
}
autoIPCStreams.Clear();
DeleteStreamMemory(params.blobParams());
return actor;
}

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

@ -0,0 +1,22 @@
/* -*- 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_ipc_MemoryStreamChild_h
#define mozilla_dom_ipc_MemoryStreamChild_h
#include "mozilla/ipc/PMemoryStreamChild.h"
namespace mozilla {
namespace dom {
class MemoryStreamChild final : public mozilla::ipc::PMemoryStreamChild
{
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ipc_MemoryStreamChild_h

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

@ -0,0 +1,78 @@
/* -*- 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 "MemoryStreamParent.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace dom {
MemoryStreamParent::MemoryStreamParent(uint64_t aSize)
: mSize(aSize)
, mCurSize(0)
{}
mozilla::ipc::IPCResult
MemoryStreamParent::RecvAddChunk(nsTArray<unsigned char>&& aData)
{
MOZ_ASSERT(mSize);
uint64_t dataLength = aData.Length();
if (!dataLength || mSize < (mCurSize + dataLength)) {
return IPC_FAIL_NO_REASON(this);
}
void* buffer = malloc(dataLength);
if (NS_WARN_IF(!buffer)) {
return IPC_FAIL_NO_REASON(this);
}
memcpy(buffer, aData.Elements(), dataLength);
mData.AppendElement(new MemoryBlobImpl::DataOwner(buffer, dataLength));
mCurSize += dataLength;
return IPC_OK();
}
void
MemoryStreamParent::ActorDestroy(IProtocol::ActorDestroyReason)
{
}
void
MemoryStreamParent::GetStream(nsIInputStream** aInputStream)
{
if (mCurSize != mSize) {
*aInputStream = nullptr;
return;
}
nsCOMPtr<nsIMultiplexInputStream> stream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
if (NS_WARN_IF(!stream)) {
*aInputStream = nullptr;
return;
}
for (uint32_t i = 0; i < mData.Length(); ++i) {
nsCOMPtr<nsIInputStream> dataStream;
nsresult rv =
MemoryBlobImpl::DataOwnerAdapter::Create(mData[i], 0, mData[i]->mLength,
getter_AddRefs(dataStream));
if (NS_WARN_IF(NS_FAILED(rv))) {
*aInputStream = nullptr;
return;
}
stream->AppendStream(dataStream);
}
stream.forget(aInputStream);
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,40 @@
/* -*- 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_ipc_MemoryStreamParent_h
#define mozilla_dom_ipc_MemoryStreamParent_h
#include "mozilla/ipc/PMemoryStreamParent.h"
#include "mozilla/dom/MemoryBlobImpl.h"
namespace mozilla {
namespace dom {
class MemoryStreamParent final : public mozilla::ipc::PMemoryStreamParent
{
public:
explicit MemoryStreamParent(uint64_t aSize);
mozilla::ipc::IPCResult
RecvAddChunk(nsTArray<unsigned char>&& aData) override;
void
ActorDestroy(IProtocol::ActorDestroyReason) override;
void
GetStream(nsIInputStream** aInputStream);
private:
uint64_t mSize;
uint64_t mCurSize;
nsTArray<RefPtr<MemoryBlobImpl::DataOwner>> mData;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ipc_MemoryStreamParent_h

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

@ -9,6 +9,7 @@ include protocol PContentBridge;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol PMemoryStream;
include BlobTypes;
include DOMTypes;

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

@ -0,0 +1,23 @@
/* 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 protocol PBackground;
include protocol PContent;
include protocol PContentBridge;
namespace mozilla {
namespace ipc {
protocol PMemoryStream
{
manager PBackground or PContent or PContentBridge;
parent:
async AddChunk(uint8_t[] data);
async __delete__();
};
} // namespace dom
} // namespace mozilla

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

@ -7,17 +7,21 @@
EXPORTS.mozilla.dom.ipc += [
'BlobChild.h',
'BlobParent.h',
'MemoryStreamChild.h',
'MemoryStreamParent.h',
'nsIRemoteBlob.h',
]
UNIFIED_SOURCES += [
'Blob.cpp',
'MemoryStreamParent.cpp',
]
IPDL_SOURCES += [
'BlobTypes.ipdlh',
'PBlob.ipdl',
'PBlobStream.ipdl',
'PMemoryStream.ipdl',
]
LOCAL_INCLUDES += [

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

@ -68,6 +68,12 @@ ContentBridgeChild::SendPBlobConstructor(PBlobChild* actor,
return PContentBridgeChild::SendPBlobConstructor(actor, params);
}
PMemoryStreamChild*
ContentBridgeChild::SendPMemoryStreamConstructor(const uint64_t& aSize)
{
return PContentBridgeChild::SendPMemoryStreamConstructor(aSize);
}
bool
ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
@ -168,6 +174,18 @@ ContentBridgeChild::DeallocPBlobChild(PBlobChild* aActor)
return nsIContentChild::DeallocPBlobChild(aActor);
}
PMemoryStreamChild*
ContentBridgeChild::AllocPMemoryStreamChild(const uint64_t& aSize)
{
return nsIContentChild::AllocPMemoryStreamChild(aSize);
}
bool
ContentBridgeChild::DeallocPMemoryStreamChild(PMemoryStreamChild* aActor)
{
return nsIContentChild::DeallocPMemoryStreamChild(aActor);
}
PChildToParentStreamChild*
ContentBridgeChild::AllocPChildToParentStreamChild()
{

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

@ -36,6 +36,9 @@ public:
SendPBlobConstructor(PBlobChild* actor,
const BlobConstructorParams& aParams) override;
virtual PMemoryStreamChild*
SendPMemoryStreamConstructor(const uint64_t& aSize) override;
jsipc::CPOWManager* GetCPOWManager() override;
virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
@ -82,6 +85,10 @@ protected:
virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams) override;
virtual bool DeallocPBlobChild(PBlobChild*) override;
virtual PMemoryStreamChild*
AllocPMemoryStreamChild(const uint64_t& aSize) override;
virtual bool DeallocPMemoryStreamChild(PMemoryStreamChild*) override;
virtual mozilla::ipc::PChildToParentStreamChild*
AllocPChildToParentStreamChild() override;

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

@ -7,6 +7,7 @@
#include "mozilla/dom/ContentBridgeParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/dom/ipc/MemoryStreamParent.h"
#include "nsXULAppAPI.h"
#include "nsIObserverService.h"
#include "base/task.h"
@ -128,6 +129,18 @@ ContentBridgeParent::DeallocPBlobParent(PBlobParent* aActor)
return nsIContentParent::DeallocPBlobParent(aActor);
}
PMemoryStreamParent*
ContentBridgeParent::AllocPMemoryStreamParent(const uint64_t& aSize)
{
return nsIContentParent::AllocPMemoryStreamParent(aSize);
}
bool
ContentBridgeParent::DeallocPMemoryStreamParent(PMemoryStreamParent* aActor)
{
return nsIContentParent::DeallocPMemoryStreamParent(aActor);
}
mozilla::jsipc::PJavaScriptParent *
ContentBridgeParent::AllocPJavaScriptParent()
{

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

@ -136,6 +136,11 @@ protected:
virtual bool DeallocPBlobParent(PBlobParent*) override;
virtual PMemoryStreamParent*
AllocPMemoryStreamParent(const uint64_t& aSize) override;
virtual bool DeallocPMemoryStreamParent(PMemoryStreamParent*) override;
virtual PChildToParentStreamParent* AllocPChildToParentStreamParent() override;
virtual bool

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

@ -1524,6 +1524,18 @@ ContentChild::DeallocPBrowserChild(PBrowserChild* aIframe)
return nsIContentChild::DeallocPBrowserChild(aIframe);
}
PMemoryStreamChild*
ContentChild::AllocPMemoryStreamChild(const uint64_t& aSize)
{
return nsIContentChild::AllocPMemoryStreamChild(aSize);
}
bool
ContentChild::DeallocPMemoryStreamChild(PMemoryStreamChild* aActor)
{
return nsIContentChild::DeallocPMemoryStreamChild(aActor);
}
PBlobChild*
ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
{
@ -1561,6 +1573,16 @@ ContentChild::SendPBlobConstructor(PBlobChild* aActor,
return PContentChild::SendPBlobConstructor(aActor, aParams);
}
PMemoryStreamChild*
ContentChild::SendPMemoryStreamConstructor(const uint64_t& aSize)
{
if (IsShuttingDown()) {
return nullptr;
}
return PContentChild::SendPMemoryStreamConstructor(aSize);
}
PPresentationChild*
ContentChild::AllocPPresentationChild()
{

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

@ -182,6 +182,12 @@ public:
virtual bool DeallocPBlobChild(PBlobChild* aActor) override;
virtual PMemoryStreamChild*
AllocPMemoryStreamChild(const uint64_t& aSize) override;
virtual bool
DeallocPMemoryStreamChild(PMemoryStreamChild* aActor) override;
virtual PHalChild* AllocPHalChild() override;
virtual bool DeallocPHalChild(PHalChild*) override;
@ -489,6 +495,9 @@ public:
SendPBlobConstructor(PBlobChild* actor,
const BlobConstructorParams& params) override;
virtual PMemoryStreamChild*
SendPMemoryStreamConstructor(const uint64_t& aSize) override;
virtual PFileDescriptorSetChild*
SendPFileDescriptorSetConstructor(const FileDescriptor&) override;

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

@ -2820,6 +2820,18 @@ ContentParent::DeallocPBlobParent(PBlobParent* aActor)
return nsIContentParent::DeallocPBlobParent(aActor);
}
PMemoryStreamParent*
ContentParent::AllocPMemoryStreamParent(const uint64_t& aSize)
{
return nsIContentParent::AllocPMemoryStreamParent(aSize);
}
bool
ContentParent::DeallocPMemoryStreamParent(PMemoryStreamParent* aActor)
{
return nsIContentParent::DeallocPMemoryStreamParent(aActor);
}
mozilla::ipc::IPCResult
ContentParent::RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& aParams)

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

@ -825,6 +825,11 @@ private:
virtual bool DeallocPBlobParent(PBlobParent* aActor) override;
virtual PMemoryStreamParent*
AllocPMemoryStreamParent(const uint64_t& aSize) override;
virtual bool DeallocPMemoryStreamParent(PMemoryStreamParent* aActor) override;
virtual mozilla::ipc::IPCResult
RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& params) override;

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

@ -5,9 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include IPCStream;
include protocol PMemoryStream;
include ProtocolTypes;
using struct mozilla::void_t
@ -47,7 +45,7 @@ struct ClonedMessageData
struct BlobDataStream
{
IPCStream stream;
PMemoryStream stream;
uint64_t length;
};

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

@ -20,6 +20,7 @@ include protocol PHeapSnapshotTempFileHelper;
include protocol PProcessHangMonitor;
include protocol PImageBridge;
include protocol PMedia;
include protocol PMemoryStream;
include protocol PNecko;
include protocol PGMPContent;
include protocol PGMPService;
@ -283,6 +284,7 @@ nested(upto inside_cpow) sync protocol PContent
manages PHandlerService;
manages PHeapSnapshotTempFileHelper;
manages PMedia;
manages PMemoryStream;
manages PNecko;
manages POfflineCacheUpdate;
manages PPrinting;
@ -647,6 +649,8 @@ parent:
async PRemoteSpellcheckEngine();
async PMemoryStream(uint64_t aSize);
async InitCrashReporter(Shmem shmem, NativeThreadId tid);
/**

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

@ -10,6 +10,7 @@ include protocol PContent;
include protocol PJavaScript;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PMemoryStream;
include protocol PParentToChildStream;
include DOMTypes;
@ -40,6 +41,7 @@ nested(upto inside_cpow) sync protocol PContentBridge
manages PFileDescriptorSet;
manages PJavaScript;
manages PChildToParentStream;
manages PMemoryStream;
manages PParentToChildStream;
child:
@ -64,6 +66,8 @@ parent:
async PChildToParentStream();
async PMemoryStream(uint64_t aSize);
both:
// Both the parent and the child can construct the PBrowser.
// See the comment in PContent::PBrowser().

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

@ -20,6 +20,7 @@
#include "mozilla/ipc/IPCStreamSource.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/dom/ipc/MemoryStreamChild.h"
#include "nsPrintfCString.h"
#include "xpcpublic.h"
@ -102,6 +103,19 @@ nsIContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
return IPC_OK();
}
PMemoryStreamChild*
nsIContentChild::AllocPMemoryStreamChild(const uint64_t& aSize)
{
return new MemoryStreamChild();
}
bool
nsIContentChild::DeallocPMemoryStreamChild(PMemoryStreamChild* aActor)
{
delete aActor;
return true;
}
PBlobChild*
nsIContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
{

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

@ -64,6 +64,9 @@ public:
SendPBlobConstructor(PBlobChild* aActor,
const BlobConstructorParams& aParams) = 0;
virtual mozilla::ipc::PMemoryStreamChild*
SendPMemoryStreamConstructor(const uint64_t& aSize) = 0;
virtual bool
SendPBrowserConstructor(PBrowserChild* aActor,
const TabId& aTabId,
@ -100,6 +103,11 @@ protected:
virtual bool DeallocPBlobChild(PBlobChild* aActor);
virtual mozilla::ipc::PMemoryStreamChild*
AllocPMemoryStreamChild(const uint64_t& aSize);
virtual bool DeallocPMemoryStreamChild(mozilla::ipc::PMemoryStreamChild* aActor);
virtual mozilla::ipc::PChildToParentStreamChild* AllocPChildToParentStreamChild();
virtual bool

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

@ -14,6 +14,7 @@
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/dom/ipc/MemoryStreamParent.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
@ -187,6 +188,19 @@ nsIContentParent::DeallocPBlobParent(PBlobParent* aActor)
return true;
}
PMemoryStreamParent*
nsIContentParent::AllocPMemoryStreamParent(const uint64_t& aSize)
{
return new MemoryStreamParent(aSize);
}
bool
nsIContentParent::DeallocPMemoryStreamParent(PMemoryStreamParent* aActor)
{
delete aActor;
return true;
}
BlobParent*
nsIContentParent::GetOrCreateActorForBlob(Blob* aBlob)
{

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

@ -36,6 +36,7 @@ namespace ipc {
class PFileDescriptorSetParent;
class PChildToParentStreamParent;
class PParentToChildStreamParent;
class PMemoryStreamParent;
}
namespace dom {
@ -121,6 +122,11 @@ protected: // IPDL methods
virtual bool DeallocPBlobParent(PBlobParent* aActor);
virtual mozilla::ipc::PMemoryStreamParent*
AllocPMemoryStreamParent(const uint64_t& aSize);
virtual bool DeallocPMemoryStreamParent(mozilla::ipc::PMemoryStreamParent* aActor);
virtual mozilla::ipc::PFileDescriptorSetParent*
AllocPFileDescriptorSetParent(const mozilla::ipc::FileDescriptor& aFD);

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

@ -20,7 +20,7 @@
left: 0em;
top: 0em;
font-size: 10pt;
font-family: monospace;
font-family: 'Courier New';
line-height: 20px;
letter-spacing: 0px;
margin-top:-1px; /* nix the text area border */

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

@ -5,7 +5,9 @@
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript">
<script>
"use strict";
var SimpleTest = window.opener.SimpleTest;
var Ci = Components.interfaces;
@ -127,13 +129,7 @@
targetPoint = { xPos: rect.left + ((charDims.width * 4) + (charDims.width / 2)),
yPos: rect.top + (charDims.height / 2) };
setEnd(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
if (isLinux || isMac) {
// XXX I think this is a bug, the right hand selection is 4.5 characters over with a
// monspaced font. what we want: t(te)s(ts)election1 what we get: t(te)st(se)lection1
checkSelection(document, "split selection", "tese");
} else if (isWindows) {
checkSelection(document, "split selection", "tets");
}
// Trying to select where there's no text, should fail but not throw
let result = dwu.selectAtPoint(rect.left - 20, rect.top - 20, Ci.nsIDOMWindowUtils.SELECT_CHARACTER, false);
@ -228,7 +224,7 @@
<style type="text/css">
body {
font-family: monospace;
font-family: 'Courier New';
margin-left: 40px;
margin-top: 40px;
padding: 0;
@ -267,7 +263,7 @@ body {
<br />
<iframe id="frame1" src="data:text/html,<html><body style='margin: 0; padding: 0; font-family: monospace;' onload='window.parent.onFrameLoad();'><div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div><br/><br/></body></html>"></iframe>
<iframe id="frame1" src="data:text/html,<html><body style='margin: 0; padding: 0; font-family: \'Courier New\';' onload='window.parent.onFrameLoad();'><div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div><br/><br/></body></html>"></iframe>
<br/>

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

@ -1120,6 +1120,8 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStatus(
case NS_NET_STATUS_END_FTP_TRANSACTION:
case NS_NET_STATUS_CONNECTING_TO:
case NS_NET_STATUS_CONNECTED_TO:
case NS_NET_STATUS_TLS_HANDSHAKE_STARTING:
case NS_NET_STATUS_TLS_HANDSHAKE_ENDED:
case NS_NET_STATUS_SENDING_TO:
case NS_NET_STATUS_RECEIVING_FROM:
case NS_NET_STATUS_WAITING_FOR:

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

@ -138,17 +138,9 @@ public:
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindowInner> window = mWorkerPrivate->GetWindow();
nsCOMPtr<nsIURI> uri;
if (window && window->GetDocShell()) {
nsIDocument* doc = window->GetExtantDoc();
if (doc) {
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
}
}
bool isCallerChrome = mWorkerPrivate->UsesSystemPrincipal();
nsresult rv = dom::Navigator::GetUserAgent(window, uri,
isCallerChrome, mUA);
nsresult rv = dom::Navigator::GetUserAgent(window, isCallerChrome, mUA);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to retrieve user-agent from the worker thread.");
}

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

@ -1,6 +1,10 @@
let { classes: Cc, interfaces: Ci } = Components;
add_task(function* test() {
yield SpecialPowers.pushPrefEnv(
{set: [["browser.tabs.remote.separateFileUriProcess", true]]}
);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)

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

@ -485,6 +485,7 @@ private:
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram", FPSPrintHistogram, bool, false);
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
DECL_OVERRIDE_PREF(Live, "layers.advanced.background-image", LayersAllowBackgroundImage, false);
DECL_OVERRIDE_PREF(Live, "layers.advanced.border-layers", LayersAllowBorderLayers, false);
DECL_OVERRIDE_PREF(Live, "layers.advanced.boxshadow-inset-layers", LayersAllowInsetBoxShadow, gfxPrefs::OverrideBase_WebRender());
DECL_OVERRIDE_PREF(Live, "layers.advanced.boxshadow-outer-layers", LayersAllowOuterBoxShadow, false);

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

@ -162,6 +162,61 @@ static inline WrColor ToWrColor(const gfx::Color& color)
return c;
}
template<class T>
static inline WrPoint ToWrPoint(const gfx::PointTyped<T>& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
template<class T>
static inline WrPoint ToWrPoint(const gfx::IntPointTyped<T>& point)
{
return ToWrPoint(IntPointToPoint(point));
}
static inline WrPoint ToWrPoint(const gfx::Point& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
template<class T>
static inline WrRect ToWrRect(const gfx::RectTyped<T>& rect)
{
WrRect r;
r.x = rect.x;
r.y = rect.y;
r.width = rect.width;
r.height = rect.height;
return r;
}
template<class T>
static inline WrRect ToWrRect(const gfx::IntRectTyped<T>& rect)
{
return ToWrRect(IntRectToRect(rect));
}
template<class T>
static inline WrSize ToWrSize(const gfx::SizeTyped<T>& size)
{
WrSize ls;
ls.width = size.width;
ls.height = size.height;
return ls;
}
template<class T>
static inline WrSize ToWrSize(const gfx::IntSizeTyped<T>& size)
{
return ToWrSize(IntSizeToSize(size));
}
static inline WrBorderStyle ToWrBorderStyle(const uint8_t& style)
{
switch (style) {
@ -199,22 +254,6 @@ static inline WrBorderSide ToWrBorderSide(const gfx::Color& color, const uint8_t
return bs;
}
static inline WrPoint ToWrPoint(const LayerPoint point)
{
WrPoint lp;
lp.x = point.x;
lp.y = point.y;
return lp;
}
static inline WrSize ToWrSize(const LayerSize size)
{
WrSize ls;
ls.width = size.width;
ls.height = size.height;
return ls;
}
static inline WrBorderRadius ToWrUniformBorderRadius(const LayerSize& aSize)
{
WrBorderRadius br;
@ -294,23 +333,6 @@ static inline WrRepeatMode ToWrRepeatMode(uint8_t repeatMode)
return WrRepeatMode::Stretch;
}
template<class T>
static inline WrRect ToWrRect(const gfx::RectTyped<T>& rect)
{
WrRect r;
r.x = rect.x;
r.y = rect.y;
r.width = rect.width;
r.height = rect.height;
return r;
}
template<class T>
static inline WrRect ToWrRect(const gfx::IntRectTyped<T>& rect)
{
return ToWrRect(IntRectToRect(rect));
}
template<class T>
static inline WrComplexClipRegion ToWrComplexClipRegion(const gfx::RectTyped<T>& rect,
const LayerSize& size)
@ -321,14 +343,6 @@ static inline WrComplexClipRegion ToWrComplexClipRegion(const gfx::RectTyped<T>&
return complex_clip;
}
static inline WrPoint ToWrPoint(const gfx::Point& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
static inline WrExternalImageId ToWrExternalImageId(uint64_t aID)
{
WrExternalImageId id;

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

@ -449,14 +449,6 @@ RasterImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey)
bool animatedFramesDiscarded =
mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated;
if (animatedFramesDiscarded && NS_IsMainThread()) {
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
// We don't need OnSurfaceDiscardedInternal to handle the animated frames
// being discarded because we just did.
animatedFramesDiscarded = false;
}
RefPtr<RasterImage> image = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
"RasterImage::OnSurfaceDiscarded",

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

@ -23,6 +23,7 @@
#include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/MemoryStreamChild.h"
#include "mozilla/dom/quota/PQuotaChild.h"
#include "mozilla/dom/GamepadEventChannelChild.h"
#include "mozilla/dom/GamepadTestChannelChild.h"
@ -215,6 +216,19 @@ BackgroundChildImpl::DeallocPBlobChild(PBlobChild* aActor)
return true;
}
PMemoryStreamChild*
BackgroundChildImpl::AllocPMemoryStreamChild(const uint64_t& aSize)
{
return new mozilla::dom::MemoryStreamChild();
}
bool
BackgroundChildImpl::DeallocPMemoryStreamChild(PMemoryStreamChild* aActor)
{
delete aActor;
return true;
}
PFileDescriptorSetChild*
BackgroundChildImpl::AllocPFileDescriptorSetChild(
const FileDescriptor& aFileDescriptor)

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

@ -76,6 +76,12 @@ protected:
virtual bool
DeallocPBlobChild(PBlobChild* aActor) override;
virtual PMemoryStreamChild*
AllocPMemoryStreamChild(const uint64_t& aSize) override;
virtual bool
DeallocPMemoryStreamChild(PMemoryStreamChild* aActor) override;
virtual PFileDescriptorSetChild*
AllocPFileDescriptorSetChild(const FileDescriptor& aFileDescriptor)
override;

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

@ -28,6 +28,7 @@
#include "mozilla/dom/cache/ActorUtils.h"
#include "mozilla/dom/indexedDB/ActorsParent.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/dom/ipc/MemoryStreamParent.h"
#include "mozilla/dom/quota/ActorsParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
@ -266,6 +267,26 @@ BackgroundParentImpl::DeallocPBlobParent(PBlobParent* aActor)
return true;
}
PMemoryStreamParent*
BackgroundParentImpl::AllocPMemoryStreamParent(const uint64_t& aSize)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return new mozilla::dom::MemoryStreamParent(aSize);
}
bool
BackgroundParentImpl::DeallocPMemoryStreamParent(PMemoryStreamParent* aActor)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& aParams)

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

@ -69,6 +69,12 @@ protected:
virtual bool
DeallocPBlobParent(PBlobParent* aActor) override;
virtual PMemoryStreamParent*
AllocPMemoryStreamParent(const uint64_t& aSize) override;
virtual bool
DeallocPMemoryStreamParent(PMemoryStreamParent* aActor) override;
virtual mozilla::ipc::IPCResult
RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& params) override;

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

@ -15,6 +15,7 @@ include protocol PFileDescriptorSet;
include protocol PFileSystemRequest;
include protocol PGamepadEventChannel;
include protocol PGamepadTestChannel;
include protocol PMemoryStream;
include protocol PMessagePort;
include protocol PCameras;
include protocol PQuota;
@ -59,6 +60,7 @@ sync protocol PBackground
manages PFileSystemRequest;
manages PGamepadEventChannel;
manages PGamepadTestChannel;
manages PMemoryStream;
manages PMessagePort;
manages PCameras;
manages PQuota;
@ -110,6 +112,8 @@ parent:
async PGamepadTestChannel();
async PMemoryStream(uint64_t aSize);
child:
async PCache();
async PCacheStreamControl();

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

@ -852,7 +852,7 @@ struct JSClass {
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 41)
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 46)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \

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

@ -0,0 +1,7 @@
/* 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/. */
function AsyncIteratorIdentity() {
return this;
}

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

@ -12,10 +12,12 @@
#include "jscntxt.h"
#include "jsexn.h"
#include "jsiter.h"
#include "gc/Heap.h"
#include "js/Debug.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "jsobjinlines.h"
@ -36,6 +38,16 @@ enum PromiseHandler {
PromiseHandlerThrower,
PromiseHandlerAsyncFunctionAwaitFulfilled,
PromiseHandlerAsyncFunctionAwaitRejected,
PromiseHandlerAsyncGeneratorAwaitFulfilled,
PromiseHandlerAsyncGeneratorAwaitRejected,
// Async Iteration proposal 6.1.1.2.1.
// Async iterator handlers take the resolved value and create new iterator
// objects. To do so it needs to forward whether the iterator is done. In
// spec, this is achieved via the [[Done]] internal slot. We enumerate both
// true and false cases here.
PromiseHandlerAsyncIteratorValueUnwrapDone,
PromiseHandlerAsyncIteratorValueUnwrapNotDone,
};
enum ResolutionMode {
@ -178,6 +190,7 @@ enum ReactionRecordSlots {
ReactionRecordSlot_IncumbentGlobalObject,
ReactionRecordSlot_Flags,
ReactionRecordSlot_HandlerArg,
ReactionRecordSlot_Generator,
ReactionRecordSlots,
};
@ -185,6 +198,7 @@ enum ReactionRecordSlots {
#define REACTION_FLAG_FULFILLED 0x2
#define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
#define REACTION_FLAG_ASYNC_FUNCTION_AWAIT 0x8
#define REACTION_FLAG_ASYNC_GENERATOR_AWAIT 0x10
// ES2016, 25.4.1.2.
class PromiseReactionRecord : public NativeObject
@ -220,6 +234,22 @@ class PromiseReactionRecord : public NativeObject
int32_t flags = this->flags();
return flags & REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
}
void setIsAsyncGeneratorAwait(Handle<AsyncGeneratorObject*> asyncGenObj) {
int32_t flags = this->flags();
flags |= REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj));
}
bool isAsyncGeneratorAwait() {
int32_t flags = this->flags();
return flags & REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
}
AsyncGeneratorObject* asyncGenerator() {
MOZ_ASSERT(isAsyncGeneratorAwait());
return &getFixedSlot(ReactionRecordSlot_Generator).toObject()
.as<AsyncGeneratorObject>();
}
Value handler() {
MOZ_ASSERT(targetState() != JS::PromiseState::Pending);
uint32_t slot = targetState() == JS::PromiseState::Fulfilled
@ -844,6 +874,34 @@ AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord
return true;
}
static MOZ_MUST_USE bool
AsyncGeneratorAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
MutableHandleValue rval)
{
MOZ_ASSERT(reaction->isAsyncGeneratorAwait());
RootedValue handlerVal(cx, reaction->handler());
RootedValue argument(cx, reaction->handlerArg());
Rooted<AsyncGeneratorObject*> asyncGenObj(cx, reaction->asyncGenerator());
int32_t handlerNum = int32_t(handlerVal.toNumber());
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled ||
handlerNum == PromiseHandlerAsyncGeneratorAwaitRejected);
// Await's handlers don't return a value, nor throw exception.
// They fail only on OOM.
if (handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled) {
if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument))
return false;
} else {
if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument))
return false;
}
rval.setUndefined();
return true;
}
// ES2016, 25.4.2.1.
/**
* Callback triggering the fulfill/reject reaction for a resolved Promise,
@ -882,6 +940,8 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
if (reaction->isAsyncFunctionAwait())
return AsyncFunctionAwaitPromiseReactionJob(cx, reaction, args.rval());
if (reaction->isAsyncGeneratorAwait())
return AsyncGeneratorAwaitPromiseReactionJob(cx, reaction, args.rval());
// Step 3.
RootedValue handlerVal(cx, reaction->handler());
@ -898,11 +958,21 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
// Step 4.
if (handlerNum == PromiseHandlerIdentity) {
handlerResult = argument;
} else {
} else if (handlerNum == PromiseHandlerThrower) {
// Step 5.
MOZ_ASSERT(handlerNum == PromiseHandlerThrower);
resolutionMode = RejectMode;
handlerResult = argument;
} else {
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone ||
handlerNum == PromiseHandlerAsyncIteratorValueUnwrapNotDone);
bool done = handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone;
// Async Iteration proposal 6.1.1.2.1 step 1.
RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done));
if (!resultObj)
return false;
handlerResult = ObjectValue(*resultObj);
}
} else {
// Step 6.
@ -2191,6 +2261,344 @@ js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, Hand
return PerformPromiseThenWithReaction(cx, promise, reaction);
}
// Async Iteration proposal 5.1 steps 2-9.
MOZ_MUST_USE bool
js::AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value)
{
// Step 2.
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return false;
// Steps 3.
if (!ResolvePromiseInternal(cx, promise, value))
return false;
// Steps 4-5.
RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitFulfilled));
RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitRejected));
RootedObject incumbentGlobal(cx);
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
return false;
// Step 6 (skipped).
// Steps 7-8.
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, nullptr,
onFulfilled, onRejected,
nullptr, nullptr,
incumbentGlobal));
if (!reaction)
return false;
reaction->setIsAsyncGeneratorAwait(asyncGenObj);
// Step 9.
return PerformPromiseThenWithReaction(cx, promise, reaction);
}
// Async Iteration proposal 6.1.3.2.1 %AsyncFromSyncIteratorPrototype%.next
// Async Iteration proposal 6.1.3.2.2 %AsyncFromSyncIteratorPrototype%.return
// Async Iteration proposal 6.1.3.2.3 %AsyncFromSyncIteratorPrototype%.throw
bool
js::AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind)
{
// Step 1.
RootedValue thisVal(cx, args.thisv());
// Step 2.
RootedObject resultPromise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!resultPromise)
return false;
// Step 3.
if (!thisVal.isObject() || !thisVal.toObject().is<AsyncFromSyncIteratorObject>()) {
// Step 3.a.
RootedValue badGeneratorError(cx);
if (!GetTypeError(cx, JSMSG_NOT_AN_ASYNC_ITERATOR, &badGeneratorError))
return false;
// Step 3.b.
if (!RejectMaybeWrappedPromise(cx, resultPromise, badGeneratorError))
return false;
// Step 3.c.
args.rval().setObject(*resultPromise);
return true;
}
Rooted<AsyncFromSyncIteratorObject*> asyncIter(
cx, &thisVal.toObject().as<AsyncFromSyncIteratorObject>());
// Step 4.
RootedObject iter(cx, asyncIter->iterator());
RootedValue resultVal(cx);
RootedValue func(cx);
if (completionKind == CompletionKind::Normal) {
// 6.1.3.2.1 steps 5-6 (partially).
if (!GetProperty(cx, iter, iter, cx->names().next, &func))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
} else if (completionKind == CompletionKind::Return) {
// 6.1.3.2.2 steps 5-6.
if (!GetProperty(cx, iter, iter, cx->names().return_, &func))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// Step 7.
if (func.isNullOrUndefined()) {
// Step 7.a.
RootedObject resultObj(cx, CreateIterResultObject(cx, args.get(0), true));
if (!resultObj)
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
RootedValue resultVal(cx, ObjectValue(*resultObj));
// Step 7.b.
if (!ResolvePromiseInternal(cx, resultPromise, resultVal))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// Step 7.c.
args.rval().setObject(*resultPromise);
return true;
}
} else {
// 6.1.3.2.3 steps 5-6.
MOZ_ASSERT(completionKind == CompletionKind::Throw);
if (!GetProperty(cx, iter, iter, cx->names().throw_, &func))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// Step 7.
if (func.isNullOrUndefined()) {
// Step 7.a.
if (!RejectMaybeWrappedPromise(cx, resultPromise, args.get(0)))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// Step 7.b.
args.rval().setObject(*resultPromise);
return true;
}
}
// 6.1.3.2.1 steps 5-6 (partially).
// 6.1.3.2.2, 6.1.3.2.3 steps 8-9.
RootedValue iterVal(cx, ObjectValue(*iter));
FixedInvokeArgs<1> args2(cx);
args2[0].set(args.get(0));
if (!js::Call(cx, func, iterVal, args2, &resultVal))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// 6.1.3.2.1 steps 5-6 (partially).
// 6.1.3.2.2, 6.1.3.2.3 steps 10.
if (!resultVal.isObject()) {
CheckIsObjectKind kind;
switch (completionKind) {
case CompletionKind::Normal:
kind = CheckIsObjectKind::IteratorNext;
break;
case CompletionKind::Throw:
kind = CheckIsObjectKind::IteratorThrow;
break;
case CompletionKind::Return:
kind = CheckIsObjectKind::IteratorReturn;
break;
}
MOZ_ALWAYS_FALSE(ThrowCheckIsObject(cx, kind));
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
}
RootedObject resultObj(cx, &resultVal.toObject());
// Following step numbers are for 6.1.3.2.1.
// For 6.1.3.2.2 and 6.1.3.2.3, steps 7-16 corresponds to steps 11-20.
// Steps 7-8.
RootedValue value(cx);
if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
// Steps 9-10.
RootedValue doneVal(cx);
if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal))
return AbruptRejectPromise(cx, args, resultPromise, nullptr);
bool done = ToBoolean(doneVal);
// Step 11.
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return false;
// Step 12.
if (!ResolvePromiseInternal(cx, promise, value))
return false;
// Steps 13-14.
RootedValue onFulfilled(cx, Int32Value(done
? PromiseHandlerAsyncIteratorValueUnwrapDone
: PromiseHandlerAsyncIteratorValueUnwrapNotDone));
RootedObject incumbentGlobal(cx);
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
return false;
// Step 15.
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise, onFulfilled,
UndefinedHandleValue,
nullptr, nullptr,
incumbentGlobal));
if (!reaction)
return false;
if (!PerformPromiseThenWithReaction(cx, promise, reaction))
return false;
// Step 16.
args.rval().setObject(*resultPromise);
return true;
}
// Async Iteration proposal 6.4.3.3.
MOZ_MUST_USE bool
js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value, bool done)
{
// Step 1 (implicit).
// Steps 2-3.
MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
// Step 4.
Rooted<AsyncGeneratorRequest*> request(
cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
if (!request)
return false;
// Step 5.
RootedObject resultPromise(cx, request->promise());
// Step 6.
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!promise)
return false;
// Step 7.
if (!ResolvePromiseInternal(cx, promise, value))
return false;
// Steps 8-9.
RootedValue onFulfilled(cx, Int32Value(done
? PromiseHandlerAsyncIteratorValueUnwrapDone
: PromiseHandlerAsyncIteratorValueUnwrapNotDone));
RootedObject incumbentGlobal(cx);
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
return false;
// Step 10.
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise, onFulfilled,
UndefinedHandleValue,
nullptr, nullptr,
incumbentGlobal));
if (!reaction)
return false;
if (!PerformPromiseThenWithReaction(cx, promise, reaction))
return false;
// Step 11.
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
return false;
// Step 12.
return true;
}
// Async Iteration proposal 6.4.3.4.
MOZ_MUST_USE bool
js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue exception)
{
// Step 1 (implicit).
// Steps 2-3.
MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
// Step 4.
Rooted<AsyncGeneratorRequest*> request(
cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
if (!request)
return false;
// Step 5.
RootedObject resultPromise(cx, request->promise());
// Step 6.
if (!RejectMaybeWrappedPromise(cx, resultPromise, exception))
return false;
// Step 7.
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
return false;
// Step 8.
return true;
}
// Async Iteration proposal 6.4.3.6.
MOZ_MUST_USE bool
js::AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal,
CompletionKind completionKind, HandleValue completionValue,
MutableHandleValue result)
{
// Step 1 (implicit).
// Step 2.
RootedObject resultPromise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
if (!resultPromise)
return false;
// Step 3.
if (!asyncGenVal.isObject() || !asyncGenVal.toObject().is<AsyncGeneratorObject>()) {
// Step 3.a.
RootedValue badGeneratorError(cx);
if (!GetTypeError(cx, JSMSG_NOT_AN_ASYNC_GENERATOR, &badGeneratorError))
return false;
// Step 3.b.
if (!RejectMaybeWrappedPromise(cx, resultPromise, badGeneratorError))
return false;
// Step 3.c.
result.setObject(*resultPromise);
return true;
}
Rooted<AsyncGeneratorObject*> asyncGenObj(
cx, &asyncGenVal.toObject().as<AsyncGeneratorObject>());
// Step 5 (reordered).
Rooted<AsyncGeneratorRequest*> request(
cx, AsyncGeneratorRequest::create(cx, completionKind, completionValue, resultPromise));
if (!request)
return false;
// Steps 4, 6.
if (!AsyncGeneratorObject::enqueueRequest(cx, asyncGenObj, request))
return false;
// Step 7.
if (!asyncGenObj->isExecuting()) {
// Step 8.
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
return false;
}
// Step 9.
result.setObject(*resultPromise);
return true;
}
// ES2016, 25.4.5.3.
bool
js::Promise_then(JSContext* cx, unsigned argc, Value* vp)

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

@ -135,6 +135,26 @@ AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise);
MOZ_MUST_USE bool
AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
class AsyncGeneratorObject;
MOZ_MUST_USE bool
AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value);
MOZ_MUST_USE bool
AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value, bool done);
MOZ_MUST_USE bool
AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue exception);
MOZ_MUST_USE bool
AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal, CompletionKind completionKind,
HandleValue completionValue, MutableHandleValue result);
bool
AsyncFromSyncIteratorMethod(JSContext* cx, CallArgs& args, CompletionKind completionKind);
/**
* A PromiseTask represents a task that can be dispatched to a helper thread
* (via StartPromiseTask), executed (by implementing PromiseTask::execute()),

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

@ -778,3 +778,15 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd);
}
bool
frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,
JS::SourceBufferHolder& srcBuf,
const Maybe<uint32_t>& parameterListEnd)
{
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd);
}

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

@ -89,6 +89,12 @@ CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun,
JS::SourceBufferHolder& srcBuf,
const mozilla::Maybe<uint32_t>& parameterListEnd);
MOZ_MUST_USE bool
CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,
JS::SourceBufferHolder& srcBuf,
const mozilla::Maybe<uint32_t>& parameterListEnd);
MOZ_MUST_USE bool
CompileAsyncFunctionBody(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,

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

@ -2004,11 +2004,15 @@ class ForOfLoopControl : public LoopControl
bool allowSelfHosted_;
IteratorKind iterKind_;
public:
ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted)
ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted,
IteratorKind iterKind)
: LoopControl(bce, StatementKind::ForOfLoop),
iterDepth_(iterDepth),
allowSelfHosted_(allowSelfHosted)
allowSelfHosted_(allowSelfHosted),
iterKind_(iterKind)
{
}
@ -2064,7 +2068,7 @@ class ForOfLoopControl : public LoopControl
bool emitIteratorClose(BytecodeEmitter* bce,
CompletionKind completionKind = CompletionKind::Normal) {
ptrdiff_t start = bce->offset();
if (!bce->emitIteratorClose(completionKind, allowSelfHosted_))
if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_))
return false;
ptrdiff_t end = bce->offset();
return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
@ -3676,6 +3680,18 @@ BytecodeEmitter::emitFinishIteratorResult(bool done)
return true;
}
bool
BytecodeEmitter::emitToIteratorResult(bool done)
{
if (!emitPrepareIteratorResult()) // VALUE OBJ
return false;
if (!emit1(JSOP_SWAP)) // OBJ VALUE
return false;
if (!emitFinishIteratorResult(done)) // RESULT
return false;
return true;
}
bool
BytecodeEmitter::emitGetNameAtLocation(JSAtom* name, const NameLocation& loc, bool callContext)
{
@ -5210,7 +5226,8 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri
}
bool
BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted /* = false */)
BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = IteratorKind::Sync */,
bool allowSelfHosted /* = false */)
{
MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
".next() iteration is prohibited in self-hosted code because it "
@ -5224,6 +5241,12 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted /* = false
return false;
if (!emitCall(JSOP_CALL, 0, pn)) // ... RESULT
return false;
if (iterKind == IteratorKind::Async) {
if (!emitAwait()) // ... RESULT
return false;
}
if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
return false;
checkTypeSet(JSOP_CALL);
@ -5231,7 +5254,8 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted /* = false
}
bool
BytecodeEmitter::emitIteratorClose(CompletionKind completionKind /* = CompletionKind::Normal */,
BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */,
CompletionKind completionKind /* = CompletionKind::Normal */,
bool allowSelfHosted /* = false */)
{
MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
@ -5316,6 +5340,11 @@ BytecodeEmitter::emitIteratorClose(CompletionKind completionKind /* = Completion
return false;
checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (!emitAwait()) // ... ... RESULT
return false;
}
if (completionKind == CompletionKind::Throw) {
if (!emit1(JSOP_SWAP)) // ... RET ITER RESULT UNDEF
return false;
@ -5325,7 +5354,7 @@ BytecodeEmitter::emitIteratorClose(CompletionKind completionKind /* = Completion
if (!tryCatch->emitCatch()) // ... RET ITER RESULT
return false;
// Just ignore the exception thrown by call.
// Just ignore the exception thrown by call and await.
if (!emit1(JSOP_EXCEPTION)) // ... RET ITER RESULT EXC
return false;
if (!emit1(JSOP_POP)) // ... RET ITER RESULT
@ -6746,6 +6775,63 @@ BytecodeEmitter::emitIterator()
return true;
}
bool
BytecodeEmitter::emitAsyncIterator()
{
// Convert iterable to iterator.
if (!emit1(JSOP_DUP)) // OBJ OBJ
return false;
if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::asyncIterator))) // OBJ OBJ @@ASYNCITERATOR
return false;
if (!emitElemOpBase(JSOP_CALLELEM)) // OBJ ITERFN
return false;
IfThenElseEmitter ifAsyncIterIsUndefined(this);
if (!emit1(JSOP_DUP)) // OBJ ITERFN ITERFN
return false;
if (!emit1(JSOP_UNDEFINED)) // OBJ ITERFN ITERFN UNDEF
return false;
if (!emit1(JSOP_EQ)) // OBJ ITERFN EQ
return false;
if (!ifAsyncIterIsUndefined.emitIfElse()) // OBJ ITERFN
return false;
if (!emit1(JSOP_POP)) // OBJ
return false;
if (!emit1(JSOP_DUP)) // OBJ OBJ
return false;
if (!emit2(JSOP_SYMBOL, uint8_t(JS::SymbolCode::iterator))) // OBJ OBJ @@ITERATOR
return false;
if (!emitElemOpBase(JSOP_CALLELEM)) // OBJ ITERFN
return false;
if (!emit1(JSOP_SWAP)) // ITERFN OBJ
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
if (!emit1(JSOP_TOASYNCITER)) // ITER
return false;
if (!ifAsyncIterIsUndefined.emitElse()) // OBJ ITERFN
return false;
if (!emit1(JSOP_SWAP)) // ITERFN OBJ
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
if (!ifAsyncIterIsUndefined.emitEnd()) // ITER
return false;
return true;
}
bool
BytecodeEmitter::emitSpread(bool allowSelfHosted)
{
@ -6799,7 +6885,7 @@ BytecodeEmitter::emitSpread(bool allowSelfHosted)
if (!emitDupAt(2)) // ITER ARR I ITER
return false;
if (!emitIteratorNext(nullptr, allowSelfHosted)) // ITER ARR I RESULT
if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted)) // ITER ARR I RESULT
return false;
if (!emit1(JSOP_DUP)) // ITER ARR I RESULT RESULT
return false;
@ -6899,6 +6985,13 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
unsigned iflags = forOfLoop->pn_iflags;
IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
? IteratorKind::Async
: IteratorKind::Sync;
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
ParseNode* forHeadExpr = forOfHead->pn_kid3;
// Certain builtins (e.g. Array.from) are implemented in self-hosting
@ -6914,8 +7007,13 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
// Evaluate the expression being iterated.
if (!emitTree(forHeadExpr)) // ITERABLE
return false;
if (!emitIterator()) // ITER
return false;
if (iterKind == IteratorKind::Async) {
if (!emitAsyncIterator()) // ITER
return false;
} else {
if (!emitIterator()) // ITER
return false;
}
int32_t iterDepth = stackDepth;
@ -6926,7 +7024,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
if (!emit1(JSOP_UNDEFINED)) // ITER RESULT UNDEF
return false;
ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter);
ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
// Annotate so IonMonkey can find the loop-closing jump.
unsigned noteIndex;
@ -7022,7 +7120,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
if (!emitDupAt(1)) // ITER UNDEF ITER
return false;
if (!emitIteratorNext(forOfHead, allowSelfHostedIter)) // ITER UNDEF RESULT
if (!emitIteratorNext(forOfHead, iterKind, allowSelfHostedIter)) // ITER UNDEF RESULT
return false;
if (!emit1(JSOP_SWAP)) // ITER RESULT UNDEF
@ -7841,7 +7939,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW));
if (funbox->isAsync()) {
MOZ_ASSERT(!needsProto);
return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow());
return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(),
fun->isStarGenerator());
}
if (fun->isArrow()) {
@ -7896,8 +7995,11 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
MOZ_ASSERT(pn->getOp() == JSOP_NOP);
switchToPrologue();
if (funbox->isAsync()) {
if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow()))
if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(),
fun->isStarGenerator()))
{
return false;
}
} else {
if (!emitIndex32(JSOP_LAMBDA, index))
return false;
@ -7913,10 +8015,12 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
// initialize the binding name of the function in the current scope.
bool isAsync = funbox->isAsync();
auto emitLambda = [index, isAsync](BytecodeEmitter* bce, const NameLocation&, bool) {
bool isStarGenerator = funbox->isStarGenerator();
auto emitLambda = [index, isAsync, isStarGenerator](BytecodeEmitter* bce,
const NameLocation&, bool) {
if (isAsync) {
return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false,
/* isArrow = */ false);
/* isArrow = */ false, isStarGenerator);
}
return bce->emitIndexOp(JSOP_LAMBDA, index);
};
@ -7951,7 +8055,8 @@ BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) {
}
bool
BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow)
BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
bool isStarGenerator)
{
// needsHomeObject can be true for propertyList for extended class.
// In that case push both unwrapped and wrapped function, in order to
@ -7983,8 +8088,13 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA
if (!emit1(JSOP_DUP))
return false;
}
if (!emit1(JSOP_TOASYNC))
return false;
if (isStarGenerator) {
if (!emit1(JSOP_TOASYNCGEN))
return false;
} else {
if (!emit1(JSOP_TOASYNC))
return false;
}
return true;
}
@ -8355,13 +8465,8 @@ BytecodeEmitter::emitYield(ParseNode* pn)
}
bool
BytecodeEmitter::emitAwait(ParseNode* pn)
BytecodeEmitter::emitAwait()
{
MOZ_ASSERT(sc->isFunctionBox());
MOZ_ASSERT(pn->getOp() == JSOP_AWAIT);
if (!emitTree(pn->pn_kid))
return false;
if (!emitGetDotGenerator())
return false;
if (!emitYieldOp(JSOP_AWAIT))
@ -8369,16 +8474,34 @@ BytecodeEmitter::emitAwait(ParseNode* pn)
return true;
}
bool
BytecodeEmitter::emitAwait(ParseNode* pn)
{
MOZ_ASSERT(sc->isFunctionBox());
MOZ_ASSERT(pn->getOp() == JSOP_AWAIT);
if (!emitTree(pn->pn_kid))
return false;
return emitAwait();
}
bool
BytecodeEmitter::emitYieldStar(ParseNode* iter)
{
MOZ_ASSERT(sc->isFunctionBox());
MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator());
bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
if (!emitTree(iter)) // ITERABLE
return false;
if (!emitIterator()) // ITER
return false;
if (isAsyncGenerator) {
if (!emitAsyncIterator()) // ITER
return false;
} else {
if (!emitIterator()) // ITER
return false;
}
// Initial send value is undefined.
if (!emit1(JSOP_UNDEFINED)) // ITER RECEIVED
@ -8436,7 +8559,8 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
//
// If the iterator does not have a "throw" method, it calls IteratorClose
// and then throws a TypeError.
if (!emitIteratorClose()) // ITER RESULT EXCEPTION
IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync;
if (!emitIteratorClose(iterKind)) // ITER RESULT EXCEPTION
return false;
if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw
return false;
@ -8452,6 +8576,12 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
if (!emitCall(JSOP_CALL, 1, iter)) // ITER OLDRESULT RESULT
return false;
checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwait()) // ITER OLDRESULT RESULT
return false;
}
if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) // ITER OLDRESULT RESULT
return false;
if (!emit1(JSOP_SWAP)) // ITER RESULT OLDRESULT
@ -8518,6 +8648,11 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (!emitAwait()) // ... FTYPE FVALUE RESULT
return false;
}
// Step v.
if (!emitCheckIsObj(CheckIsObjectKind::IteratorReturn)) // ITER OLDRESULT FTYPE FVALUE RESULT
return false;
@ -8535,6 +8670,12 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // ITER OLDRESULT FTYPE FVALUE VALUE
return false;
if (isAsyncGenerator) {
if (!emitAwait()) // ITER OLDRESULT FTYPE FVALUE VALUE
return false;
}
if (!emitPrepareIteratorResult()) // ITER OLDRESULT FTYPE FVALUE VALUE RESULT
return false;
if (!emit1(JSOP_SWAP)) // ITER OLDRESULT FTYPE FVALUE RESULT VALUE
@ -8590,9 +8731,15 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1, iter)) // ITER RESULT
return false;
checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwait()) // ITER RESULT RESULT
return false;
}
if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ITER RESULT
return false;
checkTypeSet(JSOP_CALL);
MOZ_ASSERT(this->stackDepth == startDepth);
if (!emitJumpTargetAndPatch(checkResult)) // checkResult:
@ -8619,6 +8766,11 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // VALUE
return false;
if (isAsyncGenerator) {
if (!emitAwait()) // VALUE
return false;
}
MOZ_ASSERT(this->stackDepth == startDepth - 1);
return true;

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

@ -10,6 +10,7 @@
#define frontend_BytecodeEmitter_h
#include "jscntxt.h"
#include "jsiter.h"
#include "jsopcode.h"
#include "jsscript.h"
@ -605,6 +606,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitPrepareIteratorResult();
MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
MOZ_MUST_USE bool emitToIteratorResult(bool done);
MOZ_MUST_USE bool emitGetDotGenerator();
@ -612,6 +614,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitYield(ParseNode* pn);
MOZ_MUST_USE bool emitYieldOp(JSOp op);
MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
MOZ_MUST_USE bool emitAwait();
MOZ_MUST_USE bool emitAwait(ParseNode* pn);
MOZ_MUST_USE bool emitPropLHS(ParseNode* pn);
@ -619,7 +622,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow);
MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow);
MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
bool isStarGenerator);
MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName);
@ -693,10 +697,14 @@ struct MOZ_STACK_CLASS BytecodeEmitter
// It will replace that stack value with the corresponding iterator
MOZ_MUST_USE bool emitIterator();
MOZ_MUST_USE bool emitAsyncIterator();
// Pops iterator from the top of the stack. Pushes the result of |.next()|
// onto the stack.
MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, bool allowSelfHosted = false);
MOZ_MUST_USE bool emitIteratorClose(CompletionKind completionKind = CompletionKind::Normal,
MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync,
bool allowSelfHosted = false);
MOZ_MUST_USE bool emitIteratorClose(IteratorKind iterKind = IteratorKind::Sync,
CompletionKind completionKind = CompletionKind::Normal,
bool allowSelfHosted = false);
template <typename InnerEmitter>

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

@ -3753,9 +3753,11 @@ Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHan
GeneratorKind generatorKind = NotGenerator;
if (tt == TOK_MUL) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
if (!asyncIterationSupported()) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
@ -3825,9 +3827,11 @@ Parser<ParseHandler>::functionExpr(uint32_t preludeStart, InvokedPrediction invo
return null();
if (tt == TOK_MUL) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
if (!asyncIterationSupported()) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
@ -5857,6 +5861,7 @@ Parser<ParseHandler>::matchInOrOf(bool* isForInp, bool* isForOfp)
template <class ParseHandler>
bool
Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
IteratorKind iterKind,
ParseNodeKind* forHeadKind,
Node* forInitialPart,
Maybe<ParseContext::Scope>& forLoopLexicalScope,
@ -5947,6 +5952,11 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
if (!matchInOrOf(&isForIn, &isForOf))
return false;
if (iterKind == IteratorKind::Async && !isForOf) {
error(JSMSG_FOR_AWAIT_NOT_OF);
return false;
}
// If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled
// the init expression; the caller handles the rest. Allow the Operand
// modifier when regetting: Operand must be used to examine the ';' in
@ -6020,6 +6030,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
ParseContext::Statement stmt(pc, StatementKind::ForLoop);
bool isForEach = false;
IteratorKind iterKind = IteratorKind::Sync;
unsigned iflags = 0;
if (allowsForEachIn()) {
@ -6035,6 +6046,19 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
}
}
if (asyncIterationSupported()) {
if (pc->isAsync()) {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_AWAIT))
return null();
if (matched) {
iflags |= JSITER_FORAWAITOF;
iterKind = IteratorKind::Async;
}
}
}
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
// PNK_FORHEAD, PNK_FORIN, or PNK_FOROF depending on the loop type.
@ -6072,7 +6096,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
//
// In either case the subsequent token can be consistently accessed using
// TokenStream::None semantics.
if (!forHeadStart(yieldHandling, &headKind, &startNode, forLoopLexicalScope,
if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode, forLoopLexicalScope,
&iteratedExpr))
{
return null();
@ -9288,11 +9312,6 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
bool isGenerator = false;
bool isAsync = false;
if (ltok == TOK_MUL) {
isGenerator = true;
if (!tokenStream.getToken(&ltok))
return null();
}
if (ltok == TOK_ASYNC) {
// AsyncMethod[Yield, Await]:
@ -9321,9 +9340,16 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
}
}
if (isAsync && isGenerator) {
error(JSMSG_ASYNC_GENERATOR);
return null();
if (ltok == TOK_MUL) {
if (!asyncIterationSupported()) {
if (isAsync) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
isGenerator = true;
if (!tokenStream.getToken(&ltok))
return null();
}
propAtom.set(nullptr);

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

@ -13,6 +13,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/TypeTraits.h"
#include "jsiter.h"
#include "jspubtd.h"
#include "frontend/BytecodeCompiler.h"
@ -821,6 +822,16 @@ class ParserBase : public StrictModeGetter
pc->isLegacyGenerator();
}
bool asyncIterationSupported() {
#ifdef RELEASE_OR_BETA
return false;
#else
// Expose Async Iteration only to web content until the spec proposal
// gets stable.
return !options().isProbablySystemOrAddonCode;
#endif
}
virtual bool strictMode() { return pc->sc()->strict(); }
bool setLocalStrictMode(bool strict) {
MOZ_ASSERT(tokenStream.debugHasNoLookahead());
@ -1175,6 +1186,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node forStatement(YieldHandling yieldHandling);
bool forHeadStart(YieldHandling yieldHandling,
IteratorKind iterKind,
ParseNodeKind* forHeadKind,
Node* forInitialPart,
mozilla::Maybe<ParseContext::Scope>& forLetImpliedScope,

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

@ -0,0 +1,24 @@
// |jit-test| error: InternalError
// This tests that attempting to perform ModuleDeclarationInstantation a second
// time after a failure throws an error. Doing this would be a bug in the module
// loader, which is expected to throw away modules if there is an error
// instantiating them.
//
// The first attempt fails becuase module 'a' is not available. The second
// attempt fails because of the previous failure.
//
// This test exercises the path where the previously instantiated module is
// re-instantiated directly.
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {
return moduleRepo[specifier];
});
let c;
try {
let b = moduleRepo['b'] = parseModule("export var b = 3; export var c = 4;");
c = moduleRepo['c'] = parseModule("export * from 'a'; export * from 'b';");
c.declarationInstantiation();
} catch (exc) {}
c.declarationInstantiation();

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

@ -8,6 +8,9 @@
// The first attempt fails becuase module 'a' is not available. The second
// attempt fails because of the previous failure (it would otherwise succeed as
// 'a' is now available).
//
// This test exercises the path where the previously instantiated module is
// encountered as an import.
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {

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

@ -7,6 +7,6 @@ if (typeof oomTest !== 'function' || !wasmIsSupported()) {
function foo() {
var g = newGlobal();
g.eval(`o = new WebAssembly.Instance(new WebAssemby.Module(wasmTextToBinary('(module (func) (export "" 0))')));`);
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (func) (export "" 0))')));`);
}
oomTest(foo);

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

@ -25,6 +25,7 @@
#include "jit/VMFunctions.h"
#include "js/UniquePtr.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/EnvironmentObject.h"
#include "vm/Interpreter.h"
#include "vm/TraceLogging.h"
@ -3922,6 +3923,50 @@ BaselineCompiler::emit_JSOP_TOASYNC()
return true;
}
typedef JSObject* (*ToAsyncGenFn)(JSContext*, HandleFunction);
static const VMFunction ToAsyncGenInfo =
FunctionInfo<ToAsyncGenFn>(js::WrapAsyncGenerator, "ToAsyncGen");
bool
BaselineCompiler::emit_JSOP_TOASYNCGEN()
{
frame.syncStack(0);
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
prepareVMCall();
pushArg(R0.scratchReg());
if (!callVM(ToAsyncGenInfo))
return false;
masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
frame.pop();
frame.push(R0);
return true;
}
typedef JSObject* (*ToAsyncIterFn)(JSContext*, HandleObject);
static const VMFunction ToAsyncIterInfo =
FunctionInfo<ToAsyncIterFn>(js::CreateAsyncFromSyncIterator, "ToAsyncIter");
bool
BaselineCompiler::emit_JSOP_TOASYNCITER()
{
frame.syncStack(0);
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
prepareVMCall();
pushArg(R0.scratchReg());
if (!callVM(ToAsyncIterInfo))
return false;
masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
frame.pop();
frame.push(R0);
return true;
}
typedef bool (*ThrowObjectCoercibleFn)(JSContext*, HandleValue);
static const VMFunction ThrowObjectCoercibleInfo =
FunctionInfo<ThrowObjectCoercibleFn>(ThrowObjectCoercible, "ThrowObjectCoercible");

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

@ -197,6 +197,8 @@ namespace jit {
_(JSOP_RUNONCE) \
_(JSOP_REST) \
_(JSOP_TOASYNC) \
_(JSOP_TOASYNCGEN) \
_(JSOP_TOASYNCITER) \
_(JSOP_TOID) \
_(JSOP_TOSTRING) \
_(JSOP_TABLESWITCH) \

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

@ -41,6 +41,7 @@
#include "jit/RangeAnalysis.h"
#include "jit/SharedICHelpers.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/MatchPairs.h"
#include "vm/RegExpObject.h"
#include "vm/RegExpStatics.h"
@ -10696,6 +10697,28 @@ CodeGenerator::visitToAsync(LToAsync* lir)
callVM(ToAsyncInfo, lir);
}
typedef JSObject* (*ToAsyncGenFn)(JSContext*, HandleFunction);
static const VMFunction ToAsyncGenInfo =
FunctionInfo<ToAsyncGenFn>(js::WrapAsyncGenerator, "ToAsyncGen");
void
CodeGenerator::visitToAsyncGen(LToAsyncGen* lir)
{
pushArg(ToRegister(lir->unwrapped()));
callVM(ToAsyncGenInfo, lir);
}
typedef JSObject* (*ToAsyncIterFn)(JSContext*, HandleObject);
static const VMFunction ToAsyncIterInfo =
FunctionInfo<ToAsyncIterFn>(js::CreateAsyncFromSyncIterator, "ToAsyncIter");
void
CodeGenerator::visitToAsyncIter(LToAsyncIter* lir)
{
pushArg(ToRegister(lir->unwrapped()));
callVM(ToAsyncIterInfo, lir);
}
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue,
MutableHandleValue);
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(ToIdOperation, "ToIdOperation");

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

@ -296,6 +296,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitTypeOfV(LTypeOfV* lir);
void visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool);
void visitToAsync(LToAsync* lir);
void visitToAsyncGen(LToAsyncGen* lir);
void visitToAsyncIter(LToAsyncIter* lir);
void visitToIdV(LToIdV* lir);
template<typename T> void emitLoadElementT(LLoadElementT* lir, const T& source);
void visitLoadElementT(LLoadElementT* lir);

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

@ -2068,13 +2068,13 @@ CompileBackEnd(MIRGenerator* mir)
return GenerateCode(mir, lir);
}
// Find a finished builder for the compartment.
// Find a finished builder for the runtime.
static IonBuilder*
GetFinishedBuilder(JSContext* cx, GlobalHelperThreadState::IonBuilderVector& finished)
{
for (size_t i = 0; i < finished.length(); i++) {
IonBuilder* testBuilder = finished[i];
if (testBuilder->compartment == CompileCompartment::get(cx->compartment())) {
if (testBuilder->script()->runtimeFromAnyThread() == cx->runtime()) {
HelperThreadState().remove(finished, &i);
return testBuilder;
}
@ -2095,10 +2095,10 @@ AttachFinishedCompilations(JSContext* cx)
GlobalHelperThreadState::IonBuilderVector& finished = HelperThreadState().ionFinishedList(lock);
// Incorporate any off thread compilations for the compartment which have
// Incorporate any off thread compilations for the runtime which have
// finished, failed or have been cancelled.
while (true) {
// Find a finished builder for the compartment.
// Find a finished builder for the runtime.
IonBuilder* builder = GetFinishedBuilder(cx, finished);
if (!builder)
break;

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

@ -2212,6 +2212,12 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_TOASYNC:
return jsop_toasync();
case JSOP_TOASYNCGEN:
return jsop_toasyncgen();
case JSOP_TOASYNCITER:
return jsop_toasynciter();
case JSOP_TOID:
return jsop_toid();
@ -12257,6 +12263,34 @@ IonBuilder::jsop_toasync()
return resumeAfter(ins);
}
AbortReasonOr<Ok>
IonBuilder::jsop_toasyncgen()
{
MDefinition* unwrapped = current->pop();
MOZ_ASSERT(unwrapped->type() == MIRType::Object);
MToAsyncGen* ins = MToAsyncGen::New(alloc(), unwrapped);
current->add(ins);
current->push(ins);
return resumeAfter(ins);
}
AbortReasonOr<Ok>
IonBuilder::jsop_toasynciter()
{
MDefinition* unwrapped = current->pop();
MOZ_ASSERT(unwrapped->type() == MIRType::Object);
MToAsyncIter* ins = MToAsyncIter::New(alloc(), unwrapped);
current->add(ins);
current->push(ins);
return resumeAfter(ins);
}
AbortReasonOr<Ok>
IonBuilder::jsop_toid()
{

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

@ -569,6 +569,8 @@ class IonBuilder
AbortReasonOr<Ok> jsop_globalthis();
AbortReasonOr<Ok> jsop_typeof();
AbortReasonOr<Ok> jsop_toasync();
AbortReasonOr<Ok> jsop_toasyncgen();
AbortReasonOr<Ok> jsop_toasynciter();
AbortReasonOr<Ok> jsop_toid();
AbortReasonOr<Ok> jsop_iter(uint8_t flags);
AbortReasonOr<Ok> jsop_itermore();

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

@ -1210,6 +1210,22 @@ LIRGenerator::visitToAsync(MToAsync* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitToAsyncGen(MToAsyncGen* ins)
{
LToAsyncGen* lir = new(alloc()) LToAsyncGen(useRegisterAtStart(ins->input()));
defineReturn(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitToAsyncIter(MToAsyncIter* ins)
{
LToAsyncIter* lir = new(alloc()) LToAsyncIter(useRegisterAtStart(ins->input()));
defineReturn(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitToId(MToId* ins)
{

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

@ -121,6 +121,8 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitCompare(MCompare* comp);
void visitTypeOf(MTypeOf* ins);
void visitToAsync(MToAsync* ins);
void visitToAsyncGen(MToAsyncGen* ins);
void visitToAsyncIter(MToAsyncIter* ins);
void visitToId(MToId* ins);
void visitBitNot(MBitNot* ins);
void visitBitAnd(MBitAnd* ins);

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

@ -5825,6 +5825,36 @@ class MToAsync
TRIVIAL_NEW_WRAPPERS
};
class MToAsyncGen
: public MUnaryInstruction,
public SingleObjectPolicy::Data
{
explicit MToAsyncGen(MDefinition* unwrapped)
: MUnaryInstruction(unwrapped)
{
setResultType(MIRType::Object);
}
public:
INSTRUCTION_HEADER(ToAsyncGen)
TRIVIAL_NEW_WRAPPERS
};
class MToAsyncIter
: public MUnaryInstruction,
public SingleObjectPolicy::Data
{
explicit MToAsyncIter(MDefinition* unwrapped)
: MUnaryInstruction(unwrapped)
{
setResultType(MIRType::Object);
}
public:
INSTRUCTION_HEADER(ToAsyncIter)
TRIVIAL_NEW_WRAPPERS
};
class MToId
: public MUnaryInstruction,
public BoxInputsPolicy::Data

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

@ -79,6 +79,8 @@ namespace jit {
_(BitNot) \
_(TypeOf) \
_(ToAsync) \
_(ToAsyncGen) \
_(ToAsyncIter) \
_(ToId) \
_(BitAnd) \
_(BitOr) \

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

@ -364,8 +364,8 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
if (!js::array_push(cx, 1, argv.begin()))
return false;
if (MOZ_LIKELY(argv[0].isInt32())) {
*length = argv[0].isInt32();
if (argv[0].isInt32()) {
*length = argv[0].toInt32();
return true;
}

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

@ -1618,6 +1618,32 @@ class LToAsync : public LCallInstructionHelper<1, 1, 0>
}
};
class LToAsyncGen : public LCallInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(ToAsyncGen)
explicit LToAsyncGen(const LAllocation& input) {
setOperand(0, input);
}
const LAllocation* unwrapped() {
return getOperand(0);
}
};
class LToAsyncIter : public LCallInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(ToAsyncIter)
explicit LToAsyncIter(const LAllocation& input) {
setOperand(0, input);
}
const LAllocation* unwrapped() {
return getOperand(0);
}
};
class LToIdV : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
{
public:

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

@ -363,6 +363,8 @@
_(Rest) \
_(TypeOfV) \
_(ToAsync) \
_(ToAsyncGen) \
_(ToAsyncIter) \
_(ToIdV) \
_(Floor) \
_(FloorF) \

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

@ -591,3 +591,9 @@ MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "P
// Iterator
MSG_DEF(JSMSG_RETURN_NOT_CALLABLE, 0, JSEXN_TYPEERR, "property 'return' of iterator is not callable")
MSG_DEF(JSMSG_ITERATOR_NO_THROW, 0, JSEXN_TYPEERR, "iterator does not have a 'throw' method")
// Async Iteration
MSG_DEF(JSMSG_FOR_AWAIT_NOT_OF, 0, JSEXN_TYPEERR, "'for await' loop should be used with 'of'")
MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator")
MSG_DEF(JSMSG_NOT_AN_ASYNC_ITERATOR, 0, JSEXN_TYPEERR, "Not an async from sync iterator")
MSG_DEF(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.asyncIterator]() returned a non-object value")

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

@ -157,11 +157,19 @@ TestWeakMaps()
JSObject* weakMap = JS::NewWeakMapObject(cx);
CHECK(weakMap);
JSObject* key = AllocWeakmapKeyObject();
CHECK(key);
JSObject* key;
JSObject* value;
{
JS::RootedObject rootedMap(cx, weakMap);
JSObject* value = AllocPlainObject();
CHECK(value);
key = AllocWeakmapKeyObject();
CHECK(key);
value = AllocPlainObject();
CHECK(value);
weakMap = rootedMap;
}
{
JS::RootedObject rootedMap(cx, weakMap);

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

@ -71,6 +71,7 @@
#include "js/StructuredClone.h"
#include "js/Utility.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/DateObject.h"
#include "vm/Debugger.h"
#include "vm/EnvironmentObject.h"
@ -3615,6 +3616,11 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
return nullptr;
}
if (IsWrappedAsyncGenerator(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
// If the script is to be reused, either the script can already handle
// non-syntactic scopes, or there is only the standard global lexical
@ -3867,6 +3873,7 @@ JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOp
introductionLineno = rhs.introductionLineno;
introductionOffset = rhs.introductionOffset;
hasIntroductionInfo = rhs.hasIntroductionInfo;
isProbablySystemOrAddonCode = rhs.isProbablySystemOrAddonCode;
};
void
@ -3979,6 +3986,7 @@ JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
strictOption = cx->options().strictMode();
extraWarningsOption = cx->compartment()->behaviors().extraWarnings(cx);
forEachStatementOption = cx->options().forEachStatement();
isProbablySystemOrAddonCode = cx->compartment()->isProbablySystemOrAddonCode();
werrorOption = cx->options().werror();
if (!cx->options().asmJS())
asmJSOption = AsmJSOption::Disabled;

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

@ -3879,6 +3879,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
forceAsync(false),
sourceIsLazy(false),
allowHTMLComments(true),
isProbablySystemOrAddonCode(false),
introductionType(nullptr),
introductionLineno(0),
introductionOffset(0),
@ -3915,6 +3916,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
bool forceAsync;
bool sourceIsLazy;
bool allowHTMLComments;
bool isProbablySystemOrAddonCode;
// |introductionType| is a statically allocated C string:
// one of "eval", "Function", or "GeneratorFunction".
@ -5162,7 +5164,8 @@ GetSymbolDescription(HandleSymbol symbol);
macro(split) \
macro(toPrimitive) \
macro(toStringTag) \
macro(unscopables)
macro(unscopables) \
macro(asyncIterator)
enum class SymbolCode : uint32_t {
// There is one SymbolCode for each well-known symbol.

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

@ -649,11 +649,6 @@ JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleObject rawStrings,
// registry.
MOZ_ASSERT(!templateObj->nonProxyIsExtensible());
} else {
// Add the template object to the registry before freezing to avoid
// needing to call relookupOrAdd.
if (!templateLiteralMap_.add(p, rawStrings, templateObj))
return false;
MOZ_ASSERT(templateObj->nonProxyIsExtensible());
RootedValue rawValue(cx, ObjectValue(*rawStrings));
if (!DefineProperty(cx, templateObj, cx->names().raw, rawValue, nullptr, nullptr, 0))
@ -662,6 +657,9 @@ JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleObject rawStrings,
return false;
if (!FreezeObject(cx, templateObj))
return false;
if (!templateLiteralMap_.relookupOrAdd(p, rawStrings, templateObj))
return false;
}
return true;

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

@ -975,6 +975,7 @@ IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
#define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
#define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
#define JSITER_FORAWAITOF 0x80 /* for-await-of */
JS_FRIEND_API(bool)
RunningWithTrustedPrincipals(JSContext* cx);

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

@ -41,6 +41,7 @@
#include "js/CallNonGenericMethod.h"
#include "js/Proxy.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
@ -306,6 +307,8 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args)
JSFunction* callerFun = &callerObj->as<JSFunction>();
if (IsWrappedAsyncFunction(callerFun))
callerFun = GetUnwrappedAsyncFunction(callerFun);
else if (IsWrappedAsyncGenerator(callerFun))
callerFun = GetUnwrappedAsyncGenerator(callerFun);
MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
if (callerFun->strict()) {
@ -402,13 +405,15 @@ static const JSPropertySpec function_properties[] = {
static bool
ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id)
{
MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
bool isAsyncGenerator = IsWrappedAsyncGenerator(fun);
MOZ_ASSERT_IF(!isAsyncGenerator, fun->isInterpreted() || fun->isAsmJSNative());
MOZ_ASSERT(id == NameToId(cx->names().prototype));
// Assert that fun is not a compiler-created function object, which
// must never leak to script or embedding code and then be mutated.
// Also assert that fun is not bound, per the ES5 15.3.4.5 ref above.
MOZ_ASSERT(!IsInternalFunctionObject(*fun));
MOZ_ASSERT_IF(!isAsyncGenerator, !IsInternalFunctionObject(*fun));
MOZ_ASSERT(!fun->isBoundFunction());
// Make the prototype object an instance of Object with the same parent as
@ -418,7 +423,9 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId
bool isStarGenerator = fun->isStarGenerator();
Rooted<GlobalObject*> global(cx, &fun->global());
RootedObject objProto(cx);
if (isStarGenerator)
if (isAsyncGenerator)
objProto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, global);
else if (isStarGenerator)
objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
else
objProto = GlobalObject::getOrCreateObjectPrototype(cx, global);
@ -434,7 +441,7 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId
// non-enumerable, and writable. However, per the 15 July 2013 ES6 draft,
// section 15.19.3, the .prototype of a generator function does not link
// back with a .constructor.
if (!isStarGenerator) {
if (!isStarGenerator && !isAsyncGenerator) {
RootedValue objVal(cx, ObjectValue(*fun));
if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0))
return false;
@ -484,11 +491,13 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
* - Arrow functions
* - Function.prototype
*/
if (fun->isBuiltin())
return true;
if (!fun->isConstructor()) {
if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync())
if (!IsWrappedAsyncGenerator(fun)) {
if (fun->isBuiltin())
return true;
if (!fun->isConstructor()) {
if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync())
return true;
}
}
if (!ResolveInterpretedFunctionPrototype(cx, fun, id))
@ -985,6 +994,10 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun));
return FunctionToString(cx, unwrapped, prettyPrint);
}
if (IsWrappedAsyncGenerator(fun)) {
RootedFunction unwrapped(cx, GetUnwrappedAsyncGenerator(fun));
return FunctionToString(cx, unwrapped, prettyPrint);
}
StringBuffer out(cx);
RootedScript script(cx);
@ -1637,10 +1650,14 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
&mutedErrors);
const char* introductionType = "Function";
if (isAsync)
introductionType = "AsyncFunction";
else if (generatorKind != NotGenerator)
if (isAsync) {
if (isStarGenerator)
introductionType = "AsyncGenerator";
else
introductionType = "AsyncFunction";
} else if (generatorKind != NotGenerator) {
introductionType = "GeneratorFunction";
}
const char* introducerFilename = filename;
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
@ -1767,12 +1784,20 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
: SourceBufferHolder::NoOwnership;
bool ok;
SourceBufferHolder srcBuf(chars.begin().get(), chars.length(), ownership);
if (isAsync)
ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf, parameterListEnd);
else if (isStarGenerator)
ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd);
else
ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd);
if (isAsync) {
if (isStarGenerator) {
ok = frontend::CompileStandaloneAsyncGenerator(cx, &fun, options, srcBuf,
parameterListEnd);
} else {
ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf,
parameterListEnd);
}
} else {
if (isStarGenerator)
ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd);
else
ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd);
}
// Step 33.
args.rval().setObject(*fun);
@ -1798,7 +1823,7 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// Save the callee before its reset in FunctionConstructor().
// Save the callee before it's reset in FunctionConstructor().
RootedObject newTarget(cx);
if (args.isConstructing())
newTarget = &args.newTarget().toObject();
@ -1830,6 +1855,40 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
return true;
}
bool
js::AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// Save the callee before its reset in FunctionConstructor().
RootedObject newTarget(cx);
if (args.isConstructing())
newTarget = &args.newTarget().toObject();
else
newTarget = &args.callee();
if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction))
return false;
RootedObject proto(cx);
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
return false;
if (!proto) {
proto = GlobalObject::getOrCreateAsyncGenerator(cx, cx->global());
if (!proto)
return false;
}
RootedFunction unwrapped(cx, &args.rval().toObject().as<JSFunction>());
RootedObject wrapped(cx, WrapAsyncGeneratorWithProto(cx, unwrapped, proto));
if (!wrapped)
return false;
args.rval().setObject(*wrapped);
return true;
}
bool
JSFunction::isBuiltinFunctionConstructor()
{

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

@ -647,6 +647,9 @@ Generator(JSContext* cx, unsigned argc, Value* vp);
extern bool
AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp);
extern bool
AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
// Allocate a new function backed by a JSNative. Note that by default this
// creates a singleton object.
extern JSFunction*

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

@ -938,28 +938,30 @@ js::GetIteratorObject(JSContext* cx, HandleObject obj, uint32_t flags)
return iterator;
}
// ES 2017 draft 7.4.7.
JSObject*
js::CreateItrResultObject(JSContext* cx, HandleValue value, bool done)
js::CreateIterResultObject(JSContext* cx, HandleValue value, bool done)
{
// FIXME: We can cache the iterator result object shape somewhere.
AssertHeapIsIdle();
// Step 1 (implicit).
RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, cx->global()));
if (!proto)
// Step 2.
RootedObject resultObj(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!resultObj)
return nullptr;
RootedPlainObject obj(cx, NewObjectWithGivenProto<PlainObject>(cx, proto));
if (!obj)
// Step 3.
if (!DefineProperty(cx, resultObj, cx->names().value, value))
return nullptr;
if (!DefineProperty(cx, obj, cx->names().value, value))
// Step 4.
if (!DefineProperty(cx, resultObj, cx->names().done,
done ? TrueHandleValue : FalseHandleValue))
{
return nullptr;
}
RootedValue doneBool(cx, BooleanValue(done));
if (!DefineProperty(cx, obj, cx->names().done, doneBool))
return nullptr;
return obj;
// Step 5.
return resultObj;
}
bool

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

@ -210,10 +210,10 @@ ThrowStopIteration(JSContext* cx);
/*
* Create an object of the form { value: VALUE, done: DONE }.
* ES6 draft from 2013-09-05, section 25.4.3.4.
* ES 2017 draft 7.4.7.
*/
extern JSObject*
CreateItrResultObject(JSContext* cx, HandleValue value, bool done);
CreateIterResultObject(JSContext* cx, HandleValue value, bool done);
extern JSObject*
InitLegacyIteratorClass(JSContext* cx, HandleObject obj);
@ -221,6 +221,8 @@ InitLegacyIteratorClass(JSContext* cx, HandleObject obj);
extern JSObject*
InitStopIterationClass(JSContext* cx, HandleObject obj);
enum class IteratorKind { Sync, Async };
} /* namespace js */
#endif /* jsiter_h */

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

@ -2027,8 +2027,12 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex)
case JSOP_LAMBDA:
case JSOP_LAMBDA_ARROW:
case JSOP_TOASYNC:
case JSOP_TOASYNCGEN:
return write("FUN");
case JSOP_TOASYNCITER:
return write("ASYNCITER");
case JSOP_MOREITER:
// For stack dump, defIndex == 0 is not used.
MOZ_ASSERT(defIndex == 1);
@ -2071,6 +2075,7 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex)
case JSOP_UNINITIALIZED:
return write("UNINITIALIZED");
case JSOP_AWAIT:
case JSOP_YIELD:
// Printing "yield SOMETHING" is confusing since the operand doesn't
// match to the syntax, since the stack operand for "yield 10" is

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

@ -311,6 +311,7 @@ UNIFIED_SOURCES += [
'vm/ArgumentsObject.cpp',
'vm/ArrayBufferObject.cpp',
'vm/AsyncFunction.cpp',
'vm/AsyncIteration.cpp',
'vm/Caches.cpp',
'vm/CallNonGenericMethod.cpp',
'vm/CharacterEncoding.cpp',
@ -753,6 +754,7 @@ selfhosted.inputs = [
'builtin/SelfHostingDefines.h',
'builtin/Utilities.js',
'builtin/Array.js',
'builtin/AsyncIteration.js',
'builtin/Classes.js',
'builtin/Date.js',
'builtin/Error.js',
@ -793,3 +795,6 @@ if CONFIG['GNU_CXX']:
# Suppress warnings in third-party code.
if CONFIG['CLANG_CXX']:
SOURCES['jsdtoa.cpp'].flags += ['-Wno-implicit-fallthrough']
if CONFIG['OS_ARCH'] == 'WINNT':
DEFINES['NOMINMAX'] = True

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

@ -86,6 +86,7 @@
#include "threading/Thread.h"
#include "vm/ArgumentsObject.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/Compression.h"
#include "vm/Debugger.h"
#include "vm/HelperThreads.h"
@ -2395,6 +2396,8 @@ ValueToScript(JSContext* cx, HandleValue v, JSFunction** funp = nullptr)
// Get unwrapped async function.
if (IsWrappedAsyncFunction(fun))
fun = GetUnwrappedAsyncFunction(fun);
if (IsWrappedAsyncGenerator(fun))
fun = GetUnwrappedAsyncGenerator(fun);
if (!fun->isInterpreted()) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_SCRIPTS_ONLY);

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

@ -9,9 +9,6 @@ if (typeof Reflect !== "undefined" && Reflect.parse) {
assertEq(Reflect.parse("async function a() {}").body[0].async, true);
assertEq(Reflect.parse("() => {}").body[0].async, undefined);
// Async generators are not allowed (with regards to spec)
assertThrows(() => Reflect.parse("async function* a() {}"), SyntaxError);
// No line terminator after async
assertEq(Reflect.parse("async\nfunction a(){}").body[0].expression.name, "async");

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

@ -11,7 +11,8 @@ var names = [
"hasInstance",
"split",
"toPrimitive",
"unscopables"
"unscopables",
"asyncIterator"
];
for (var name of names) {

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

@ -40,6 +40,9 @@ skip script test262/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
skip-if(!Array.prototype.values) script test262/built-ins/Array/prototype/Symbol.iterator.js
skip-if(!Array.prototype.values) include test262/built-ins/Array/prototype/values/jstests.list
# Async generator is non-release-or-beta only.
skip-if(release_or_beta) include test262/language/expressions/async-generators/jstests.list
skip-if(release_or_beta) include test262/language/statements/async-generator/jstests.list
#####################################
# Test262 tests disabled on browser #
@ -493,10 +496,6 @@ skip script test262/annexB/language/eval-code/indirect/global-if-decl-else-decl-
skip script test262/annexB/language/eval-code/indirect/global-block-decl-eval-global-exsting-global-init.js
skip script test262/annexB/language/eval-code/indirect/global-switch-case-eval-global-exsting-global-init.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1331092
skip include test262/language/expressions/async-generators/jstests.list
skip include test262/language/statements/async-generator/jstests.list
# SIMD.
skip script test262/built-ins/Simd/check.js
skip script test262/built-ins/Simd/from.js
@ -871,3 +870,11 @@ skip script test262/intl402/PluralRules/prototype/select/tainting.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1340304
skip-if(!xulRuntime.shell) script test262/language/module-code/instn-iee-err-circular.js
skip-if(!xulRuntime.shell) script test262/language/module-code/instn-iee-err-circular-as.js
# Async generators are now a thing.
skip script test262/language/statements/async-function/early-errors-no-async-generator-n.js
# Need to be rewritten to follow the change in https://github.com/tc39/proposal-async-iteration/pull/92
skip script test262/language/statements/async-generator/yield-star-async-next.js
skip script test262/language/statements/async-generator/yield-star-async-return.js
skip script test262/language/statements/async-generator/yield-star-async-throw.js

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше