mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Merge inbound to central, a=merge
This commit is contained in:
commit
514e230373
22
accessible/interfaces/msaa/AccessibleMarshalThunk.c
Normal file
22
accessible/interfaces/msaa/AccessibleMarshalThunk.c
Normal file
@ -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/. */
|
||||
|
||||
#include "ISimpleDOM.h"
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
ISimpleDOMNode_get_localInterface_Proxy(ISimpleDOMNode * This,
|
||||
void **localInterface)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
ISimpleDOMNode_get_localInterface_Stub(ISimpleDOMNode * This,
|
||||
IUnknown **localInterface)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -168,6 +168,9 @@ interface ISimpleDOMNode : IUnknown
|
||||
|
||||
[propget, local] HRESULT localInterface([out][retval] void **localInterface);
|
||||
|
||||
[propget, call_as(get_localInterface)]
|
||||
HRESULT remoteLocalInterface([out][retval] IUnknown **localInterface);
|
||||
|
||||
[propget] HRESULT language([out, retval] BSTR *language);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ SOURCES += [
|
||||
'!dlldata.c',
|
||||
'!ISimpleDOM_i.c',
|
||||
'!ISimpleDOM_p.c',
|
||||
'AccessibleMarshalThunk.c',
|
||||
]
|
||||
|
||||
DEFINES['REGISTER_PROXY_DLL'] = True
|
||||
|
@ -1513,7 +1513,7 @@ pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
|
||||
pref("dom.ipc.cpows.forbid-cpows-in-compat-addons", true);
|
||||
|
||||
// ...except for these add-ons:
|
||||
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},firegestures@xuldev.org,{DDC359D1-844A-42a7-9AA1-88A850A938A8},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,treestyletab@piro.sakura.ne.jp,cliqz@cliqz.com,{AE93811A-5C9A-4d34-8462-F7B864FC4696},contextsearch2@lwz.addons.mozilla.org,{EF522540-89F5-46b9-B6FE-1829E2B572C6},{677a8f98-fd64-40b0-a883-b8c95d0cbf17},images@wink.su,fx-devtools,toolkit/require,url_advisor@kaspersky.com,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d},{dc572301-7619-498c-a57d-39143191b318},dta@downthemall.net,{86095750-AD15-46d8-BF32-C0789F7E6A32},screenwise-prod@google.com,{91aa5abe-9de4-4347-b7b5-322c38dd9271},secureLogin@blueimp.net,ich@maltegoetz.de,come.back.block.image.from@cat-in-136.blogspot.com,{7b1bf0b6-a1b9-42b0-b75d-252036438bdc},s3crypto@data,{1e0fd655-5aea-4b4c-a583-f76ef1e3af9c},akahuku.fx.sp@toshiakisp.github.io,{aff87fa2-a58e-4edd-b852-0a20203c1e17},{1018e4d6-728f-4b20-ad56-37578a4de76b},rehostimage@engy.us,lazarus@interclue.com,{b2e69492-2358-071a-7056-24ad0c3defb1},flashstopper@byo.co.il,{e4a8a97b-f2ed-450b-b12d-ee082ba24781},jid1-f3mYMbCpz2AZYl@jetpack,{8c550e28-88c9-4764-bb52-aa489cf2efcd},{37fa1426-b82d-11db-8314-0800200c9a66},{ac2cfa60-bc96-11e0-962b-0800200c9a66},igetter@presenta.net,killspinners@byo.co.il,abhere2@moztw.org,{fc6339b8-9581-4fc7-b824-dffcb091fcb7},wampi@wink.su,backtrack@byalexv.co.uk,Gladiator_X@mail.ru,{73a6fe31-595d-460b-a920-fcc0f8843232},{46551EC9-40F0-4e47-8E18-8E5CF550CFB8},acewebextension_unlisted@acestream.org,@screen_maker,yasearch@yandex.ru,sp@avast.com,s3google@translator,igetterextension@presenta.net,{C1A2A613-35F1-4FCF-B27F-2840527B6556},screenwise-testing@google.com,helper-sig@savefrom.net,browser-loader,ImageSaver@Merci.chao,proxtube@abz.agency,wrc@avast.com,{9AA46F4F-4DC7-4c06-97AF-5035170634FE},jid1-CikLKKPVkw6ipw@jetpack,artur.dubovoy@gmail.com,nlgfeb@nlgfeb.ext,{A065A84F-95B6-433A-A0C8-4C040B77CE8A},fdm_ffext@freedownloadmanager.org");
|
||||
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},firegestures@xuldev.org,{DDC359D1-844A-42a7-9AA1-88A850A938A8},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,treestyletab@piro.sakura.ne.jp,cliqz@cliqz.com,{AE93811A-5C9A-4d34-8462-F7B864FC4696},contextsearch2@lwz.addons.mozilla.org,{EF522540-89F5-46b9-B6FE-1829E2B572C6},{677a8f98-fd64-40b0-a883-b8c95d0cbf17},images@wink.su,fx-devtools,url_advisor@kaspersky.com,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d},{dc572301-7619-498c-a57d-39143191b318},dta@downthemall.net,{86095750-AD15-46d8-BF32-C0789F7E6A32},screenwise-prod@google.com,{91aa5abe-9de4-4347-b7b5-322c38dd9271},secureLogin@blueimp.net,ich@maltegoetz.de,come.back.block.image.from@cat-in-136.blogspot.com,{7b1bf0b6-a1b9-42b0-b75d-252036438bdc},s3crypto@data,{1e0fd655-5aea-4b4c-a583-f76ef1e3af9c},akahuku.fx.sp@toshiakisp.github.io,{aff87fa2-a58e-4edd-b852-0a20203c1e17},{1018e4d6-728f-4b20-ad56-37578a4de76b},rehostimage@engy.us,lazarus@interclue.com,{b2e69492-2358-071a-7056-24ad0c3defb1},flashstopper@byo.co.il,{e4a8a97b-f2ed-450b-b12d-ee082ba24781},jid1-f3mYMbCpz2AZYl@jetpack,{8c550e28-88c9-4764-bb52-aa489cf2efcd},{37fa1426-b82d-11db-8314-0800200c9a66},{ac2cfa60-bc96-11e0-962b-0800200c9a66},igetter@presenta.net,killspinners@byo.co.il,abhere2@moztw.org,{fc6339b8-9581-4fc7-b824-dffcb091fcb7},wampi@wink.su,backtrack@byalexv.co.uk,Gladiator_X@mail.ru,{73a6fe31-595d-460b-a920-fcc0f8843232},{46551EC9-40F0-4e47-8E18-8E5CF550CFB8},acewebextension_unlisted@acestream.org,@screen_maker,yasearch@yandex.ru,sp@avast.com,s3google@translator,igetterextension@presenta.net,{C1A2A613-35F1-4FCF-B27F-2840527B6556},screenwise-testing@google.com,helper-sig@savefrom.net,ImageSaver@Merci.chao,proxtube@abz.agency,wrc@avast.com,{9AA46F4F-4DC7-4c06-97AF-5035170634FE},jid1-CikLKKPVkw6ipw@jetpack,artur.dubovoy@gmail.com,nlgfeb@nlgfeb.ext,{A065A84F-95B6-433A-A0C8-4C040B77CE8A},fdm_ffext@freedownloadmanager.org");
|
||||
|
||||
// Enable e10s hang monitoring (slow script checking and plugin hang
|
||||
// detection).
|
||||
|
@ -32,8 +32,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
ShortcutUtils:false, SimpleServiceDiscovery:false, SitePermissions:false,
|
||||
Social:false, TabCrashHandler:false, Task:false, TelemetryStopwatch:false,
|
||||
Translation:false, UITour:false, UpdateUtils:false, Weave:false,
|
||||
fxAccounts:false, gDevTools:false, gDevToolsBrowser:false, webrtcUI:false,
|
||||
FullZoomUI:false
|
||||
WebNavigationFrames: false, fxAccounts:false, gDevTools:false,
|
||||
gDevToolsBrowser:false, webrtcUI:false, FullZoomUI:false
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -80,6 +80,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
["UITour", "resource:///modules/UITour.jsm"],
|
||||
["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
|
||||
["Weave", "resource://services-sync/main.js"],
|
||||
["WebNavigationFrames", "resource://gre/modules/WebNavigationFrames.js"],
|
||||
["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
|
||||
["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
|
||||
["gDevToolsBrowser", "resource://devtools/client/framework/gDevTools.jsm"],
|
||||
@ -5803,9 +5804,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||
}
|
||||
}
|
||||
|
||||
let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
let params = {
|
||||
|
@ -47,6 +47,8 @@ XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
|
||||
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
||||
return new tmp.PageMenuChild();
|
||||
});
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
|
||||
"resource://gre/modules/WebNavigationFrames.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Feeds",
|
||||
"resource:///modules/Feeds.jsm");
|
||||
|
||||
@ -120,9 +122,7 @@ var handleContentContextMenu = function(event) {
|
||||
let baseURI = doc.baseURI;
|
||||
let referrer = doc.referrer;
|
||||
let referrerPolicy = doc.referrerPolicy;
|
||||
let frameOuterWindowID = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
|
||||
let loginFillInfo = LoginManagerContent.getFieldContext(event.target);
|
||||
|
||||
// The same-origin check will be done in nsContextMenu.openLinkInTab.
|
||||
@ -536,9 +536,7 @@ var ClickEventHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
let frameOuterWindowID = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
let frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
|
||||
|
||||
let json = { button: event.button, shiftKey: event.shiftKey,
|
||||
ctrlKey: event.ctrlKey, metaKey: event.metaKey,
|
||||
@ -1055,7 +1053,7 @@ var PageInfoListener = {
|
||||
let frameOuterWindowID = message.data.frameOuterWindowID;
|
||||
|
||||
// If inside frame then get the frame's window and document.
|
||||
if (frameOuterWindowID) {
|
||||
if (frameOuterWindowID != undefined) {
|
||||
window = Services.wm.getOuterWindowWithId(frameOuterWindowID);
|
||||
document = window.document;
|
||||
} else {
|
||||
|
@ -15,6 +15,8 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
|
||||
"resource://gre/modules/LoginHelper.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
|
||||
"resource://gre/modules/WebNavigationFrames.jsm");
|
||||
|
||||
var gContextMenuContentData = null;
|
||||
|
||||
@ -62,7 +64,7 @@ nsContextMenu.prototype = {
|
||||
pageUrl: this.browser ? this.browser.currentURI.spec : undefined,
|
||||
linkUrl: this.linkURL,
|
||||
selectionText: this.isTextSelected ? this.selectionInfo.text : undefined,
|
||||
windowId: this.frameOuterWindowID,
|
||||
frameId: this.frameOuterWindowID,
|
||||
};
|
||||
subject.wrappedJSObject = subject;
|
||||
Services.obs.notifyObservers(subject, "on-build-contextmenu", null);
|
||||
@ -670,10 +672,7 @@ nsContextMenu.prototype = {
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
this.principal = ownerDoc.nodePrincipal;
|
||||
this.frameOuterWindowID = ownerDoc.defaultView
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
this.frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
|
||||
}
|
||||
this.onSocial = !!this.browser.getAttribute("origin");
|
||||
|
||||
@ -996,9 +995,7 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
|
||||
if (!this.isRemote) {
|
||||
params.frameOuterWindowID = this.target.ownerGlobal
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
params.frameOuterWindowID = WebNavigationFrames.getFrameId(this.target.ownerGlobal);
|
||||
}
|
||||
// If we want to change userContextId, we must be sure that we don't
|
||||
// propagate the referrer.
|
||||
|
@ -1,15 +1,17 @@
|
||||
[DEFAULT]
|
||||
# These tests can be prone to intermittent failures on slower systems.
|
||||
# Since the specific flavor doesn't matter from a correctness standpoint,
|
||||
# just skip the tests on ASAN and debug builds. Also known to be flaky on
|
||||
# Linux32 (bug 1172468, bug 1349307), so skip them there as well.
|
||||
skip-if = asan || debug || (os == 'linux' && bits == 32)
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_all_files_referenced.js]
|
||||
skip-if = debug || (os == 'linux' && bits == 32) # no point in running on both opt and debug, and will likely intermittently timeout on debug; oom crashes on linux32 (bug 1349307)
|
||||
[browser_misused_characters_in_strings.js]
|
||||
support-files =
|
||||
bug1262648_string_with_newlines.dtd
|
||||
[browser_parsable_css.js]
|
||||
support-files =
|
||||
dummy_page.html
|
||||
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
|
||||
[browser_parsable_script.js]
|
||||
skip-if = asan || (os == 'linux' && !debug && (bits == 32)) # disabled on asan because of timeouts, and bug 1172468 for the linux 32-bit pgo issue.
|
||||
|
@ -326,7 +326,7 @@ function openLinkIn(url, where, params) {
|
||||
|
||||
const sourceWindow = (w || window);
|
||||
let win;
|
||||
if (params.frameOuterWindowID && sourceWindow) {
|
||||
if (params.frameOuterWindowID != undefined && sourceWindow) {
|
||||
// Only notify it as a WebExtensions' webNavigation.onCreatedNavigationTarget
|
||||
// event if it contains the expected frameOuterWindowID params.
|
||||
// (e.g. we should not notify it as a onCreatedNavigationTarget if the user is
|
||||
@ -450,7 +450,7 @@ function openLinkIn(url, where, params) {
|
||||
});
|
||||
targetBrowser = tabUsedForLoad.linkedBrowser;
|
||||
|
||||
if (params.frameOuterWindowID && w) {
|
||||
if (params.frameOuterWindowID != undefined && w) {
|
||||
// Only notify it as a WebExtensions' webNavigation.onCreatedNavigationTarget
|
||||
// event if it contains the expected frameOuterWindowID params.
|
||||
// (e.g. we should not notify it as a onCreatedNavigationTarget if the user is
|
||||
|
@ -496,11 +496,6 @@ MenuItem.prototype = {
|
||||
mediaType = "image";
|
||||
}
|
||||
|
||||
let frameId;
|
||||
if (contextData.windowId) {
|
||||
frameId = ExtensionManagement.getFrameId(contextData.windowId);
|
||||
}
|
||||
|
||||
let info = {
|
||||
menuItemId: this.id,
|
||||
editable: contextData.onEditableArea || contextData.onPassword,
|
||||
@ -518,7 +513,7 @@ MenuItem.prototype = {
|
||||
setIfDefined("srcUrl", contextData.srcUrl);
|
||||
setIfDefined("pageUrl", contextData.pageUrl);
|
||||
setIfDefined("frameUrl", contextData.frameUrl);
|
||||
setIfDefined("frameId", frameId);
|
||||
setIfDefined("frameId", contextData.frameId);
|
||||
setIfDefined("selectionText", contextData.selectionText);
|
||||
|
||||
if ((this.type === "checkbox") || (this.type === "radio")) {
|
||||
|
@ -124,7 +124,6 @@ support-files =
|
||||
[browser_ext_tabs_update_url.js]
|
||||
[browser_ext_themes_icons.js]
|
||||
[browser_ext_themes_validation.js]
|
||||
[browser_ext_topwindowid.js]
|
||||
[browser_ext_url_overrides_newtab.js]
|
||||
[browser_ext_url_overrides_home.js]
|
||||
[browser_ext_webRequest.js]
|
||||
|
@ -1,23 +0,0 @@
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* test_topwindowid_cleanup() {
|
||||
let {Frames} = Cu.import("resource://gre/modules/ExtensionManagement.jsm", {});
|
||||
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
|
||||
|
||||
let {outerWindowID, messageManager} = tab.linkedBrowser;
|
||||
|
||||
ok(Frames.topWindowIds.has(outerWindowID), "Outer window ID is registered");
|
||||
|
||||
let awaitDisconnect = TestUtils.topicObserved("message-manager-disconnect",
|
||||
subject => subject === messageManager);
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
|
||||
yield awaitDisconnect;
|
||||
|
||||
ok(!Frames.topWindowIds.has(outerWindowID), "Outer window ID is no longer registered");
|
||||
});
|
||||
|
@ -104,6 +104,9 @@
|
||||
|
||||
RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}"
|
||||
|
||||
; Register AccessibleHandler.dll with COM (this writes to HKLM)
|
||||
${RegisterAccessibleHandler}
|
||||
|
||||
!ifdef MOZ_MAINTENANCE_SERVICE
|
||||
Call IsUserAdmin
|
||||
Pop $R0
|
||||
@ -850,6 +853,11 @@
|
||||
!define AddMaintCertKeys "!insertmacro AddMaintCertKeys"
|
||||
!endif
|
||||
|
||||
!macro RegisterAccessibleHandler
|
||||
${RegisterDLL} "$INSTDIR\AccessibleHandler.dll"
|
||||
!macroend
|
||||
!define RegisterAccessibleHandler "!insertmacro RegisterAccessibleHandler"
|
||||
|
||||
; Removes various registry entries for reasons noted below (does not use SHCTX).
|
||||
!macro RemoveDeprecatedKeys
|
||||
StrCpy $0 "SOFTWARE\Classes"
|
||||
|
@ -906,7 +906,7 @@ cargo_target_flag := --target=$(RUST_TARGET)
|
||||
|
||||
# Permit users to pass flags to cargo from their mozconfigs (e.g. --color=always).
|
||||
cargo_build_flags = $(CARGOFLAGS)
|
||||
ifndef MOZ_DEBUG
|
||||
ifndef MOZ_DEBUG_RUST
|
||||
cargo_build_flags += --release
|
||||
endif
|
||||
cargo_build_flags += --frozen
|
||||
@ -936,8 +936,8 @@ endif
|
||||
ifndef MOZ_OPTIMIZE
|
||||
rustflags = -C opt-level=0
|
||||
# Unfortunately, -C opt-level=0 implies -C debug-assertions, so we need
|
||||
# to explicitly disable them when MOZ_DEBUG is not set.
|
||||
ifndef MOZ_DEBUG
|
||||
# to explicitly disable them when MOZ_DEBUG_RUST is not set.
|
||||
ifndef MOZ_DEBUG_RUST
|
||||
rustflags += -C debug-assertions=no
|
||||
endif
|
||||
rustflags_override = RUSTFLAGS='$(rustflags)'
|
||||
|
@ -86,17 +86,22 @@ TabGroup::GetChromeTabGroup()
|
||||
}
|
||||
|
||||
/* static */ TabGroup*
|
||||
TabGroup::GetFromWindowActor(mozIDOMWindowProxy* aWindow)
|
||||
TabGroup::GetFromWindow(mozIDOMWindowProxy* aWindow)
|
||||
{
|
||||
if (TabChild* tabChild = TabChild::GetFrom(aWindow)) {
|
||||
return tabChild->TabGroup();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ TabGroup*
|
||||
TabGroup::GetFromActor(TabChild* aTabChild)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
TabChild* tabChild = TabChild::GetFrom(aWindow);
|
||||
if (!tabChild) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
nsCOMPtr<nsIEventTarget> target = cc->GetActorEventTarget(tabChild);
|
||||
nsCOMPtr<nsIEventTarget> target = cc->GetActorEventTarget(aTabChild);
|
||||
if (!target) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -67,13 +67,13 @@ public:
|
||||
static TabGroup*
|
||||
GetChromeTabGroup();
|
||||
|
||||
// Checks if the PBrowserChild associated with aWindow already has a TabGroup
|
||||
// assigned to it in IPDL. Returns this TabGroup if it does. This could happen
|
||||
// if the parent process created the PBrowser and we needed to assign a
|
||||
// TabGroup immediately upon receiving the IPDL message. This method is main
|
||||
// thread only.
|
||||
static TabGroup*
|
||||
GetFromWindowActor(mozIDOMWindowProxy* aWindow);
|
||||
// Checks if the TabChild already has a TabGroup assigned to it in
|
||||
// IPDL. Returns this TabGroup if it does. This could happen if the parent
|
||||
// process created the PBrowser and we needed to assign a TabGroup immediately
|
||||
// upon receiving the IPDL message. This method is main thread only.
|
||||
static TabGroup* GetFromActor(TabChild* aTabChild);
|
||||
|
||||
static TabGroup* GetFromWindow(mozIDOMWindowProxy* aWindow);
|
||||
|
||||
explicit TabGroup(bool aIsChrome = false);
|
||||
|
||||
|
@ -2415,22 +2415,6 @@ nsDOMWindowUtils::StopFrameTimeRecording(uint32_t startIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::BeginTabSwitch()
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LayerManager *mgr = widget->GetLayerManager();
|
||||
if (!mgr)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mgr->BeginTabSwitch();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
ComputeAnimationValue(nsCSSPropertyID aProperty,
|
||||
Element* aElement,
|
||||
|
@ -2833,28 +2833,30 @@ nsFrameLoader::SetClampScrollPosition(bool aClamp)
|
||||
}
|
||||
|
||||
static
|
||||
ContentParent*
|
||||
Tuple<ContentParent*, TabParent*>
|
||||
GetContentParent(Element* aBrowser)
|
||||
{
|
||||
using ReturnTuple = Tuple<ContentParent*, TabParent*>;
|
||||
|
||||
nsCOMPtr<nsIBrowser> browser = do_QueryInterface(aBrowser);
|
||||
if (!browser) {
|
||||
return nullptr;
|
||||
return ReturnTuple(nullptr, nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> otherLoader;
|
||||
browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoader));
|
||||
if (!otherLoader) {
|
||||
return nullptr;
|
||||
return ReturnTuple(nullptr, nullptr);
|
||||
}
|
||||
|
||||
TabParent* tabParent = TabParent::GetFrom(otherLoader);
|
||||
if (tabParent &&
|
||||
tabParent->Manager() &&
|
||||
tabParent->Manager()->IsContentParent()) {
|
||||
return tabParent->Manager()->AsContentParent();
|
||||
return MakeTuple(tabParent->Manager()->AsContentParent(), tabParent);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return ReturnTuple(nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2889,7 +2891,8 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
}
|
||||
|
||||
TabParent* openingTab = TabParent::GetFrom(parentDocShell->GetOpener());
|
||||
ContentParent* openerContentParent = nullptr;
|
||||
RefPtr<ContentParent> openerContentParent;
|
||||
RefPtr<TabParent> sameTabGroupAs;
|
||||
|
||||
if (openingTab &&
|
||||
openingTab->Manager() &&
|
||||
@ -2933,7 +2936,7 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
}
|
||||
|
||||
// Try to get the related content parent from our browser element.
|
||||
openerContentParent = GetContentParent(mOwnerContent);
|
||||
Tie(openerContentParent, sameTabGroupAs) = GetContentParent(mOwnerContent);
|
||||
}
|
||||
|
||||
uint32_t chromeFlags = 0;
|
||||
@ -2955,7 +2958,8 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
||||
mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement, openerContentParent);
|
||||
mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement,
|
||||
openerContentParent, sameTabGroupAs);
|
||||
if (!mRemoteBrowser) {
|
||||
return false;
|
||||
}
|
||||
|
@ -15005,15 +15005,14 @@ nsGlobalWindow::TabGroupOuter()
|
||||
} else if (parent) {
|
||||
toJoin = parent->TabGroup();
|
||||
} else {
|
||||
// If the tab was created by the parent process, the IPC code may have
|
||||
// already created a TabGroup for us. Fetch it in that case.
|
||||
toJoin = TabGroup::GetFromWindowActor(AsOuter());
|
||||
toJoin = TabGroup::GetFromWindow(AsOuter());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Make sure that, if we have a tab group from the actor, it matches the one
|
||||
// we're planning to join.
|
||||
mozilla::dom::TabGroup* actorTabGroup = TabGroup::GetFromWindowActor(AsOuter());
|
||||
MOZ_ASSERT_IF(actorTabGroup, actorTabGroup == toJoin);
|
||||
mozilla::dom::TabGroup* testGroup = TabGroup::GetFromWindow(AsOuter());
|
||||
MOZ_ASSERT_IF(testGroup, testGroup == toJoin);
|
||||
#endif
|
||||
|
||||
mTabGroup = mozilla::dom::TabGroup::Join(AsOuter(), toJoin);
|
||||
|
24
dom/base/test/intersectionobserver_cross_domain_iframe.html
Normal file
24
dom/base/test/intersectionobserver_cross_domain_iframe.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
#target5 {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: #f00;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="target5"></div>
|
||||
<script>
|
||||
var io = new IntersectionObserver(function (records) {
|
||||
console.log(records[0].rootBounds, location.href);
|
||||
window.parent.postMessage(records[0].rootBounds == null, 'http://mochi.test:8888');
|
||||
}, {});
|
||||
io.observe(document.getElementById("target5"));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -13,12 +13,5 @@
|
||||
</style>
|
||||
<body>
|
||||
<div id="target5"></div>
|
||||
<script>
|
||||
var io = new IntersectionObserver(function (records) {
|
||||
window.parent.postMessage(records[0].rootBounds == null, 'http://mochi.test:8888');
|
||||
io.disconnect();
|
||||
}, {});
|
||||
io.observe(document.getElementById("target5"));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -27,7 +27,6 @@
|
||||
records[0].rootBounds.bottom === viewportHeight &&
|
||||
records[0].rootBounds.height === viewportHeight;
|
||||
window.opener.postMessage(passed, '*');
|
||||
io.disconnect();
|
||||
});
|
||||
io.observe(document.getElementById("target"));
|
||||
</script>
|
||||
|
@ -921,7 +921,7 @@ limitations under the License.
|
||||
callDelayed(function () {
|
||||
expect(spy.callCount).to.be(1);
|
||||
done();
|
||||
}, ASYNC_TIMEOUT);
|
||||
}, ASYNC_TIMEOUT * 3);
|
||||
});
|
||||
|
||||
});
|
||||
@ -970,11 +970,11 @@ limitations under the License.
|
||||
it('rootBounds should is set to null for cross-origin observations', function(done) {
|
||||
|
||||
window.onmessage = function (e) {
|
||||
expect(e.data).to.be.ok();
|
||||
expect(e.data).to.be(true);
|
||||
done();
|
||||
};
|
||||
|
||||
targetEl4.src = "http://example.org/tests/dom/base/test/intersectionobserver_iframe.html";
|
||||
targetEl4.src = "http://example.org/tests/dom/base/test/intersectionobserver_cross_domain_iframe.html";
|
||||
|
||||
});
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -409,7 +409,7 @@ public:
|
||||
}
|
||||
|
||||
void DrawWindow(nsGlobalWindow& aWindow, double aX, double aY,
|
||||
double aW, double aH,
|
||||
double aW, double aH,
|
||||
const nsAString& aBgColor, uint32_t aFlags,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
@ -451,11 +451,12 @@ public:
|
||||
const char16_t* aEncoderOptions,
|
||||
nsIInputStream** aStream) override;
|
||||
|
||||
already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) override
|
||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType = nullptr) override
|
||||
{
|
||||
EnsureTarget();
|
||||
if (aPremultAlpha) {
|
||||
*aPremultAlpha = true;
|
||||
if (aOutAlphaType) {
|
||||
*aOutAlphaType = (mOpaque ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
|
||||
}
|
||||
return mTarget->Snapshot();
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ static already_AddRefed<SourceSurface>
|
||||
GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, ErrorResult& aRv)
|
||||
{
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(&aElement, nsLayoutUtils::SFE_WANT_FIRST_FRAME);
|
||||
nsLayoutUtils::SurfaceFromElement(&aElement, nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE);
|
||||
|
||||
// check origin-clean
|
||||
if (!CheckSecurityForHTMLElements(res)) {
|
||||
@ -432,13 +432,13 @@ HasRasterImage(HTMLImageElement& aImageEl)
|
||||
}
|
||||
|
||||
ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||
bool aIsPremultipliedAlpha /* = true */)
|
||||
gfxAlphaType aAlphaType)
|
||||
: mParent(aGlobal)
|
||||
, mData(aData)
|
||||
, mSurface(nullptr)
|
||||
, mDataWrapper(new ImageUtils(mData))
|
||||
, mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height)
|
||||
, mIsPremultipliedAlpha(aIsPremultipliedAlpha)
|
||||
, mAlphaType(aAlphaType)
|
||||
, mIsCroppingAreaOutSideOfSourceImage(false)
|
||||
{
|
||||
MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor.");
|
||||
@ -622,13 +622,11 @@ ImageBitmap::PrepareForDrawTarget(gfx::DrawTarget* aTarget)
|
||||
}
|
||||
|
||||
// Pre-multiply alpha here.
|
||||
// Apply pre-multiply alpha only if mIsPremultipliedAlpha is false.
|
||||
// Ignore this step if the source surface does not have alpha channel; this
|
||||
// kind of source surfaces might come form layers::PlanarYCbCrImage.
|
||||
if (!mIsPremultipliedAlpha &&
|
||||
mSurface->GetFormat() != SurfaceFormat::B8G8R8X8 &&
|
||||
mSurface->GetFormat() != SurfaceFormat::R8G8B8X8 &&
|
||||
mSurface->GetFormat() != SurfaceFormat::X8R8G8B8) {
|
||||
if (mAlphaType == gfxAlphaType::NonPremult &&
|
||||
!IsOpaque(mSurface->GetFormat()))
|
||||
{
|
||||
MOZ_ASSERT(mSurface->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
||||
mSurface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
||||
mSurface->GetFormat() == SurfaceFormat::A8R8G8B8);
|
||||
@ -692,7 +690,7 @@ ImageBitmap::ToCloneData() const
|
||||
{
|
||||
UniquePtr<ImageBitmapCloneData> result(new ImageBitmapCloneData());
|
||||
result->mPictureRect = mPictureRect;
|
||||
result->mIsPremultipliedAlpha = mIsPremultipliedAlpha;
|
||||
result->mAlphaType = mAlphaType;
|
||||
result->mIsCroppingAreaOutSideOfSourceImage = mIsCroppingAreaOutSideOfSourceImage;
|
||||
RefPtr<SourceSurface> surface = mData->GetAsSourceSurface();
|
||||
result->mSurface = surface->GetDataSurface();
|
||||
@ -707,8 +705,7 @@ ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
|
||||
{
|
||||
RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface);
|
||||
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data,
|
||||
aData->mIsPremultipliedAlpha);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mAlphaType);
|
||||
|
||||
// Report memory allocation.
|
||||
RegisterAllocation(aGlobal, aData->mSurface);
|
||||
@ -734,7 +731,7 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal,
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromOffscreenCanvas(&aOffscreenCanvas,
|
||||
nsLayoutUtils::SFE_WANT_FIRST_FRAME);
|
||||
nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE);
|
||||
|
||||
RefPtr<SourceSurface> surface = res.GetSourceSurface();
|
||||
|
||||
@ -926,6 +923,8 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
|
||||
|
||||
array.ComputeLengthAndData();
|
||||
const SurfaceFormat FORMAT = SurfaceFormat::R8G8B8A8;
|
||||
// ImageData's underlying data is not alpha-premultiplied.
|
||||
const auto alphaType = gfxAlphaType::NonPremult;
|
||||
const uint32_t BYTES_PER_PIXEL = BytesPerPixel(FORMAT);
|
||||
const uint32_t imageWidth = aImageData.Width();
|
||||
const uint32_t imageHeight = aImageData.Height();
|
||||
@ -964,8 +963,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
|
||||
}
|
||||
|
||||
// Create an ImageBimtap.
|
||||
// ImageData's underlying data is not alpha-premultiplied.
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, alphaType);
|
||||
|
||||
// Report memory allocation.
|
||||
RegisterAllocation(aGlobal, data);
|
||||
@ -1035,7 +1033,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap,
|
||||
}
|
||||
|
||||
RefPtr<layers::Image> data = aImageBitmap.mData;
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mIsPremultipliedAlpha);
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mAlphaType);
|
||||
|
||||
// Set the picture rectangle.
|
||||
if (ret && aCropRect.isSome()) {
|
||||
@ -1499,12 +1497,12 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
||||
uint32_t picRectY_;
|
||||
uint32_t picRectWidth_;
|
||||
uint32_t picRectHeight_;
|
||||
uint32_t isPremultipliedAlpha_;
|
||||
uint32_t alphaType_;
|
||||
uint32_t isCroppingAreaOutSideOfSourceImage_;
|
||||
|
||||
if (!JS_ReadUint32Pair(aReader, &picRectX_, &picRectY_) ||
|
||||
!JS_ReadUint32Pair(aReader, &picRectWidth_, &picRectHeight_) ||
|
||||
!JS_ReadUint32Pair(aReader, &isPremultipliedAlpha_,
|
||||
!JS_ReadUint32Pair(aReader, &alphaType_,
|
||||
&isCroppingAreaOutSideOfSourceImage_)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1513,6 +1511,7 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
||||
int32_t picRectY = BitwiseCast<int32_t>(picRectY_);
|
||||
int32_t picRectWidth = BitwiseCast<int32_t>(picRectWidth_);
|
||||
int32_t picRectHeight = BitwiseCast<int32_t>(picRectHeight_);
|
||||
const auto alphaType = BitwiseCast<gfxAlphaType>(alphaType_);
|
||||
|
||||
// Create a new ImageBitmap.
|
||||
MOZ_ASSERT(!aClonedSurfaces.IsEmpty());
|
||||
@ -1526,8 +1525,7 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
{
|
||||
RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]);
|
||||
RefPtr<ImageBitmap> imageBitmap =
|
||||
new ImageBitmap(aParent, img, isPremultipliedAlpha_);
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aParent, img, alphaType);
|
||||
|
||||
imageBitmap->mIsCroppingAreaOutSideOfSourceImage =
|
||||
isCroppingAreaOutSideOfSourceImage_;
|
||||
@ -1563,7 +1561,7 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
||||
const uint32_t picRectY = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.y);
|
||||
const uint32_t picRectWidth = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.width);
|
||||
const uint32_t picRectHeight = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.height);
|
||||
const uint32_t isPremultipliedAlpha = aImageBitmap->mIsPremultipliedAlpha ? 1 : 0;
|
||||
const uint32_t alphaType = BitwiseCast<uint32_t>(aImageBitmap->mAlphaType);
|
||||
const uint32_t isCroppingAreaOutSideOfSourceImage = aImageBitmap->mIsCroppingAreaOutSideOfSourceImage ? 1 : 0;
|
||||
|
||||
// Indexing the cloned surfaces and send the index to the receiver.
|
||||
@ -1572,7 +1570,7 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
||||
if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEBITMAP, index)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectX, picRectY)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectWidth, picRectHeight)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isPremultipliedAlpha,
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, alphaType,
|
||||
isCroppingAreaOutSideOfSourceImage))) {
|
||||
return false;
|
||||
}
|
||||
@ -2135,7 +2133,8 @@ ImageBitmap::Create(nsIGlobalObject* aGlobal,
|
||||
|
||||
// Create an ImageBimtap.
|
||||
// Assume the data from an external buffer is not alpha-premultiplied.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, false);
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data,
|
||||
gfxAlphaType::NonPremult);
|
||||
|
||||
// Report memory allocation.
|
||||
RegisterAllocation(aGlobal, data);
|
||||
|
@ -63,7 +63,7 @@ struct ImageBitmapCloneData final
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> mSurface;
|
||||
gfx::IntRect mPictureRect;
|
||||
bool mIsPremultipliedAlpha;
|
||||
gfxAlphaType mAlphaType;
|
||||
bool mIsCroppingAreaOutSideOfSourceImage;
|
||||
};
|
||||
|
||||
@ -200,7 +200,7 @@ protected:
|
||||
* CreateInternal(from ImageData) method.
|
||||
*/
|
||||
ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||
bool aIsPremultipliedAlpha = true);
|
||||
gfxAlphaType aAlphaType = gfxAlphaType::Premult);
|
||||
|
||||
virtual ~ImageBitmap();
|
||||
|
||||
@ -272,7 +272,7 @@ protected:
|
||||
*/
|
||||
gfx::IntRect mPictureRect;
|
||||
|
||||
const bool mIsPremultipliedAlpha;
|
||||
const gfxAlphaType mAlphaType;
|
||||
|
||||
/*
|
||||
* Set mIsCroppingAreaOutSideOfSourceImage if image bitmap was cropped to the
|
||||
|
@ -182,14 +182,14 @@ ImageBitmapRenderingContext::GetInputStream(const char* aMimeType,
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
ImageBitmapRenderingContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
||||
ImageBitmapRenderingContext::GetSurfaceSnapshot(gfxAlphaType* const aOutAlphaType)
|
||||
{
|
||||
if (!mImage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aPremultAlpha) {
|
||||
*aPremultAlpha = true;
|
||||
if (aOutAlphaType) {
|
||||
*aOutAlphaType = (GetIsOpaque() ? gfxAlphaType::Opaque : gfxAlphaType::Premult);
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
nsIInputStream** aStream) override;
|
||||
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) override;
|
||||
GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType) override;
|
||||
|
||||
NS_IMETHOD SetIsOpaque(bool aIsOpaque) override;
|
||||
virtual bool GetIsOpaque() override;
|
||||
|
@ -302,13 +302,13 @@ OffscreenCanvas::ToBlob(JSContext* aCx,
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
OffscreenCanvas::GetSurfaceSnapshot(bool* aPremultAlpha)
|
||||
OffscreenCanvas::GetSurfaceSnapshot(gfxAlphaType* const aOutAlphaType)
|
||||
{
|
||||
if (!mCurrentContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mCurrentContext->GetSurfaceSnapshot(aPremultAlpha);
|
||||
return mCurrentContext->GetSurfaceSnapshot(aOutAlphaType);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject>
|
||||
|
@ -124,7 +124,7 @@ public:
|
||||
return mCurrentContext;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr);
|
||||
already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType = nullptr);
|
||||
|
||||
static already_AddRefed<OffscreenCanvas>
|
||||
CreateFromCloneData(nsIGlobalObject* aGlobal, OffscreenCanvasCloneData* aData);
|
||||
|
@ -270,7 +270,7 @@ FallbackOnZero(uint32_t val, uint32_t fallback)
|
||||
|
||||
TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t rowLength, uint32_t width, uint32_t height,
|
||||
uint32_t depth, bool srcIsPremult)
|
||||
uint32_t depth, gfxAlphaType srcAlphaType)
|
||||
: mAlignment(webgl->mPixelStore_UnpackAlignment)
|
||||
, mRowLength(rowLength)
|
||||
, mImageHeight(FallbackOnZero(ZeroOn2D(target, webgl->mPixelStore_UnpackImageHeight),
|
||||
@ -284,7 +284,7 @@ TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
|
||||
, mHeight(height)
|
||||
, mDepth(depth)
|
||||
|
||||
, mSrcIsPremult(srcIsPremult)
|
||||
, mSrcAlphaType(srcAlphaType)
|
||||
|
||||
, mNeedsExactUpload(false)
|
||||
{
|
||||
@ -327,7 +327,18 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
|
||||
if (!rowLength || !rowCount)
|
||||
return true;
|
||||
|
||||
const auto srcIsPremult = (mSrcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = webgl->mPixelStore_PremultiplyAlpha;
|
||||
const auto fnHasPremultMismatch = [&]() {
|
||||
if (mSrcAlphaType == gfxAlphaType::Opaque)
|
||||
return false;
|
||||
|
||||
if (!HasColorAndAlpha(srcFormat))
|
||||
return false;
|
||||
|
||||
return srcIsPremult != dstIsPremult;
|
||||
};
|
||||
|
||||
const auto srcOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
|
||||
: gl::OriginPos::BottomLeft);
|
||||
const auto dstOrigin = gl::OriginPos::BottomLeft;
|
||||
@ -336,7 +347,7 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
|
||||
webgl->GeneratePerfWarning("%s: Conversion requires pixel reformatting. (%u->%u)",
|
||||
funcName, uint32_t(srcFormat),
|
||||
uint32_t(dstFormat));
|
||||
} else if (mSrcIsPremult != dstIsPremult && HasColorAndAlpha(srcFormat)) {
|
||||
} else if (fnHasPremultMismatch()) {
|
||||
webgl->GeneratePerfWarning("%s: Conversion requires change in"
|
||||
" alpha-premultiplication.",
|
||||
funcName);
|
||||
@ -369,7 +380,7 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
|
||||
// And go!:
|
||||
bool wasTrivial;
|
||||
if (!ConvertImage(rowLength, rowCount,
|
||||
srcBegin, srcStride, srcOrigin, srcFormat, mSrcIsPremult,
|
||||
srcBegin, srcStride, srcOrigin, srcFormat, srcIsPremult,
|
||||
dstBegin, dstStride, dstOrigin, dstFormat, dstIsPremult,
|
||||
&wasTrivial))
|
||||
{
|
||||
@ -403,7 +414,7 @@ TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target,
|
||||
bool isClientData, const uint8_t* ptr, size_t availBytes)
|
||||
: TexUnpackBlob(webgl, target,
|
||||
FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width),
|
||||
width, height, depth, false)
|
||||
width, height, depth, gfxAlphaType::NonPremult)
|
||||
, mIsClientData(isClientData)
|
||||
, mPtr(ptr)
|
||||
, mAvailBytes(availBytes)
|
||||
@ -578,9 +589,9 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
|
||||
TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
layers::Image* image, bool isAlphaPremult)
|
||||
layers::Image* image, gfxAlphaType srcAlphaType)
|
||||
: TexUnpackBlob(webgl, target, image->GetSize().width, width, height, depth,
|
||||
isAlphaPremult)
|
||||
srcAlphaType)
|
||||
, mImage(image)
|
||||
{ }
|
||||
|
||||
@ -626,15 +637,32 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& dstIsPremult = webgl->mPixelStore_PremultiplyAlpha;
|
||||
if (mSrcIsPremult != dstIsPremult) {
|
||||
if (webgl->mPixelStore_UnpackSkipPixels ||
|
||||
webgl->mPixelStore_UnpackSkipRows ||
|
||||
webgl->mPixelStore_UnpackSkipImages)
|
||||
{
|
||||
fallbackReason = "non-zero UNPACK_SKIP_* not yet supported";
|
||||
break;
|
||||
}
|
||||
|
||||
const auto fnHasPremultMismatch = [&]() {
|
||||
if (mSrcAlphaType == gfxAlphaType::Opaque)
|
||||
return false;
|
||||
|
||||
const bool srcIsPremult = (mSrcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = webgl->mPixelStore_PremultiplyAlpha;
|
||||
if (srcIsPremult == dstIsPremult)
|
||||
return false;
|
||||
|
||||
if (dstIsPremult) {
|
||||
fallbackReason = "UNPACK_PREMULTIPLY_ALPHA_WEBGL is not true";
|
||||
} else {
|
||||
fallbackReason = "UNPACK_PREMULTIPLY_ALPHA_WEBGL is not false";
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (fnHasPremultMismatch())
|
||||
break;
|
||||
}
|
||||
|
||||
if (dui->unpackFormat != LOCAL_GL_RGB && dui->unpackFormat != LOCAL_GL_RGBA) {
|
||||
fallbackReason = "`format` is not RGB or RGBA";
|
||||
@ -701,7 +729,7 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
}
|
||||
|
||||
const TexUnpackSurface surfBlob(webgl, target, mWidth, mHeight, mDepth, dataSurf,
|
||||
mSrcIsPremult);
|
||||
mSrcAlphaType);
|
||||
|
||||
return surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level,
|
||||
dui, xOffset, yOffset, zOffset, out_error);
|
||||
@ -713,9 +741,10 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
|
||||
TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
gfx::DataSourceSurface* surf, bool isAlphaPremult)
|
||||
gfx::DataSourceSurface* surf,
|
||||
gfxAlphaType srcAlphaType)
|
||||
: TexUnpackBlob(webgl, target, surf->GetSize().width, width, height, depth,
|
||||
isAlphaPremult)
|
||||
srcAlphaType)
|
||||
, mSurf(surf)
|
||||
{ }
|
||||
|
||||
|
@ -51,13 +51,14 @@ public:
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mDepth;
|
||||
|
||||
const bool mSrcIsPremult;
|
||||
const gfxAlphaType mSrcAlphaType;
|
||||
|
||||
bool mNeedsExactUpload;
|
||||
|
||||
protected:
|
||||
TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target, uint32_t rowLength,
|
||||
uint32_t width, uint32_t height, uint32_t depth, bool isSrcPremult);
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
gfxAlphaType srcAlphaType);
|
||||
|
||||
public:
|
||||
virtual ~TexUnpackBlob() { }
|
||||
@ -117,7 +118,7 @@ public:
|
||||
|
||||
TexUnpackImage(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
|
||||
uint32_t height, uint32_t depth, layers::Image* image,
|
||||
bool isAlphaPremult);
|
||||
gfxAlphaType srcAlphaType);
|
||||
|
||||
~TexUnpackImage(); // Prevent needing to define layers::Image in the header.
|
||||
|
||||
@ -137,7 +138,7 @@ public:
|
||||
|
||||
TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
|
||||
uint32_t height, uint32_t depth, gfx::DataSourceSurface* surf,
|
||||
bool isAlphaPremult);
|
||||
gfxAlphaType srcAlphaType);
|
||||
|
||||
virtual bool Validate(WebGLContext* webgl, const char* funcName,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
|
@ -1247,14 +1247,10 @@ WebGLContext::GetImageBuffer(int32_t* out_format)
|
||||
*out_format = 0;
|
||||
|
||||
// Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
|
||||
bool premult;
|
||||
RefPtr<SourceSurface> snapshot =
|
||||
GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
|
||||
if (!snapshot) {
|
||||
gfxAlphaType any;
|
||||
RefPtr<SourceSurface> snapshot = GetSurfaceSnapshot(&any);
|
||||
if (!snapshot)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
|
||||
|
||||
@ -1272,14 +1268,11 @@ WebGLContext::GetInputStream(const char* mimeType,
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
|
||||
bool premult;
|
||||
RefPtr<SourceSurface> snapshot =
|
||||
GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
|
||||
gfxAlphaType any;
|
||||
RefPtr<SourceSurface> snapshot = GetSurfaceSnapshot(&any);
|
||||
if (!snapshot)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
|
||||
return gfxUtils::GetInputStream(dataSurface, mOptions.premultipliedAlpha, mimeType,
|
||||
encoderOptions, out_stream);
|
||||
@ -1934,21 +1927,19 @@ WebGLContext::MakeContextCurrent() const
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha)
|
||||
WebGLContext::GetSurfaceSnapshot(gfxAlphaType* const out_alphaType)
|
||||
{
|
||||
if (!gl)
|
||||
return nullptr;
|
||||
|
||||
bool hasAlpha = mOptions.alpha;
|
||||
SurfaceFormat surfFormat = hasAlpha ? SurfaceFormat::B8G8R8A8
|
||||
: SurfaceFormat::B8G8R8X8;
|
||||
const auto surfFormat = mOptions.alpha ? SurfaceFormat::B8G8R8A8
|
||||
: SurfaceFormat::B8G8R8X8;
|
||||
RefPtr<DataSourceSurface> surf;
|
||||
surf = Factory::CreateDataSourceSurfaceWithStride(IntSize(mWidth, mHeight),
|
||||
surfFormat,
|
||||
mWidth * 4);
|
||||
if (NS_WARN_IF(!surf)) {
|
||||
if (NS_WARN_IF(!surf))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gl->MakeCurrent();
|
||||
{
|
||||
@ -1968,15 +1959,22 @@ WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha)
|
||||
}
|
||||
}
|
||||
|
||||
if (out_premultAlpha) {
|
||||
*out_premultAlpha = true;
|
||||
gfxAlphaType alphaType;
|
||||
if (!mOptions.alpha) {
|
||||
alphaType = gfxAlphaType::Opaque;
|
||||
} else if (mOptions.premultipliedAlpha) {
|
||||
alphaType = gfxAlphaType::Premult;
|
||||
} else {
|
||||
alphaType = gfxAlphaType::NonPremult;
|
||||
}
|
||||
bool srcPremultAlpha = mOptions.premultipliedAlpha;
|
||||
if (!srcPremultAlpha) {
|
||||
if (out_premultAlpha) {
|
||||
*out_premultAlpha = false;
|
||||
} else if(hasAlpha) {
|
||||
|
||||
if (out_alphaType) {
|
||||
*out_alphaType = alphaType;
|
||||
} else {
|
||||
// Expects Opaque or Premult
|
||||
if (alphaType == gfxAlphaType::NonPremult) {
|
||||
gfxUtils::PremultiplyDataSurface(surf, surf);
|
||||
alphaType = gfxAlphaType::Premult;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1984,10 +1982,8 @@ WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha)
|
||||
Factory::CreateDrawTarget(gfxPlatform::GetPlatform()->GetSoftwareBackend(),
|
||||
IntSize(mWidth, mHeight),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
|
||||
if (!dt) {
|
||||
if (!dt)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dt->SetTransform(Matrix::Translation(0.0, mHeight).PreScale(1.0, -1.0));
|
||||
|
||||
|
@ -375,8 +375,8 @@ public:
|
||||
const char16_t* encoderOptions,
|
||||
nsIInputStream** out_stream) override;
|
||||
|
||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(bool* out_premultAlpha) override;
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(gfxAlphaType* out_alphaType) override;
|
||||
|
||||
NS_IMETHOD SetIsOpaque(bool) override { return NS_OK; };
|
||||
bool GetIsOpaque() override { return false; }
|
||||
|
@ -220,8 +220,6 @@ FromImageBitmap(WebGLContext* webgl, const char* funcName, TexImageTarget target
|
||||
UniquePtr<dom::ImageBitmapCloneData> cloneData = Move(imageBitmap.ToCloneData());
|
||||
const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface;
|
||||
|
||||
////
|
||||
|
||||
if (!width) {
|
||||
width = surf->GetSize().width;
|
||||
}
|
||||
@ -230,15 +228,11 @@ FromImageBitmap(WebGLContext* webgl, const char* funcName, TexImageTarget target
|
||||
height = surf->GetSize().height;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const bool isAlphaPremult = cloneData->mIsPremultipliedAlpha;
|
||||
return MakeUnique<webgl::TexUnpackSurface>(webgl, target, width, height, depth, surf,
|
||||
isAlphaPremult);
|
||||
cloneData->mAlphaType);
|
||||
}
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBlob>
|
||||
@ -257,6 +251,11 @@ FromImageData(WebGLContext* webgl, const char* funcName, TexImageTarget target,
|
||||
const size_t stride = size.width * 4;
|
||||
const gfx::SurfaceFormat surfFormat = gfx::SurfaceFormat::R8G8B8A8;
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const auto alphaType = gfxAlphaType::NonPremult;
|
||||
|
||||
MOZ_ASSERT(dataSize == stride * size.height);
|
||||
|
||||
uint8_t* wrappableData = (uint8_t*)data;
|
||||
@ -281,12 +280,8 @@ FromImageData(WebGLContext* webgl, const char* funcName, TexImageTarget target,
|
||||
|
||||
////
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const bool isAlphaPremult = false;
|
||||
return MakeUnique<webgl::TexUnpackSurface>(webgl, target, width, height, depth, surf,
|
||||
isAlphaPremult);
|
||||
alphaType);
|
||||
}
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob>
|
||||
@ -294,7 +289,11 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t
|
||||
uint32_t height, uint32_t depth, const dom::Element& elem,
|
||||
ErrorResult* const out_error)
|
||||
{
|
||||
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
|
||||
// The canvas spec says that drawImage should draw the first frame of
|
||||
// animated images. The webgl spec doesn't mention the issue, so we do the
|
||||
// same as drawImage.
|
||||
uint32_t flags = nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE |
|
||||
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
|
||||
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
|
||||
|
||||
if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
|
||||
@ -375,16 +374,14 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t
|
||||
//////
|
||||
// Ok, we're good!
|
||||
|
||||
const bool isAlphaPremult = sfer.mIsPremultiplied;
|
||||
|
||||
if (layersImage) {
|
||||
return MakeUnique<webgl::TexUnpackImage>(this, target, width, height, depth,
|
||||
layersImage, isAlphaPremult);
|
||||
layersImage, sfer.mAlphaType);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(dataSurf);
|
||||
return MakeUnique<webgl::TexUnpackSurface>(this, target, width, height, depth,
|
||||
dataSurf, isAlphaPremult);
|
||||
dataSurf, sfer.mAlphaType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
@ -119,7 +119,8 @@ public:
|
||||
// If premultAlpha is provided, then it assumed the callee can handle
|
||||
// un-premultiplied surfaces, and *premultAlpha will be set to false
|
||||
// if one is returned.
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* premultAlpha = nullptr) = 0;
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(gfxAlphaType* out_alphaType = nullptr) = 0;
|
||||
|
||||
// If this context is opaque, the backing store of the canvas should
|
||||
// be created as opaque; all compositing operators should assume the
|
||||
|
@ -88,7 +88,7 @@ InternalHeaders::Get(const nsACString& aName, nsACString& aValue, ErrorResult& a
|
||||
return;
|
||||
}
|
||||
|
||||
const char* delimiter = ",";
|
||||
const char* delimiter = ", ";
|
||||
bool firstValueFound = false;
|
||||
|
||||
for (uint32_t i = 0; i < mList.Length(); ++i) {
|
||||
|
@ -1308,12 +1308,12 @@ HTMLCanvasElement::SetFrameCapture(already_AddRefed<SourceSurface> aSurface,
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
HTMLCanvasElement::GetSurfaceSnapshot(bool* aPremultAlpha)
|
||||
HTMLCanvasElement::GetSurfaceSnapshot(gfxAlphaType* const aOutAlphaType)
|
||||
{
|
||||
if (!mCurrentContext)
|
||||
return nullptr;
|
||||
|
||||
return mCurrentContext->GetSurfaceSnapshot(aPremultAlpha);
|
||||
return mCurrentContext->GetSurfaceSnapshot(aOutAlphaType);
|
||||
}
|
||||
|
||||
AsyncCanvasRenderer*
|
||||
|
@ -254,7 +254,8 @@ public:
|
||||
bool GetIsOpaque();
|
||||
virtual bool GetOpaqueAttr() override;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr);
|
||||
virtual already_AddRefed<gfx::SourceSurface>
|
||||
GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType = nullptr);
|
||||
|
||||
/*
|
||||
* Register a FrameCaptureListener with this canvas.
|
||||
|
@ -1454,12 +1454,6 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
[optional] out unsigned long frameCount,
|
||||
[retval, array, size_is(frameCount)] out float frameIntervals);
|
||||
|
||||
/**
|
||||
* Signals that we're begining to tab switch. This is used by painting code to
|
||||
* determine total tab switch time.
|
||||
*/
|
||||
void beginTabSwitch();
|
||||
|
||||
/**
|
||||
* The DPI of the display
|
||||
*/
|
||||
|
@ -77,6 +77,7 @@ ContentBridgeChild::SendPMemoryStreamConstructor(const uint64_t& aSize)
|
||||
bool
|
||||
ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -84,6 +85,7 @@ ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
{
|
||||
return PContentBridgeChild::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
@ -128,12 +130,14 @@ ContentBridgeChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
|
||||
|
||||
PBrowserChild*
|
||||
ContentBridgeChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentChild::AllocPBrowserChild(aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
@ -149,6 +153,7 @@ ContentBridgeChild::DeallocPBrowserChild(PBrowserChild* aChild)
|
||||
mozilla::ipc::IPCResult
|
||||
ContentBridgeChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -156,6 +161,7 @@ ContentBridgeChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
{
|
||||
return nsIContentChild::RecvPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -67,6 +68,7 @@ protected:
|
||||
virtual ~ContentBridgeChild();
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -74,6 +76,7 @@ protected:
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*) override;
|
||||
virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(PBrowserChild* aCctor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
|
@ -98,6 +98,7 @@ ContentBridgeParent::SendPBlobConstructor(PBlobParent* actor,
|
||||
PBrowserParent*
|
||||
ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -105,6 +106,7 @@ ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
{
|
||||
return PContentBridgeParent::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
@ -155,12 +157,14 @@ ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
|
||||
|
||||
PBrowserParent*
|
||||
ContentBridgeParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentParent::AllocPBrowserParent(aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
virtual PBrowserParent*
|
||||
SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -124,6 +125,7 @@ protected:
|
||||
|
||||
virtual PBrowserParent*
|
||||
AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext &aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
|
@ -776,18 +776,6 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
|
||||
GetID(),
|
||||
&tabId);
|
||||
|
||||
TabContext newTabContext = aTabOpener ? *aTabOpener : TabContext();
|
||||
RefPtr<TabChild> newChild = new TabChild(this, tabId,
|
||||
newTabContext, aChromeFlags);
|
||||
if (NS_FAILED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (aTabOpener) {
|
||||
MOZ_ASSERT(ipcContext->type() == IPCTabContext::TPopupIPCTabContext);
|
||||
ipcContext->get_PopupIPCTabContext().opener() = aTabOpener;
|
||||
}
|
||||
|
||||
// We need to assign a TabGroup to the PBrowser actor before we send it to the
|
||||
// parent. Otherwise, the parent could send messages to us before we have a
|
||||
// proper TabGroup for that actor.
|
||||
@ -798,13 +786,26 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
|
||||
} else {
|
||||
tabGroup = new TabGroup();
|
||||
}
|
||||
|
||||
TabContext newTabContext = aTabOpener ? *aTabOpener : TabContext();
|
||||
RefPtr<TabChild> newChild = new TabChild(this, tabId, tabGroup,
|
||||
newTabContext, aChromeFlags);
|
||||
if (NS_FAILED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (aTabOpener) {
|
||||
MOZ_ASSERT(ipcContext->type() == IPCTabContext::TPopupIPCTabContext);
|
||||
ipcContext->get_PopupIPCTabContext().opener() = aTabOpener;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = tabGroup->EventTargetFor(TaskCategory::Other);
|
||||
SetEventTargetForActor(newChild, target);
|
||||
|
||||
Unused << SendPBrowserConstructor(
|
||||
// We release this ref in DeallocPBrowserChild
|
||||
RefPtr<TabChild>(newChild).forget().take(),
|
||||
tabId, *ipcContext, aChromeFlags,
|
||||
tabId, TabId(0), *ipcContext, aChromeFlags,
|
||||
GetID(), IsForBrowser());
|
||||
|
||||
nsString name(aName);
|
||||
@ -1442,12 +1443,14 @@ ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *aChild)
|
||||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentChild::AllocPBrowserChild(aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
@ -1457,6 +1460,7 @@ ContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
bool
|
||||
ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -1468,6 +1472,7 @@ ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
|
||||
return PContentChild::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
@ -1477,6 +1482,7 @@ ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -1493,8 +1499,13 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
NS_IdleDispatchToCurrentThread(firstIdleTask.forget());
|
||||
}
|
||||
|
||||
return nsIContentChild::RecvPBrowserConstructor(aActor, aTabId, aContext,
|
||||
aChromeFlags, aCpID, aIsForBrowser);
|
||||
return nsIContentChild::RecvPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpID,
|
||||
aIsForBrowser);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3171,6 +3182,32 @@ ContentChild::GetConstructedEventTarget(const Message& aMsg)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ActorHandle handle;
|
||||
TabId tabId, sameTabGroupAs;
|
||||
PickleIterator iter(aMsg);
|
||||
if (!IPC::ReadParam(&aMsg, &iter, &handle)) {
|
||||
return nullptr;
|
||||
}
|
||||
aMsg.IgnoreSentinel(&iter);
|
||||
if (!IPC::ReadParam(&aMsg, &iter, &tabId)) {
|
||||
return nullptr;
|
||||
}
|
||||
aMsg.IgnoreSentinel(&iter);
|
||||
if (!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If sameTabGroupAs is non-zero, then the new tab will be in the same
|
||||
// TabGroup as a previously created tab. Rather than try to find the
|
||||
// previously created tab (whose constructor message may not even have been
|
||||
// processed yet, in theory) and look up its event target, we just use the
|
||||
// default event target. This means that runnables for this tab will not be
|
||||
// labeled. However, this path is only taken for print preview and view
|
||||
// source, which are not performance-sensitive.
|
||||
if (sameTabGroupAs) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If the request for a new TabChild is coming from the parent process, then
|
||||
// there is no opener. Therefore, we create a fresh TabGroup.
|
||||
RefPtr<TabGroup> tabGroup = new TabGroup();
|
||||
|
@ -170,6 +170,7 @@ public:
|
||||
virtual mozilla::ipc::IPCResult RecvSetProcessSandbox(const MaybeFileDesc& aBroker) override;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -509,6 +510,7 @@ public:
|
||||
|
||||
virtual bool SendPBrowserConstructor(PBrowserChild* actor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -516,6 +518,7 @@ public:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(PBrowserChild* aCctor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
|
@ -1162,7 +1162,8 @@ ContentParent::RecvFindPlugins(const uint32_t& aPluginEpoch,
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowser(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
ContentParent* aOpenerContentParent)
|
||||
ContentParent* aOpenerContentParent,
|
||||
TabParent* aSameTabGroupAs)
|
||||
{
|
||||
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
|
||||
|
||||
@ -1243,6 +1244,7 @@ ContentParent::CreateBrowser(const TabContext& aContext,
|
||||
constructorSender->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases this ref.
|
||||
tp.forget().take(), tabId,
|
||||
aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
|
||||
aContext.AsIPCTabContext(),
|
||||
chromeFlags,
|
||||
constructorSender->ChildID(),
|
||||
@ -2802,12 +2804,14 @@ ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
|
||||
|
||||
PBrowserParent*
|
||||
ContentParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
return nsIContentParent::AllocPBrowserParent(aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpId,
|
||||
@ -3844,6 +3848,7 @@ ContentParent::SendPBlobConstructor(PBlobParent* aActor,
|
||||
PBrowserParent*
|
||||
ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
@ -3851,6 +3856,7 @@ ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
|
||||
{
|
||||
return PContentParent::SendPBrowserConstructor(aActor,
|
||||
aTabId,
|
||||
aSameTabGroupAs,
|
||||
aContext,
|
||||
aChromeFlags,
|
||||
aCpId,
|
||||
|
@ -188,7 +188,8 @@ public:
|
||||
static TabParent*
|
||||
CreateBrowser(const TabContext& aContext,
|
||||
Element* aFrameElement,
|
||||
ContentParent* aOpenerContentParent);
|
||||
ContentParent* aOpenerContentParent,
|
||||
TabParent* aSameTabGroupAs);
|
||||
|
||||
static void GetAll(nsTArray<ContentParent*>& aArray);
|
||||
|
||||
@ -699,6 +700,7 @@ private:
|
||||
virtual PBrowserParent* SendPBrowserConstructor(
|
||||
PBrowserParent* actor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupsAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
@ -831,6 +833,7 @@ private:
|
||||
DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) override;
|
||||
|
||||
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
|
@ -325,8 +325,13 @@ both:
|
||||
// type PopupIPCTabContext. The parent checks that if the opener is a
|
||||
// browser element, the context is also for a browser element.
|
||||
//
|
||||
// If |sameTabGroupAs| is non-zero, the new tab should go in the same
|
||||
// TabGroup as |sameTabGroupAs|. This parameter should always be zero
|
||||
// for PBrowser messages sent from the child to the parent.
|
||||
//
|
||||
// Keep the last 3 attributes in sync with GetProcessAttributes!
|
||||
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
|
||||
async PBrowser(TabId tabId, TabId sameTabGroupAs,
|
||||
IPCTabContext context, uint32_t chromeFlags,
|
||||
ContentParentId cpId, bool isForBrowser);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
@ -71,7 +71,8 @@ parent:
|
||||
both:
|
||||
// Both the parent and the child can construct the PBrowser.
|
||||
// See the comment in PContent::PBrowser().
|
||||
async PBrowser(TabId tabId, IPCTabContext context, uint32_t chromeFlags,
|
||||
async PBrowser(TabId tabId, TabId sameTabGroupAs,
|
||||
IPCTabContext context, uint32_t chromeFlags,
|
||||
ContentParentId cpId, bool isForBrowser);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
@ -356,19 +356,24 @@ TabChild::FindTabChild(const TabId& aTabId)
|
||||
/*static*/ already_AddRefed<TabChild>
|
||||
TabChild::Create(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const TabContext &aContext,
|
||||
uint32_t aChromeFlags)
|
||||
{
|
||||
RefPtr<TabChild> iframe = new TabChild(aManager, aTabId,
|
||||
aContext, aChromeFlags);
|
||||
return iframe.forget();
|
||||
RefPtr<TabChild> groupChild = FindTabChild(aSameTabGroupAs);
|
||||
dom::TabGroup* group = groupChild ? groupChild->TabGroup() : nullptr;
|
||||
RefPtr<TabChild> iframe = new TabChild(aManager, aTabId, group,
|
||||
aContext, aChromeFlags);
|
||||
return iframe.forget();
|
||||
}
|
||||
|
||||
TabChild::TabChild(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
dom::TabGroup* aTabGroup,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags)
|
||||
: TabContext(aContext)
|
||||
, mTabGroup(aTabGroup)
|
||||
, mRemoteFrame(nullptr)
|
||||
, mManager(aManager)
|
||||
, mChromeFlags(aChromeFlags)
|
||||
@ -566,6 +571,10 @@ TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
|
||||
nsresult
|
||||
TabChild::Init()
|
||||
{
|
||||
if (!mTabGroup) {
|
||||
mTabGroup = TabGroup::GetFromActor(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
|
||||
if (!webBrowser) {
|
||||
NS_ERROR("Couldn't create a nsWebBrowser?");
|
||||
@ -2657,9 +2666,6 @@ TabChild::InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIden
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache the TabGroup so it can be fetched off the main thread.
|
||||
TabGroup();
|
||||
|
||||
MOZ_ASSERT(aLayersId != 0);
|
||||
mTextureFactoryIdentifier = aTextureFactoryIdentifier;
|
||||
|
||||
@ -3344,14 +3350,6 @@ TabChildSHistoryListener::SHistoryDidUpdate(bool aTruncate /* = false */)
|
||||
mozilla::dom::TabGroup*
|
||||
TabChild::TabGroup()
|
||||
{
|
||||
if (mTabGroup) {
|
||||
return mTabGroup;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
|
||||
MOZ_ASSERT(window);
|
||||
mTabGroup = window->TabGroup();
|
||||
return mTabGroup;
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,7 @@ public:
|
||||
*/
|
||||
TabChild(nsIContentChild* aManager,
|
||||
const TabId& aTabId,
|
||||
TabGroup* aTabGroup,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags);
|
||||
|
||||
@ -286,6 +287,7 @@ public:
|
||||
/** Return a TabChild with the given attributes. */
|
||||
static already_AddRefed<TabChild>
|
||||
Create(nsIContentChild* aManager, const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const TabContext& aContext, uint32_t aChromeFlags);
|
||||
|
||||
// Let managees query if it is safe to send messages.
|
||||
|
@ -46,6 +46,7 @@ nsIContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild)
|
||||
|
||||
PBrowserChild*
|
||||
nsIContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -64,7 +65,8 @@ nsIContentChild::AllocPBrowserChild(const TabId& aTabId,
|
||||
}
|
||||
|
||||
RefPtr<TabChild> child =
|
||||
TabChild::Create(this, aTabId, tc.GetTabContext(), aChromeFlags);
|
||||
TabChild::Create(this, aTabId, aSameTabGroupAs,
|
||||
tc.GetTabContext(), aChromeFlags);
|
||||
|
||||
// The ref here is released in DeallocPBrowserChild.
|
||||
return child.forget().take();
|
||||
@ -81,6 +83,7 @@ nsIContentChild::DeallocPBrowserChild(PBrowserChild* aIframe)
|
||||
mozilla::ipc::IPCResult
|
||||
nsIContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
virtual bool
|
||||
SendPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
@ -86,6 +87,7 @@ protected:
|
||||
virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
@ -94,6 +96,7 @@ protected:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(PBrowserChild* aActor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpID,
|
||||
|
@ -121,11 +121,14 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
||||
|
||||
PBrowserParent*
|
||||
nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
const bool& aIsForBrowser)
|
||||
{
|
||||
MOZ_ASSERT(!aSameTabGroupAs);
|
||||
|
||||
Unused << aCpId;
|
||||
Unused << aIsForBrowser;
|
||||
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
MOZ_MUST_USE virtual PBrowserParent*
|
||||
SendPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& aTabId,
|
||||
const TabId& aSameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
@ -112,6 +113,7 @@ protected: // IPDL methods
|
||||
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
|
||||
|
||||
virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
|
||||
const TabId& aSameTabGroupsAs,
|
||||
const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags,
|
||||
const ContentParentId& aCpId,
|
||||
|
@ -77,12 +77,12 @@ function TestCoreBehavior(headers, name) {
|
||||
headers.append(name, "bar");
|
||||
|
||||
checkHas(headers, name, "Has the header");
|
||||
var expected = (start ? start.concat(",bar") : "bar");
|
||||
var expected = (start ? start.concat(", bar") : "bar");
|
||||
checkGet(headers, name, expected, "Retrieve all headers for name");
|
||||
|
||||
headers.append(name, "baz");
|
||||
checkHas(headers, name, "Has the header");
|
||||
expected = (start ? start.concat(",bar,baz") : "bar,baz");
|
||||
expected = (start ? start.concat(", bar, baz") : "bar, baz");
|
||||
checkGet(headers, name, expected, "Retrieve all headers for name");
|
||||
|
||||
headers.set(name, "snafu");
|
||||
@ -151,7 +151,7 @@ function TestFilledHeaders() {
|
||||
["uts", "321"]
|
||||
]);
|
||||
checkGet(filled, "zxy", "987", "Has first sequence filled key");
|
||||
checkGet(filled, "xwv", "654,abc", "Has second sequence filled key");
|
||||
checkGet(filled, "xwv", "654, abc", "Has second sequence filled key");
|
||||
checkGet(filled, "uts", "321", "Has third sequence filled key");
|
||||
TestCoreBehavior(filled, "xwv");
|
||||
|
||||
|
@ -756,9 +756,13 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage)
|
||||
mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]);
|
||||
}
|
||||
BindAndUploadYUVTexture(Channel_Y, yuvData->mYStride, yuvData->mYSize.height, yuvData->mYChannel, needsAllocation);
|
||||
BindAndUploadYUVTexture(Channel_Cb, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCbChannel, needsAllocation);
|
||||
BindAndUploadYUVTexture(Channel_Cr, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCrChannel, needsAllocation);
|
||||
|
||||
{
|
||||
const ResetUnpackState reset(mGL);
|
||||
BindAndUploadYUVTexture(Channel_Y, yuvData->mYStride, yuvData->mYSize.height, yuvData->mYChannel, needsAllocation);
|
||||
BindAndUploadYUVTexture(Channel_Cb, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCbChannel, needsAllocation);
|
||||
BindAndUploadYUVTexture(Channel_Cr, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCrChannel, needsAllocation);
|
||||
}
|
||||
|
||||
if (needsAllocation) {
|
||||
mGL->fUniform2f(mYTexScaleLoc, (float)yuvData->mYSize.width/yuvData->mYStride, 1.0f);
|
||||
@ -868,13 +872,8 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
|
||||
mGL->fViewport(0, 0, destSize.width, destSize.height);
|
||||
|
||||
switch (type) {
|
||||
case ConvertPlanarYCbCr: {
|
||||
const auto saved = mGL->GetIntAs<GLint>(LOCAL_GL_UNPACK_ALIGNMENT);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
|
||||
const auto ret = BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage));
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, saved);
|
||||
return ret;
|
||||
}
|
||||
case ConvertPlanarYCbCr:
|
||||
return BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage));
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
case ConvertSurfaceTexture:
|
||||
|
@ -530,6 +530,52 @@ ScopedPackState::UnwrapImpl()
|
||||
mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mSkipRows);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ResetUnpackState
|
||||
|
||||
ResetUnpackState::ResetUnpackState(GLContext* gl)
|
||||
: ScopedGLWrapper<ResetUnpackState>(gl)
|
||||
{
|
||||
const auto fnReset = [&](GLenum pname, GLuint val, GLuint* const out_old) {
|
||||
mGL->GetUIntegerv(pname, out_old);
|
||||
if (*out_old != val) {
|
||||
mGL->fPixelStorei(pname, val);
|
||||
}
|
||||
};
|
||||
|
||||
// Default is 4, but 1 is more useful.
|
||||
fnReset(LOCAL_GL_UNPACK_ALIGNMENT, 1, &mAlignment);
|
||||
|
||||
if (!mGL->HasPBOState())
|
||||
return;
|
||||
|
||||
mGL->GetUIntegerv(LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING, &mPBO);
|
||||
if (mPBO != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
fnReset(LOCAL_GL_UNPACK_ROW_LENGTH , 0, &mRowLength);
|
||||
fnReset(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0, &mImageHeight);
|
||||
fnReset(LOCAL_GL_UNPACK_SKIP_PIXELS , 0, &mSkipPixels);
|
||||
fnReset(LOCAL_GL_UNPACK_SKIP_ROWS , 0, &mSkipRows);
|
||||
fnReset(LOCAL_GL_UNPACK_SKIP_IMAGES , 0, &mSkipImages);
|
||||
}
|
||||
|
||||
void
|
||||
ResetUnpackState::UnwrapImpl()
|
||||
{
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mAlignment);
|
||||
|
||||
if (!mGL->HasPBOState())
|
||||
return;
|
||||
|
||||
mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPBO);
|
||||
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mImageHeight);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mSkipPixels);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mSkipRows);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mSkipImages);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ScopedBindPBO
|
||||
|
||||
|
@ -362,6 +362,28 @@ protected:
|
||||
void UnwrapImpl();
|
||||
};
|
||||
|
||||
struct ResetUnpackState
|
||||
: public ScopedGLWrapper<ResetUnpackState>
|
||||
{
|
||||
friend struct ScopedGLWrapper<ResetUnpackState>;
|
||||
|
||||
protected:
|
||||
GLuint mAlignment;
|
||||
|
||||
GLuint mPBO;
|
||||
GLuint mRowLength;
|
||||
GLuint mImageHeight;
|
||||
GLuint mSkipPixels;
|
||||
GLuint mSkipRows;
|
||||
GLuint mSkipImages;
|
||||
|
||||
public:
|
||||
explicit ResetUnpackState(GLContext* gl);
|
||||
|
||||
protected:
|
||||
void UnwrapImpl();
|
||||
};
|
||||
|
||||
struct ScopedBindPBO final
|
||||
: public ScopedGLWrapper<ScopedBindPBO>
|
||||
{
|
||||
|
@ -174,14 +174,14 @@ class MacIOSurfaceImage;
|
||||
/**
|
||||
* A class representing a buffer of pixel data. The data can be in one
|
||||
* of various formats including YCbCr.
|
||||
*
|
||||
*
|
||||
* Create an image using an ImageContainer. Fill the image with data, and
|
||||
* then call ImageContainer::SetImage to display it. An image must not be
|
||||
* modified after calling SetImage. Image implementations do not need to
|
||||
* perform locking; when filling an Image, the Image client is responsible
|
||||
* for ensuring only one thread accesses the Image at a time, and after
|
||||
* SetImage the image is immutable.
|
||||
*
|
||||
*
|
||||
* When resampling an Image, only pixels within the buffer should be
|
||||
* sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
|
||||
*/
|
||||
@ -258,7 +258,7 @@ protected:
|
||||
|
||||
/**
|
||||
* A RecycleBin is owned by an ImageContainer. We store buffers in it that we
|
||||
* want to recycle from one image to the next.It's a separate object from
|
||||
* want to recycle from one image to the next.It's a separate object from
|
||||
* ImageContainer because images need to store a strong ref to their RecycleBin
|
||||
* and we must avoid creating a reference loop between an ImageContainer and
|
||||
* its active image.
|
||||
@ -341,7 +341,7 @@ private:
|
||||
Mutex mLock;
|
||||
ImageContainer* mImageContainer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A class that manages Images for an ImageLayer. The only reason
|
||||
* we need a separate class here is that ImageLayers aren't threadsafe
|
||||
@ -421,7 +421,7 @@ public:
|
||||
* mProducerID is a unique ID for the stream of images. A change in the
|
||||
* mProducerID means changing to a new mFrameID namespace. All frames in
|
||||
* aImages must have the same mProducerID.
|
||||
*
|
||||
*
|
||||
* The Image data must not be modified after this method is called!
|
||||
* Note that this must not be called if ENABLE_ASYNC has not been set.
|
||||
*
|
||||
@ -457,11 +457,11 @@ public:
|
||||
* Set an Image as the current image to display. The Image must have
|
||||
* been created by this ImageContainer.
|
||||
* Must be called on the main thread, within a layers transaction.
|
||||
*
|
||||
*
|
||||
* This method takes mReentrantMonitor
|
||||
* when accessing thread-shared state.
|
||||
* aImage can be null. While it's null, nothing will be painted.
|
||||
*
|
||||
*
|
||||
* The Image data must not be modified after this method is called!
|
||||
* Note that this must not be called if ENABLE_ASYNC been set.
|
||||
*
|
||||
@ -726,7 +726,7 @@ struct PlanarYCbCrData {
|
||||
*
|
||||
* The color format is detected based on the height/width ratios
|
||||
* defined above.
|
||||
*
|
||||
*
|
||||
* The Image that is rendered is the picture region defined by
|
||||
* mPicX, mPicY and mPicSize. The size of the rendered image is
|
||||
* mPicSize, not mYSize or mCbCrSize.
|
||||
|
@ -1489,7 +1489,7 @@ RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
* to get valid results (because the cyclic buffer was overwritten since that call).
|
||||
*
|
||||
* To determine availability of the data upon StopFrameTimeRecording:
|
||||
* - mRecording.mNextIndex increases on each PostPresent, and never resets.
|
||||
* - mRecording.mNextIndex increases on each RecordFrame, and never resets.
|
||||
* - Cyclic buffer position is realized as mNextIndex % bufferSize.
|
||||
* - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called,
|
||||
* the required start index is passed as an arg, and we're able to calculate the required
|
||||
@ -1544,16 +1544,6 @@ LayerManager::RecordFrame()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManager::PostPresent()
|
||||
{
|
||||
if (!mTabSwitchStart.IsNull()) {
|
||||
Telemetry::Accumulate(Telemetry::FX_TAB_SWITCH_TOTAL_MS,
|
||||
uint32_t((TimeStamp::Now() - mTabSwitchStart).ToMilliseconds()));
|
||||
mTabSwitchStart = TimeStamp();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManager::StopFrameTimeRecording(uint32_t aStartIndex,
|
||||
nsTArray<float>& aFrameIntervals)
|
||||
@ -1582,12 +1572,6 @@ LayerManager::StopFrameTimeRecording(uint32_t aStartIndex,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManager::BeginTabSwitch()
|
||||
{
|
||||
mTabSwitchStart = TimeStamp::Now();
|
||||
}
|
||||
|
||||
static void PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
@ -660,9 +660,6 @@ public:
|
||||
nsTArray<float>& aFrameIntervals);
|
||||
|
||||
void RecordFrame();
|
||||
void PostPresent();
|
||||
|
||||
void BeginTabSwitch();
|
||||
|
||||
static bool IsLogEnabled();
|
||||
static mozilla::LogModule* GetLog();
|
||||
@ -775,8 +772,6 @@ private:
|
||||
};
|
||||
FramesTimingRecording mRecording;
|
||||
|
||||
TimeStamp mTabSwitchStart;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Methods to store/get/clear a "pending scroll info update" object on a
|
||||
|
@ -1150,19 +1150,17 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent);
|
||||
|
||||
MOZ_ASSERT(GetCurrentTouchBlock());
|
||||
if (gfxPrefs::TouchActionEnabled() && GetCurrentTouchBlock()->TouchActionAllowsPanningXY()) {
|
||||
// User tries to trigger a touch behavior. If allowed touch behavior is vertical pan
|
||||
// + horizontal pan (touch-action value is equal to AUTO) we can return ConsumeNoDefault
|
||||
// status immediately to trigger cancel event further. It should happen independent of
|
||||
// the parent type (whether it is scrolling or not).
|
||||
StartPanning(touchPoint);
|
||||
StartPanning(aEvent);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
return StartPanning(touchPoint);
|
||||
return StartPanning(aEvent);
|
||||
}
|
||||
|
||||
case PANNING:
|
||||
@ -1253,9 +1251,43 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
case PAN_MOMENTUM:
|
||||
{
|
||||
MOZ_ASSERT(GetCurrentTouchBlock());
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints();
|
||||
mX.EndTouch(aEvent.mTime);
|
||||
mY.EndTouch(aEvent.mTime);
|
||||
return HandleEndOfPan();
|
||||
ParentLayerPoint flingVelocity = GetVelocityVector();
|
||||
// Clear our velocities; if DispatchFling() gives the fling to us,
|
||||
// the fling velocity gets *added* to our existing velocity in
|
||||
// AcceptFling().
|
||||
mX.SetVelocity(0);
|
||||
mY.SetVelocity(0);
|
||||
// Clear our state so that we don't stay in the PANNING state
|
||||
// if DispatchFling() gives the fling to somone else. However,
|
||||
// don't send the state change notification until we've determined
|
||||
// what our final state is to avoid notification churn.
|
||||
StateChangeNotificationBlocker blocker(this);
|
||||
SetState(NOTHING);
|
||||
|
||||
APZC_LOG("%p starting a fling animation if %f >= %f\n", this,
|
||||
flingVelocity.Length().value, gfxPrefs::APZFlingMinVelocityThreshold());
|
||||
|
||||
if (flingVelocity.Length() < gfxPrefs::APZFlingMinVelocityThreshold()) {
|
||||
// Relieve overscroll now if needed, since we will not transition to a fling
|
||||
// animation and then an overscroll animation, and relieve it then.
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->SnapBackOverscrolledApzc(this);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
// Make a local copy of the tree manager pointer and check that it's not
|
||||
// null before calling DispatchFling(). This is necessary because Destroy(),
|
||||
// which nulls out mTreeManager, could be called concurrently.
|
||||
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
|
||||
FlingHandoffState handoffState{flingVelocity,
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain(),
|
||||
false /* not handoff */,
|
||||
GetCurrentTouchBlock()->GetScrolledApzc()};
|
||||
treeManagerLocal->DispatchFling(this, handoffState);
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
case PINCHING:
|
||||
SetState(NOTHING);
|
||||
@ -1286,8 +1318,6 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve
|
||||
APZC_LOG("%p got a scale-begin in state %d\n", this, mState);
|
||||
|
||||
mPinchPaintTimerSet = false;
|
||||
mX.StartTouch(aEvent.mLocalFocusPoint.x, aEvent.mTime);
|
||||
mY.StartTouch(aEvent.mLocalFocusPoint.y, aEvent.mTime);
|
||||
// Note that there may not be a touch block at this point, if we received the
|
||||
// PinchGestureEvent directly from widget code without any touch events.
|
||||
if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
|
||||
@ -1312,8 +1342,6 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a scale in state %d\n", this, mState);
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.x, 0, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalFocusPoint.y, 0, aEvent.mTime);
|
||||
|
||||
if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
|
||||
return nsEventStatus_eIgnore;
|
||||
@ -1449,6 +1477,8 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||
}
|
||||
}
|
||||
|
||||
SetState(NOTHING);
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
ScheduleComposite();
|
||||
@ -1458,86 +1488,32 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||
|
||||
// Non-negative focus point would indicate that one finger is still down
|
||||
if (aEvent.mLocalFocusPoint.x != -1 && aEvent.mLocalFocusPoint.y != -1) {
|
||||
if (mZoomConstraints.mAllowZoom) {
|
||||
mPanDirRestricted = false;
|
||||
SetState(TOUCHING);
|
||||
} else {
|
||||
StartPanning(aEvent.mLocalFocusPoint);
|
||||
}
|
||||
mPanDirRestricted = false;
|
||||
mX.StartTouch(aEvent.mLocalFocusPoint.x, aEvent.mTime);
|
||||
mY.StartTouch(aEvent.mLocalFocusPoint.y, aEvent.mTime);
|
||||
SetState(TOUCHING);
|
||||
} else {
|
||||
// Otherwise, handle the fingers being lifted.
|
||||
mX.EndTouch(aEvent.mTime);
|
||||
mY.EndTouch(aEvent.mTime);
|
||||
if (mZoomConstraints.mAllowZoom) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
// We can get into a situation where we are overscrolled at the end of a
|
||||
// pinch if we go into overscroll with a two-finger pan, and then turn
|
||||
// that into a pinch by increasing the span sufficiently. In such a case,
|
||||
// there is no snap-back animation to get us out of overscroll, so we need
|
||||
// to get out of it somehow.
|
||||
// Moreover, in cases of scroll handoff, the overscroll can be on an APZC
|
||||
// further up in the handoff chain rather than on the current APZC, so
|
||||
// we need to clear overscroll along the entire handoff chain.
|
||||
if (HasReadyTouchBlock()) {
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->ClearOverscroll();
|
||||
} else {
|
||||
ClearOverscroll();
|
||||
}
|
||||
// Along with clearing the overscroll, we also want to snap to the nearest
|
||||
// snap point as appropriate.
|
||||
ScrollSnap();
|
||||
// We can get into a situation where we are overscrolled at the end of a
|
||||
// pinch if we go into overscroll with a two-finger pan, and then turn
|
||||
// that into a pinch by increasing the span sufficiently. In such a case,
|
||||
// there is no snap-back animation to get us out of overscroll, so we need
|
||||
// to get out of it somehow.
|
||||
// Moreover, in cases of scroll handoff, the overscroll can be on an APZC
|
||||
// further up in the handoff chain rather than on the current APZC, so
|
||||
// we need to clear overscroll along the entire handoff chain.
|
||||
if (HasReadyTouchBlock()) {
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->ClearOverscroll();
|
||||
} else {
|
||||
// when zoom is not allowed
|
||||
if (mState == PINCHING) {
|
||||
// still pinching
|
||||
if (HasReadyTouchBlock()) {
|
||||
return HandleEndOfPan();
|
||||
}
|
||||
}
|
||||
ClearOverscroll();
|
||||
}
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::HandleEndOfPan()
|
||||
{
|
||||
MOZ_ASSERT(GetCurrentTouchBlock());
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints();
|
||||
ParentLayerPoint flingVelocity = GetVelocityVector();
|
||||
|
||||
// Clear our velocities; if DispatchFling() gives the fling to us,
|
||||
// the fling velocity gets *added* to our existing velocity in
|
||||
// AcceptFling().
|
||||
mX.SetVelocity(0);
|
||||
mY.SetVelocity(0);
|
||||
// Clear our state so that we don't stay in the PANNING state
|
||||
// if DispatchFling() gives the fling to somone else. However,
|
||||
// don't send the state change notification until we've determined
|
||||
// what our final state is to avoid notification churn.
|
||||
StateChangeNotificationBlocker blocker(this);
|
||||
SetState(NOTHING);
|
||||
|
||||
APZC_LOG("%p starting a fling animation if %f >= %f\n", this,
|
||||
flingVelocity.Length().value, gfxPrefs::APZFlingMinVelocityThreshold());
|
||||
|
||||
if (flingVelocity.Length() < gfxPrefs::APZFlingMinVelocityThreshold()) {
|
||||
// Relieve overscroll now if needed, since we will not transition to a fling
|
||||
// animation and then an overscroll animation, and relieve it then.
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->SnapBackOverscrolledApzc(this);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
// Along with clearing the overscroll, we also want to snap to the nearest
|
||||
// snap point as appropriate.
|
||||
ScrollSnap();
|
||||
}
|
||||
|
||||
// Make a local copy of the tree manager pointer and check that it's not
|
||||
// null before calling DispatchFling(). This is necessary because Destroy(),
|
||||
// which nulls out mTreeManager, could be called concurrently.
|
||||
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
|
||||
FlingHandoffState handoffState{flingVelocity,
|
||||
GetCurrentTouchBlock()->GetOverscrollHandoffChain(),
|
||||
false /* not handoff */,
|
||||
GetCurrentTouchBlock()->GetScrolledApzc()};
|
||||
treeManagerLocal->DispatchFling(this, handoffState);
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
@ -2348,12 +2324,12 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
AsyncPanZoomController::StartPanning(const ParentLayerPoint& aStartPoint) {
|
||||
nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
float dx = mX.PanDistance(aStartPoint.x);
|
||||
float dy = mY.PanDistance(aStartPoint.y);
|
||||
ParentLayerPoint point = GetFirstTouchPoint(aEvent);
|
||||
float dx = mX.PanDistance(point.x);
|
||||
float dy = mY.PanDistance(point.y);
|
||||
|
||||
double angle = atan2(dy, dx); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
@ -457,7 +457,6 @@ protected:
|
||||
nsEventStatus OnPanEnd(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent);
|
||||
nsEventStatus HandleEndOfPan();
|
||||
|
||||
/**
|
||||
* Helper methods for handling scroll wheel events.
|
||||
@ -577,7 +576,7 @@ protected:
|
||||
* Sets up anything needed for panning. This takes us out of the "TOUCHING"
|
||||
* state and starts actually panning us.
|
||||
*/
|
||||
nsEventStatus StartPanning(const ParentLayerPoint& aStartPoint);
|
||||
nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
|
||||
|
||||
/**
|
||||
* Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
|
||||
|
@ -138,7 +138,7 @@ PinchWithPinchInput(const RefPtr<InputReceiver>& aTarget,
|
||||
CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_END,
|
||||
// note: negative values here tell APZC
|
||||
// not to turn the pinch into a pan
|
||||
ScreenIntPoint(-1, -1), 10.0 * aScale, 10.0 * aScale),
|
||||
aFocus, -1.0, -1.0),
|
||||
nullptr);
|
||||
if (aOutEventStatuses) {
|
||||
(*aOutEventStatuses)[2] = actualStatus;
|
||||
|
@ -630,7 +630,6 @@ BasicLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
|
||||
FlashWidgetUpdateArea(mTarget);
|
||||
}
|
||||
RecordFrame();
|
||||
PostPresent();
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// Clear out target if we have a complete transaction.
|
||||
|
@ -194,6 +194,10 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
||||
// This can also happen if all images in the list are invalid.
|
||||
// We return true because the caller would attempt to recreate the
|
||||
// ImageClient otherwise, and that isn't going to help.
|
||||
for (auto& b : mBuffers) {
|
||||
RemoveTexture(b.mTextureClient);
|
||||
}
|
||||
mBuffers.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -79,4 +79,10 @@ enum class gfxContentType {
|
||||
SENTINEL = 0xffff
|
||||
};
|
||||
|
||||
enum class gfxAlphaType {
|
||||
Opaque,
|
||||
Premult,
|
||||
NonPremult,
|
||||
};
|
||||
|
||||
#endif /* GFX_TYPES_H */
|
||||
|
@ -8,9 +8,12 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "OSPreferences.h"
|
||||
#include "mozIOSPreferences.h"
|
||||
#include "unicode/udatpg.h"
|
||||
|
||||
namespace mozilla {
|
||||
using namespace mozilla::intl;
|
||||
|
||||
nsCString* DateTimeFormat::mLocale = nullptr;
|
||||
|
||||
@ -84,48 +87,115 @@ DateTimeFormat::FormatUDateTime(const nsDateFormatSelector aDateFormatSelector,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get the date style for the formatter:
|
||||
UDateFormatStyle dateStyle;
|
||||
// Get the date style for the formatter.
|
||||
nsAutoString skeletonDate;
|
||||
nsAutoString patternDate;
|
||||
bool haveSkeleton = true;
|
||||
switch (aDateFormatSelector) {
|
||||
case kDateFormatLong:
|
||||
dateStyle = UDAT_LONG;
|
||||
break;
|
||||
case kDateFormatShort:
|
||||
dateStyle = UDAT_SHORT;
|
||||
break;
|
||||
case kDateFormatYearMonth:
|
||||
case kDateFormatYearMonthLong:
|
||||
case kDateFormatMonthLong:
|
||||
case kDateFormatWeekday:
|
||||
dateStyle = UDAT_PATTERN;
|
||||
break;
|
||||
case kDateFormatNone:
|
||||
dateStyle = UDAT_NONE;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsDateFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
case kDateFormatLong:
|
||||
rv = OSPreferences::GetInstance()->GetDateTimePattern(mozIOSPreferences::dateTimeFormatStyleLong,
|
||||
mozIOSPreferences::dateTimeFormatStyleNone,
|
||||
nsDependentCString(mLocale->get()),
|
||||
patternDate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
haveSkeleton = false;
|
||||
break;
|
||||
case kDateFormatShort:
|
||||
rv = OSPreferences::GetInstance()->GetDateTimePattern(mozIOSPreferences::dateTimeFormatStyleShort,
|
||||
mozIOSPreferences::dateTimeFormatStyleNone,
|
||||
nsDependentCString(mLocale->get()),
|
||||
patternDate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
haveSkeleton = false;
|
||||
break;
|
||||
case kDateFormatYearMonth:
|
||||
skeletonDate.AssignLiteral("yyyyMM");
|
||||
break;
|
||||
case kDateFormatYearMonthLong:
|
||||
skeletonDate.AssignLiteral("yyyyMMMM");
|
||||
break;
|
||||
case kDateFormatMonthLong:
|
||||
skeletonDate.AssignLiteral("MMMM");
|
||||
break;
|
||||
case kDateFormatWeekday:
|
||||
skeletonDate.AssignLiteral("EEE");
|
||||
break;
|
||||
case kDateFormatNone:
|
||||
haveSkeleton = false;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsDateFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// Get the time style for the formatter:
|
||||
UDateFormatStyle timeStyle;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (haveSkeleton) {
|
||||
// Get pattern for skeleton.
|
||||
UDateTimePatternGenerator* patternGenerator = udatpg_open(mLocale->get(), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
int32_t patternLength;
|
||||
patternDate.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
patternLength = udatpg_getBestPattern(patternGenerator,
|
||||
reinterpret_cast<const UChar*>(skeletonDate.BeginReading()),
|
||||
skeletonDate.Length(),
|
||||
reinterpret_cast<UChar*>(patternDate.BeginWriting()),
|
||||
DATETIME_FORMAT_INITIAL_LEN,
|
||||
&status);
|
||||
patternDate.SetLength(patternLength);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udatpg_getBestPattern(patternGenerator,
|
||||
reinterpret_cast<const UChar*>(skeletonDate.BeginReading()),
|
||||
skeletonDate.Length(),
|
||||
reinterpret_cast<UChar*>(patternDate.BeginWriting()),
|
||||
patternLength,
|
||||
&status);
|
||||
}
|
||||
}
|
||||
udatpg_close(patternGenerator);
|
||||
}
|
||||
|
||||
// Get the time style for the formatter.
|
||||
nsAutoString patternTime;
|
||||
switch (aTimeFormatSelector) {
|
||||
case kTimeFormatSeconds:
|
||||
timeStyle = UDAT_MEDIUM;
|
||||
break;
|
||||
case kTimeFormatNoSeconds:
|
||||
timeStyle = UDAT_SHORT;
|
||||
break;
|
||||
case kTimeFormatNone:
|
||||
timeStyle = UDAT_NONE;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsTimeFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
case kTimeFormatSeconds:
|
||||
rv = OSPreferences::GetInstance()->GetDateTimePattern(mozIOSPreferences::dateTimeFormatStyleNone,
|
||||
mozIOSPreferences::dateTimeFormatStyleLong,
|
||||
nsDependentCString(mLocale->get()),
|
||||
patternTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
case kTimeFormatNoSeconds:
|
||||
rv = OSPreferences::GetInstance()->GetDateTimePattern(mozIOSPreferences::dateTimeFormatStyleNone,
|
||||
mozIOSPreferences::dateTimeFormatStyleShort,
|
||||
nsDependentCString(mLocale->get()),
|
||||
patternTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
case kTimeFormatNone:
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsTimeFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// generate date/time string
|
||||
nsAutoString pattern;
|
||||
if (patternTime.Length() == 0) {
|
||||
pattern.Assign(patternDate);
|
||||
} else if (patternDate.Length() == 0) {
|
||||
pattern.Assign(patternTime);
|
||||
} else {
|
||||
OSPreferences::GetDateTimeConnectorPattern(nsDependentCString(mLocale->get()), pattern);
|
||||
int32_t index = pattern.Find("{1}");
|
||||
if (index != kNotFound)
|
||||
pattern.Replace(index, 3, patternDate);
|
||||
index = pattern.Find("{0}");
|
||||
if (index != kNotFound)
|
||||
pattern.Replace(index, 3, patternTime);
|
||||
}
|
||||
|
||||
// Generate date/time string.
|
||||
nsAutoString timeZoneID(u"GMT");
|
||||
if (aTimeParameters) {
|
||||
int32_t totalOffsetMinutes = (aTimeParameters->tp_gmt_offset + aTimeParameters->tp_dst_offset) / 60;
|
||||
@ -137,100 +207,38 @@ DateTimeFormat::FormatUDateTime(const nsDateFormatSelector aDateFormatSelector,
|
||||
}
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
UDateFormat* dateTimeFormat;
|
||||
if (dateStyle == UDAT_PATTERN) {
|
||||
nsAutoString pattern;
|
||||
|
||||
dateTimeFormat = udat_open(timeStyle, UDAT_NONE, mLocale->get(), nullptr, -1, nullptr, -1, &status);
|
||||
|
||||
if (U_SUCCESS(status) && dateTimeFormat) {
|
||||
int32_t patternLength;
|
||||
if (timeStyle != UDAT_NONE) {
|
||||
pattern.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
patternLength = udat_toPattern(dateTimeFormat, FALSE, reinterpret_cast<UChar*>(pattern.BeginWriting()), DATETIME_FORMAT_INITIAL_LEN, &status);
|
||||
pattern.SetLength(patternLength);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udat_toPattern(dateTimeFormat, FALSE, reinterpret_cast<UChar*>(pattern.BeginWriting()), patternLength, &status);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString skeleton;
|
||||
switch (aDateFormatSelector) {
|
||||
case kDateFormatYearMonth:
|
||||
skeleton.AssignLiteral("yyyyMM ");
|
||||
break;
|
||||
case kDateFormatYearMonthLong:
|
||||
skeleton.AssignLiteral("yyyyMMMM ");
|
||||
break;
|
||||
case kDateFormatMonthLong:
|
||||
skeleton.AssignLiteral("MMMM ");
|
||||
break;
|
||||
case kDateFormatWeekday:
|
||||
skeleton.AssignLiteral("EEE ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int32_t dateSkeletonLen = skeleton.Length();
|
||||
|
||||
if (timeStyle != UDAT_NONE) {
|
||||
skeleton.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
int32_t skeletonLength = udatpg_getSkeleton(nullptr, reinterpret_cast<const UChar*>(pattern.BeginReading()), patternLength,
|
||||
reinterpret_cast<UChar*>(skeleton.BeginWriting() + dateSkeletonLen), DATETIME_FORMAT_INITIAL_LEN - dateSkeletonLen, &status);
|
||||
skeleton.SetLength(dateSkeletonLen + skeletonLength);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udatpg_getSkeleton(nullptr, reinterpret_cast<const UChar*>(pattern.BeginReading()), patternLength,
|
||||
reinterpret_cast<UChar*>(skeleton.BeginWriting() + dateSkeletonLen), dateSkeletonLen + skeletonLength, &status);
|
||||
}
|
||||
}
|
||||
|
||||
UDateTimePatternGenerator* patternGenerator = udatpg_open(mLocale->get(), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
pattern.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
patternLength = udatpg_getBestPattern(patternGenerator, reinterpret_cast<const UChar*>(skeleton.BeginReading()), skeleton.Length(),
|
||||
reinterpret_cast<UChar*>(pattern.BeginWriting()), DATETIME_FORMAT_INITIAL_LEN, &status);
|
||||
pattern.SetLength(patternLength);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udatpg_getBestPattern(patternGenerator, reinterpret_cast<const UChar*>(skeleton.BeginReading()), skeleton.Length(),
|
||||
reinterpret_cast<UChar*>(pattern.BeginWriting()), patternLength, &status);
|
||||
}
|
||||
}
|
||||
|
||||
udatpg_close(patternGenerator);
|
||||
}
|
||||
|
||||
udat_close(dateTimeFormat);
|
||||
|
||||
if (aTimeParameters) {
|
||||
dateTimeFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(), reinterpret_cast<const UChar*>(timeZoneID.BeginReading()), timeZoneID.Length(),
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()), pattern.Length(), &status);
|
||||
} else {
|
||||
dateTimeFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(), nullptr, -1, reinterpret_cast<const UChar*>(pattern.BeginReading()), pattern.Length(), &status);
|
||||
}
|
||||
if (aTimeParameters) {
|
||||
dateTimeFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(),
|
||||
reinterpret_cast<const UChar*>(timeZoneID.BeginReading()),
|
||||
timeZoneID.Length(),
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()),
|
||||
pattern.Length(),
|
||||
&status);
|
||||
} else {
|
||||
if (aTimeParameters) {
|
||||
dateTimeFormat = udat_open(timeStyle, dateStyle, mLocale->get(), reinterpret_cast<const UChar*>(timeZoneID.BeginReading()), timeZoneID.Length(), nullptr, -1, &status);
|
||||
} else {
|
||||
dateTimeFormat = udat_open(timeStyle, dateStyle, mLocale->get(), nullptr, -1, nullptr, -1, &status);
|
||||
}
|
||||
dateTimeFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(),
|
||||
nullptr, -1,
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()),
|
||||
pattern.Length(),
|
||||
&status);
|
||||
}
|
||||
|
||||
if (U_SUCCESS(status) && dateTimeFormat) {
|
||||
aStringOut.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
dateTimeLen = udat_format(dateTimeFormat, aUDateTime, reinterpret_cast<UChar*>(aStringOut.BeginWriting()), DATETIME_FORMAT_INITIAL_LEN, nullptr, &status);
|
||||
dateTimeLen = udat_format(dateTimeFormat, aUDateTime,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
DATETIME_FORMAT_INITIAL_LEN,
|
||||
nullptr,
|
||||
&status);
|
||||
aStringOut.SetLength(dateTimeLen);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udat_format(dateTimeFormat, aUDateTime, reinterpret_cast<UChar*>(aStringOut.BeginWriting()), dateTimeLen, nullptr, &status);
|
||||
udat_format(dateTimeFormat, aUDateTime,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
dateTimeLen,
|
||||
nullptr,
|
||||
&status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,22 +279,21 @@ bool
|
||||
OSPreferences::GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
nsAString& aRetVal)
|
||||
{
|
||||
bool result = false;
|
||||
#ifdef ENABLE_INTL_API
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDateTimePatternGenerator* pg = udatpg_open(PromiseFlatCString(aLocale).get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
if (U_SUCCESS(status)) {
|
||||
int32_t resultSize;
|
||||
const UChar* value = udatpg_getDateTimeFormat(pg, &resultSize);
|
||||
MOZ_ASSERT(resultSize >= 0);
|
||||
|
||||
aRetVal.Assign((char16_t*)value, resultSize);
|
||||
result = true;
|
||||
}
|
||||
|
||||
int32_t resultSize;
|
||||
const UChar* value = udatpg_getDateTimeFormat(pg, &resultSize);
|
||||
MOZ_ASSERT(resultSize >= 0);
|
||||
|
||||
aRetVal.Assign((char16_t*)value, resultSize);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
udatpg_close(pg);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,6 +101,9 @@ public:
|
||||
*/
|
||||
bool GetSystemLocales(nsTArray<nsCString>& aRetVal);
|
||||
|
||||
static bool GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
|
||||
protected:
|
||||
nsTArray<nsCString> mSystemLocales;
|
||||
|
||||
@ -129,9 +132,6 @@ private:
|
||||
const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
|
||||
bool GetDateTimeConnectorPattern(const nsACString& aLocale,
|
||||
nsAString& aRetVal);
|
||||
|
||||
/**
|
||||
* This is a host environment specific method that will be implemented
|
||||
* separately for each platform.
|
||||
|
@ -3,6 +3,32 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Normalise time.
|
||||
static nsAutoCString nt(nsAutoCString aDatetime)
|
||||
{
|
||||
nsAutoCString datetime = aDatetime;
|
||||
|
||||
// Replace "January 01" with "January 1" (found on Windows).
|
||||
int32_t ind = datetime.Find("January 01");
|
||||
if (ind != kNotFound)
|
||||
datetime.Replace(ind, 10, "January 1");
|
||||
|
||||
// Strip trailing " GMT" (found on Mac/Linux).
|
||||
ind = datetime.Find(" GMT");
|
||||
if (ind != kNotFound)
|
||||
datetime.Truncate(ind);
|
||||
|
||||
// Strip leading "Thursday, " or "Wednesday, " (found on Windows).
|
||||
ind = datetime.Find("Thursday, ");
|
||||
if (ind == 0)
|
||||
datetime.Replace(0, 10, "");
|
||||
ind = datetime.Find("Wednesday, ");
|
||||
if (ind == 0)
|
||||
datetime.Replace(0, 11, "");
|
||||
|
||||
return datetime;
|
||||
}
|
||||
|
||||
TEST(DateTimeFormat, FormatPRExplodedTime) {
|
||||
PRTime prTime = 0;
|
||||
PRExplodedTime prExplodedTime;
|
||||
@ -13,37 +39,37 @@ TEST(DateTimeFormat, FormatPRExplodedTime) {
|
||||
nsAutoString formattedTime;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1, 1970 at 12:00:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("January 1, 1970, 12:00:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 19, 0, 1, 0, 1970, 4, 0, { (19 * 60), 0 } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1, 1970 at 12:19:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("January 1, 1970, 12:19:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 0, 7, 1, 0, 1970, 4, 0, { (6 * 60 * 60), (1 * 60 * 60) } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1, 1970 at 7:00:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("January 1, 1970, 7:00:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 29, 11, 1, 0, 1970, 4, 0, { (10 * 60 * 60) + (29 * 60), (1 * 60 * 60) } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1, 1970 at 11:29:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("January 1, 1970, 11:29:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 37, 23, 31, 11, 1969, 3, 364, { -(23 * 60), 0 } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("December 31, 1969 at 11:37:00 PM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("December 31, 1969, 11:37:00 PM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 0, 17, 31, 11, 1969, 3, 364, { -(7 * 60 * 60), 0 } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("December 31, 1969 at 5:00:00 PM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("December 31, 1969, 5:00:00 PM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
prExplodedTime = { 0, 0, 47, 14, 31, 11, 1969, 3, 364, { -((10 * 60 * 60) + (13 * 60)), (1 * 60 * 60) } };
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatLong, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("December 31, 1969 at 2:47:00 PM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("December 31, 1969, 2:47:00 PM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
}
|
||||
|
||||
TEST(DateTimeFormat, DateFormatSelectors) {
|
||||
@ -68,11 +94,11 @@ TEST(DateTimeFormat, DateFormatSelectors) {
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatYearMonth, kTimeFormatNoSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01/1970, 12:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("01/1970, 12:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatYearMonth, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01/1970, 12:00:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("01/1970, 12:00:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatWeekday, kTimeFormatNone, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
@ -80,11 +106,11 @@ TEST(DateTimeFormat, DateFormatSelectors) {
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatWeekday, kTimeFormatNoSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Thu 12:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("Thu, 12:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(kDateFormatWeekday, kTimeFormatSeconds, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Thu 12:00:00 AM", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
ASSERT_STREQ("Thu, 12:00:00 AM", nt(NS_ConvertUTF16toUTF8(formattedTime)).get());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -457,6 +457,11 @@ bool Pickle::ReadSentinel(PickleIterator* iter, uint32_t sentinel) const {
|
||||
return found == sentinel;
|
||||
}
|
||||
|
||||
bool Pickle::IgnoreSentinel(PickleIterator* iter) const {
|
||||
uint32_t found;
|
||||
return ReadUInt32(iter, &found);
|
||||
}
|
||||
|
||||
bool Pickle::WriteSentinel(uint32_t sentinel) {
|
||||
return WriteUInt32(sentinel);
|
||||
}
|
||||
|
@ -129,6 +129,15 @@ class Pickle {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IgnoreSentinel(PickleIterator* iter) const
|
||||
#ifdef MOZ_PICKLE_SENTINEL_CHECKING
|
||||
;
|
||||
#else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE: The message type optional parameter should _only_ be called from
|
||||
// generated IPDL code, as it is used to trigger the IPC_READ_LATENCY_MS
|
||||
// telemetry probe.
|
||||
|
@ -490,16 +490,19 @@ EnqueuePromiseReactionJob(JSContext* cx, HandleObject reactionObj,
|
||||
Rooted<PromiseReactionRecord*> reaction(cx);
|
||||
RootedValue handlerArg(cx, handlerArg_);
|
||||
mozilla::Maybe<AutoCompartment> ac;
|
||||
if (IsWrapper(reactionObj)) {
|
||||
RootedObject unwrappedReactionObj(cx, UncheckedUnwrap(reactionObj));
|
||||
if (!unwrappedReactionObj)
|
||||
return false;
|
||||
ac.emplace(cx, unwrappedReactionObj);
|
||||
reaction = &unwrappedReactionObj->as<PromiseReactionRecord>();
|
||||
if (!cx->compartment()->wrap(cx, &handlerArg))
|
||||
return false;
|
||||
} else {
|
||||
if (!IsProxy(reactionObj)) {
|
||||
MOZ_RELEASE_ASSERT(reactionObj->is<PromiseReactionRecord>());
|
||||
reaction = &reactionObj->as<PromiseReactionRecord>();
|
||||
} else {
|
||||
if (JS_IsDeadWrapper(UncheckedUnwrap(reactionObj))) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
reaction = &UncheckedUnwrap(reactionObj)->as<PromiseReactionRecord>();
|
||||
MOZ_RELEASE_ASSERT(reaction->is<PromiseReactionRecord>());
|
||||
ac.emplace(cx, reaction);
|
||||
if (!reaction->compartment()->wrap(cx, &handlerArg))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must not enqueue a reaction job more than once.
|
||||
@ -640,7 +643,7 @@ FulfillMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj, HandleValue v
|
||||
if (!IsProxy(promiseObj)) {
|
||||
promise = &promiseObj->as<PromiseObject>();
|
||||
} else {
|
||||
if (JS_IsDeadWrapper(promiseObj)) {
|
||||
if (JS_IsDeadWrapper(UncheckedUnwrap(promiseObj))) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
@ -790,7 +793,7 @@ RejectMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj, HandleValue re
|
||||
if (!IsProxy(promiseObj)) {
|
||||
promise = &promiseObj->as<PromiseObject>();
|
||||
} else {
|
||||
if (JS_IsDeadWrapper(promiseObj)) {
|
||||
if (JS_IsDeadWrapper(UncheckedUnwrap(promiseObj))) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
@ -931,8 +934,15 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
||||
// back, we check if the reaction is a wrapper and if so, unwrap it and
|
||||
// enter its compartment.
|
||||
mozilla::Maybe<AutoCompartment> ac;
|
||||
if (IsWrapper(reactionObj)) {
|
||||
if (!IsProxy(reactionObj)) {
|
||||
MOZ_RELEASE_ASSERT(reactionObj->is<PromiseReactionRecord>());
|
||||
} else {
|
||||
reactionObj = UncheckedUnwrap(reactionObj);
|
||||
if (JS_IsDeadWrapper(reactionObj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(reactionObj->is<PromiseReactionRecord>());
|
||||
ac.emplace(cx, reactionObj);
|
||||
}
|
||||
|
||||
@ -2810,10 +2820,14 @@ BlockOnPromise(JSContext* cx, HandleValue promiseVal, HandleObject blockedPromis
|
||||
RootedObject blockedPromise(cx, blockedPromise_);
|
||||
|
||||
mozilla::Maybe<AutoCompartment> ac;
|
||||
if (IsWrapper(promiseObj)) {
|
||||
if (IsProxy(promiseObj)) {
|
||||
unwrappedPromiseObj = CheckedUnwrap(promiseObj);
|
||||
if (!unwrappedPromiseObj)
|
||||
return false;
|
||||
if (JS_IsDeadWrapper(unwrappedPromiseObj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
ac.emplace(cx, unwrappedPromiseObj);
|
||||
if (!cx->compartment()->wrap(cx, &blockedPromise))
|
||||
return false;
|
||||
@ -2864,8 +2878,12 @@ AddPromiseReaction(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
// If only a single reaction exists, it's stored directly instead of in a
|
||||
// list. In that case, `reactionsObj` might be a wrapper, which we can
|
||||
// always safely unwrap.
|
||||
if (IsWrapper(reactionsObj)) {
|
||||
if (IsProxy(reactionsObj)) {
|
||||
reactionsObj = UncheckedUnwrap(reactionsObj);
|
||||
if (JS_IsDeadWrapper(reactionsObj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(reactionsObj->is<PromiseReactionRecord>());
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope);
|
||||
|
||||
// Call setters for optional arguments.
|
||||
void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor);
|
||||
|
||||
JSScript* compileGlobalScript(ScopeKind scopeKind);
|
||||
JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
|
||||
ModuleObject* compileModule();
|
||||
@ -54,12 +51,13 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
const Maybe<uint32_t>& parameterListEnd);
|
||||
|
||||
ScriptSourceObject* sourceObjectPtr() const;
|
||||
SourceCompressionTask* sourceCompressionTask() const;
|
||||
|
||||
private:
|
||||
JSScript* compileScript(HandleObject environment, SharedContext* sc);
|
||||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool maybeCompressSource();
|
||||
bool enqueueOffThreadSourceCompression();
|
||||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
@ -67,7 +65,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
bool maybeCompleteCompressSource();
|
||||
|
||||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
@ -80,9 +77,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
|
||||
RootedScriptSource sourceObject;
|
||||
ScriptSource* scriptSource;
|
||||
|
||||
Maybe<SourceCompressionTask> maybeSourceCompressor;
|
||||
SourceCompressionTask* sourceCompressor;
|
||||
SourceCompressionTask* sourceCompressionTask_;
|
||||
|
||||
Maybe<UsedNameTracker> usedNames;
|
||||
Maybe<Parser<SyntaxParseHandler>> syntaxParser;
|
||||
@ -172,7 +167,7 @@ BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
||||
enclosingScope(cx, enclosingScope),
|
||||
sourceObject(cx),
|
||||
scriptSource(nullptr),
|
||||
sourceCompressor(nullptr),
|
||||
sourceCompressionTask_(nullptr),
|
||||
directives(options.strictOption),
|
||||
startPosition(keepAtoms),
|
||||
script(cx)
|
||||
@ -180,12 +175,6 @@ BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
||||
MOZ_ASSERT(sourceBuffer.get());
|
||||
}
|
||||
|
||||
void
|
||||
BytecodeCompiler::maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor)
|
||||
{
|
||||
this->sourceCompressor = sourceCompressor;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::checkLength()
|
||||
{
|
||||
@ -212,21 +201,11 @@ BytecodeCompiler::createScriptSource(const Maybe<uint32_t>& parameterListEnd)
|
||||
return false;
|
||||
|
||||
scriptSource = sourceObject->source();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompressSource()
|
||||
{
|
||||
if (!sourceCompressor) {
|
||||
maybeSourceCompressor.emplace(cx);
|
||||
sourceCompressor = maybeSourceCompressor.ptr();
|
||||
}
|
||||
|
||||
if (!cx->compartment()->behaviors().discardSource()) {
|
||||
if (options.sourceIsLazy) {
|
||||
scriptSource->setSourceRetrievable();
|
||||
} else if (!scriptSource->setSourceCopy(cx, sourceBuffer, sourceCompressor)) {
|
||||
} else if (!scriptSource->setSourceCopy(cx, sourceBuffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -234,6 +213,40 @@ BytecodeCompiler::maybeCompressSource()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::enqueueOffThreadSourceCompression()
|
||||
{
|
||||
// There are several cases where source compression is not a good idea:
|
||||
// - If the script is tiny, then compression will save little or no space.
|
||||
// - If there is only one core, then compression will contend with JS
|
||||
// execution (which hurts benchmarketing).
|
||||
//
|
||||
// Otherwise, enqueue a compression task to be processed when a major
|
||||
// GC is requested.
|
||||
|
||||
if (!scriptSource->hasUncompressedSource())
|
||||
return true;
|
||||
|
||||
bool canCompressOffThread =
|
||||
HelperThreadState().cpuCount > 1 &&
|
||||
HelperThreadState().threadCount >= 2 &&
|
||||
CanUseExtraThreads();
|
||||
const size_t TINY_SCRIPT = 256;
|
||||
if (TINY_SCRIPT <= sourceBuffer.length() && canCompressOffThread) {
|
||||
// Heap allocate the task. It will be freed upon compression
|
||||
// completing in AttachFinishedCompressedSources.
|
||||
SourceCompressionTask* task = cx->new_<SourceCompressionTask>(cx->runtime(),
|
||||
scriptSource);
|
||||
if (!task)
|
||||
return false;
|
||||
if (!EnqueueOffThreadCompression(cx, task))
|
||||
return false;
|
||||
sourceCompressionTask_ = task;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::canLazilyParse()
|
||||
{
|
||||
@ -263,7 +276,6 @@ BytecodeCompiler::createParser()
|
||||
|
||||
parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr);
|
||||
parser->sct = sourceCompressor;
|
||||
parser->ss = scriptSource;
|
||||
if (!parser->checkOptions())
|
||||
return false;
|
||||
@ -276,7 +288,6 @@ bool
|
||||
BytecodeCompiler::createSourceAndParser(const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
{
|
||||
return createScriptSource(parameterListEnd) &&
|
||||
maybeCompressSource() &&
|
||||
createParser();
|
||||
}
|
||||
|
||||
@ -341,12 +352,6 @@ BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObj
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::maybeCompleteCompressSource()
|
||||
{
|
||||
return !maybeSourceCompressor || maybeSourceCompressor->complete();
|
||||
}
|
||||
|
||||
JSScript*
|
||||
BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
||||
{
|
||||
@ -394,13 +399,14 @@ BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
||||
usedNames->reset();
|
||||
}
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
return nullptr;
|
||||
|
||||
// We have just finished parsing the source. Inform the source so that we
|
||||
// can compute statistics (e.g. how much time our functions remain lazy).
|
||||
script->scriptSource()->recordParseEnded();
|
||||
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
|
||||
return script;
|
||||
@ -462,7 +468,8 @@ BytecodeCompiler::compileModule()
|
||||
|
||||
module->setInitialEnvironment(env);
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
@ -517,7 +524,8 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
||||
if (!NameFunctions(cx, fn))
|
||||
return false;
|
||||
|
||||
if (!maybeCompleteCompressSource())
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!enqueueOffThreadSourceCompression())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -529,6 +537,12 @@ BytecodeCompiler::sourceObjectPtr() const
|
||||
return sourceObject.get();
|
||||
}
|
||||
|
||||
SourceCompressionTask*
|
||||
BytecodeCompiler::sourceCompressionTask() const
|
||||
{
|
||||
return sourceCompressionTask_;
|
||||
}
|
||||
|
||||
ScriptSourceObject*
|
||||
frontend::CreateScriptSourceObject(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
@ -580,16 +594,22 @@ class MOZ_STACK_CLASS AutoInitializeSourceObject
|
||||
{
|
||||
BytecodeCompiler& compiler_;
|
||||
ScriptSourceObject** sourceObjectOut_;
|
||||
SourceCompressionTask** sourceCompressionTaskOut_;
|
||||
|
||||
public:
|
||||
AutoInitializeSourceObject(BytecodeCompiler& compiler, ScriptSourceObject** sourceObjectOut)
|
||||
AutoInitializeSourceObject(BytecodeCompiler& compiler,
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
: compiler_(compiler),
|
||||
sourceObjectOut_(sourceObjectOut)
|
||||
sourceObjectOut_(sourceObjectOut),
|
||||
sourceCompressionTaskOut_(sourceCompressionTaskOut)
|
||||
{ }
|
||||
|
||||
~AutoInitializeSourceObject() {
|
||||
if (sourceObjectOut_)
|
||||
*sourceObjectOut_ = compiler_.sourceObjectPtr();
|
||||
if (sourceCompressionTaskOut_)
|
||||
*sourceCompressionTaskOut_ = compiler_.sourceCompressionTask();
|
||||
}
|
||||
};
|
||||
|
||||
@ -597,13 +617,12 @@ JSScript*
|
||||
frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
compiler.maybeSetSourceCompressor(extraSct);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileGlobalScript(scopeKind);
|
||||
}
|
||||
|
||||
@ -612,19 +631,19 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
||||
HandleObject environment, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
compiler.maybeSetSourceCompressor(extraSct);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileEvalScript(environment, enclosingScope);
|
||||
}
|
||||
|
||||
ModuleObject*
|
||||
frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
ScriptSourceObject** sourceObjectOut /* = nullptr */)
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
SourceCompressionTask** sourceCompressionTaskOut)
|
||||
{
|
||||
MOZ_ASSERT(srcBuf.get());
|
||||
MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
|
||||
@ -636,7 +655,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut, sourceCompressionTaskOut);
|
||||
return compiler.compileModule();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ class LazyScript;
|
||||
class LifoAlloc;
|
||||
class ModuleObject;
|
||||
class ScriptSourceObject;
|
||||
struct SourceCompressionTask;
|
||||
class SourceCompressionTask;
|
||||
|
||||
namespace frontend {
|
||||
|
||||
@ -35,16 +35,16 @@ JSScript*
|
||||
CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct = nullptr,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
JSScript*
|
||||
CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
||||
HandleObject scopeChain, HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
SourceCompressionTask* extraSct = nullptr,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
ModuleObject*
|
||||
CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
@ -53,7 +53,8 @@ CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
ModuleObject*
|
||||
CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
ScriptSourceObject** sourceObjectOut = nullptr,
|
||||
SourceCompressionTask** sourceCompressionTaskOut = nullptr);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||
|
@ -3593,7 +3593,7 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
|
||||
TokenStream& ts = tokenStream();
|
||||
ErrorMetadata metadata;
|
||||
if (ts.computeErrorMetadata(&metadata, pos.begin))
|
||||
ts.compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
@ -52,10 +52,6 @@ class FullParseHandler
|
||||
size_t lazyInnerFunctionIndex;
|
||||
size_t lazyClosedOverBindingIndex;
|
||||
|
||||
const TokenPos& pos() {
|
||||
return tokenStream.currentToken().pos;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
@ -247,15 +243,9 @@ class FullParseHandler
|
||||
return new_<UnaryNode>(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, pos, kid);
|
||||
}
|
||||
|
||||
ParseNode* newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
return new_<BinaryNode>(kind, op, pos(), (ParseNode*) nullptr, (ParseNode*) nullptr);
|
||||
}
|
||||
ParseNode* newBinary(ParseNodeKind kind, ParseNode* left,
|
||||
JSOp op = JSOP_NOP) {
|
||||
return new_<BinaryNode>(kind, op, left->pn_pos, left, (ParseNode*) nullptr);
|
||||
}
|
||||
ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right,
|
||||
JSOp op = JSOP_NOP) {
|
||||
JSOp op = JSOP_NOP)
|
||||
{
|
||||
TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
|
||||
return new_<BinaryNode>(kind, op, pos, left, right);
|
||||
}
|
||||
@ -317,12 +307,12 @@ class FullParseHandler
|
||||
literal->append(element);
|
||||
}
|
||||
|
||||
ParseNode* newCall() {
|
||||
return newList(PNK_CALL, JSOP_CALL);
|
||||
ParseNode* newCall(const TokenPos& pos) {
|
||||
return newList(PNK_CALL, pos, JSOP_CALL);
|
||||
}
|
||||
|
||||
ParseNode* newTaggedTemplate() {
|
||||
return newList(PNK_TAGGED_TEMPLATE, JSOP_CALL);
|
||||
ParseNode* newTaggedTemplate(const TokenPos& pos) {
|
||||
return newList(PNK_TAGGED_TEMPLATE, pos, JSOP_CALL);
|
||||
}
|
||||
|
||||
ParseNode* newObjectLiteral(uint32_t begin) {
|
||||
@ -634,6 +624,10 @@ class FullParseHandler
|
||||
return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr);
|
||||
}
|
||||
|
||||
ParseNode* newExpressionBody(ParseNode* expr) {
|
||||
return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, expr->pn_pos, expr);
|
||||
}
|
||||
|
||||
ParseNode* newWithStatement(uint32_t begin, ParseNode* expr, ParseNode* body) {
|
||||
return new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
|
||||
expr, body);
|
||||
@ -679,16 +673,16 @@ class FullParseHandler
|
||||
pn->setDirectRHSAnonFunction(true);
|
||||
}
|
||||
|
||||
ParseNode* newFunctionStatement() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos());
|
||||
ParseNode* newFunctionStatement(const TokenPos& pos) {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
ParseNode* newFunctionExpression() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos());
|
||||
ParseNode* newFunctionExpression(const TokenPos& pos) {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos);
|
||||
}
|
||||
|
||||
ParseNode* newArrowFunction() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos());
|
||||
ParseNode* newArrowFunction(const TokenPos& pos) {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos);
|
||||
}
|
||||
|
||||
bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) {
|
||||
@ -716,14 +710,23 @@ class FullParseHandler
|
||||
fn->pn_body->append(body);
|
||||
}
|
||||
|
||||
ParseNode* newModule() {
|
||||
return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos());
|
||||
ParseNode* newModule(const TokenPos& pos) {
|
||||
return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
|
||||
return new_<LexicalScopeNode>(bindings, body);
|
||||
}
|
||||
|
||||
Node newNewExpression(uint32_t begin, ParseNode* ctor) {
|
||||
ParseNode* newExpr = newList(PNK_NEW, begin, JSOP_NEW);
|
||||
if (!newExpr)
|
||||
return nullptr;
|
||||
|
||||
addList(newExpr, ctor);
|
||||
return newExpr;
|
||||
}
|
||||
|
||||
ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs,
|
||||
JSOp op)
|
||||
{
|
||||
@ -802,29 +805,28 @@ class FullParseHandler
|
||||
return kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST;
|
||||
}
|
||||
|
||||
ParseNode* newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ParseNode* newList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
return new_<ListNode>(kind, op, pos);
|
||||
}
|
||||
|
||||
private:
|
||||
ParseNode* newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, TokenPos(begin, begin + 1));
|
||||
return newList(kind, TokenPos(begin, begin + 1), op);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ParseNode* newList(ParseNodeKind kind, const T& begin, JSOp op = JSOP_NOP) = delete;
|
||||
|
||||
public:
|
||||
ParseNode* newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
}
|
||||
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, const TokenPos& pos, JSOp op) {
|
||||
MOZ_ASSERT(isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
}
|
||||
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
return new_<ListNode>(kind, op, pos);
|
||||
}
|
||||
|
||||
bool isDeclarationList(ParseNode* node) {
|
||||
@ -837,8 +839,8 @@ class FullParseHandler
|
||||
return decl->pn_head;
|
||||
}
|
||||
|
||||
ParseNode* newCatchList() {
|
||||
return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos());
|
||||
ParseNode* newCatchList(const TokenPos& pos) {
|
||||
return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
ParseNode* newCommaExpressionList(ParseNode* kid) {
|
||||
|
@ -596,7 +596,7 @@ ParserBase::error(unsigned errorNumber, ...)
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (tokenStream.computeErrorMetadata(&metadata, pos().begin))
|
||||
tokenStream.compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -608,8 +608,10 @@ ParserBase::errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber,
|
||||
va_start(args, errorNumber);
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (tokenStream.computeErrorMetadata(&metadata, pos().begin))
|
||||
tokenStream.compileError(Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber, args);
|
||||
if (tokenStream.computeErrorMetadata(&metadata, pos().begin)) {
|
||||
ReportCompileError(context, Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -622,7 +624,7 @@ ParserBase::errorAt(uint32_t offset, unsigned errorNumber, ...)
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (tokenStream.computeErrorMetadata(&metadata, offset))
|
||||
tokenStream.compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -635,8 +637,10 @@ ParserBase::errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
va_start(args, errorNumber);
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (tokenStream.computeErrorMetadata(&metadata, offset))
|
||||
tokenStream.compileError(Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber, args);
|
||||
if (tokenStream.computeErrorMetadata(&metadata, offset)) {
|
||||
ReportCompileError(context, Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -667,7 +671,7 @@ ParserBase::warningAt(uint32_t offset, unsigned errorNumber, ...)
|
||||
if (result) {
|
||||
result =
|
||||
tokenStream.compileWarning(Move(metadata), nullptr, JSREPORT_WARNING, errorNumber,
|
||||
args);
|
||||
args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
@ -729,7 +733,8 @@ ParserBase::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumb
|
||||
tokenStream.computeErrorMetadataNoOffset(&metadata);
|
||||
|
||||
if (kind == ParseError) {
|
||||
tokenStream.compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
MOZ_ASSERT(!result);
|
||||
} else {
|
||||
result =
|
||||
@ -774,7 +779,6 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
|
||||
const char16_t* chars, size_t length,
|
||||
bool foldConstants,
|
||||
UsedNameTracker& usedNames,
|
||||
Parser<SyntaxParseHandler>* syntaxParser,
|
||||
LazyScript* lazyOuterFunction)
|
||||
: context(cx),
|
||||
alloc(alloc),
|
||||
@ -782,7 +786,6 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
|
||||
traceListHead(nullptr),
|
||||
pc(nullptr),
|
||||
usedNames(usedNames),
|
||||
sct(nullptr),
|
||||
ss(nullptr),
|
||||
keepAtoms(cx),
|
||||
foldConstants(foldConstants),
|
||||
@ -819,8 +822,7 @@ Parser<ParseHandler>::Parser(JSContext* cx, LifoAlloc& alloc,
|
||||
UsedNameTracker& usedNames,
|
||||
Parser<SyntaxParseHandler>* syntaxParser,
|
||||
LazyScript* lazyOuterFunction)
|
||||
: ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, syntaxParser,
|
||||
lazyOuterFunction),
|
||||
: ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, lazyOuterFunction),
|
||||
AutoGCRooter(cx, PARSER),
|
||||
handler(cx, alloc, tokenStream, syntaxParser, lazyOuterFunction)
|
||||
{
|
||||
@ -864,9 +866,8 @@ Parser<FullParseHandler>::setAwaitIsKeyword(bool isKeyword)
|
||||
parser->setAwaitIsKeyword(isKeyword);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
ObjectBox*
|
||||
Parser<ParseHandler>::newObjectBox(JSObject* obj)
|
||||
ParserBase::newObjectBox(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
@ -1007,9 +1008,8 @@ ParserBase::isValidStrictBinding(PropertyName* name)
|
||||
* Returns true if all parameter names are valid strict mode binding names and
|
||||
* no duplicate parameter names are present.
|
||||
*/
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::hasValidSimpleStrictParameterNames()
|
||||
ParserBase::hasValidSimpleStrictParameterNames()
|
||||
{
|
||||
MOZ_ASSERT(pc->isFunctionBox() && pc->functionBox()->hasSimpleParameterList());
|
||||
|
||||
@ -2203,7 +2203,7 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
|
||||
if (!varScope.init(pc))
|
||||
return nullptr;
|
||||
|
||||
Node mn = handler.newModule();
|
||||
Node mn = handler.newModule(pos());
|
||||
if (!mn)
|
||||
return null();
|
||||
|
||||
@ -2514,11 +2514,11 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
|
||||
Node fn = handler.newFunctionStatement();
|
||||
Node fn = handler.newFunctionStatement(pos());
|
||||
if (!fn)
|
||||
return null();
|
||||
|
||||
ParseNode* argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
ParseNode* argsbody = handler.newList(PNK_PARAMSBODY, pos());
|
||||
if (!argsbody)
|
||||
return null();
|
||||
fn->pn_body = argsbody;
|
||||
@ -2680,7 +2680,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
pn = handler.newReturnStatement(kid, handler.getPosition(kid));
|
||||
pn = handler.newExpressionBody(kid);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -2737,11 +2737,10 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
||||
return finishLexicalScope(pc->varScope(), pn);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
JSFunction*
|
||||
Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
HandleObject proto)
|
||||
ParserBase::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
HandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
|
||||
|
||||
@ -2982,7 +2981,7 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn
|
||||
funbox->setStart(tokenStream);
|
||||
}
|
||||
|
||||
Node argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
Node argsbody = handler.newList(PNK_PARAMSBODY, pos());
|
||||
if (!argsbody)
|
||||
return false;
|
||||
handler.setFunctionFormalParametersAndBody(funcpn, argsbody);
|
||||
@ -3551,7 +3550,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
|
||||
{
|
||||
MOZ_ASSERT(checkOptionsCalled);
|
||||
|
||||
Node pn = handler.newFunctionStatement();
|
||||
Node pn = handler.newFunctionStatement(pos());
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -3825,7 +3824,7 @@ Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHan
|
||||
return null();
|
||||
}
|
||||
|
||||
Node pn = handler.newFunctionStatement();
|
||||
Node pn = handler.newFunctionStatement(pos());
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -3870,7 +3869,7 @@ Parser<ParseHandler>::functionExpr(uint32_t preludeStart, InvokedPrediction invo
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
|
||||
Node pn = handler.newFunctionExpression();
|
||||
Node pn = handler.newFunctionExpression(pos());
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -4781,7 +4780,7 @@ Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
|
||||
MOZ_CRASH("Unknown declaration kind");
|
||||
}
|
||||
|
||||
Node decl = handler.newDeclarationList(kind, op);
|
||||
Node decl = handler.newDeclarationList(kind, pos(), op);
|
||||
if (!decl)
|
||||
return null();
|
||||
|
||||
@ -4983,7 +4982,7 @@ Parser<FullParseHandler>::importDeclaration()
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
||||
Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
|
||||
Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST, pos());
|
||||
if (!importSpecSet)
|
||||
return null();
|
||||
|
||||
@ -5234,7 +5233,7 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
|
||||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_MUL));
|
||||
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST, pos());
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
@ -5285,7 +5284,7 @@ Parser<ParseHandler>::exportClause(uint32_t begin)
|
||||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST, pos());
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
@ -6796,7 +6795,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
if (tt == TOK_CATCH) {
|
||||
catchList = handler.newCatchList();
|
||||
catchList = handler.newCatchList(pos());
|
||||
if (!catchList)
|
||||
return null();
|
||||
|
||||
@ -8122,7 +8121,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
|
||||
Node pn = handler.newArrowFunction();
|
||||
Node pn = handler.newArrowFunction(pos());
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -8418,7 +8417,7 @@ template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
|
||||
{
|
||||
Node genfn = handler.newFunctionExpression();
|
||||
Node genfn = handler.newFunctionExpression(pos());
|
||||
if (!genfn)
|
||||
return null();
|
||||
|
||||
@ -8818,10 +8817,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
||||
if (newTarget) {
|
||||
lhs = newTarget;
|
||||
} else {
|
||||
lhs = handler.newList(PNK_NEW, newBegin, JSOP_NEW);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
||||
// Gotten by tryNewTarget
|
||||
tt = tokenStream.currentToken().type;
|
||||
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt,
|
||||
@ -8830,7 +8825,9 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
||||
if (!ctorExpr)
|
||||
return null();
|
||||
|
||||
handler.addList(lhs, ctorExpr);
|
||||
lhs = handler.newNewExpression(newBegin, ctorExpr);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_LP))
|
||||
@ -8937,7 +8934,10 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
||||
return null();
|
||||
}
|
||||
|
||||
nextMember = tt == TOK_LP ? handler.newCall() : handler.newTaggedTemplate();
|
||||
TokenPos nextMemberPos = pos();
|
||||
nextMember = tt == TOK_LP
|
||||
? handler.newCall(nextMemberPos)
|
||||
: handler.newTaggedTemplate(nextMemberPos);
|
||||
if (!nextMember)
|
||||
return null();
|
||||
|
||||
@ -9169,7 +9169,7 @@ template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::stringLiteral()
|
||||
{
|
||||
return handler.newStringLiteral(stopStringCompression(), pos());
|
||||
return handler.newStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@ -9181,7 +9181,7 @@ Parser<ParseHandler>::noSubstitutionTaggedTemplate()
|
||||
return handler.newRawUndefinedLiteral(pos());
|
||||
}
|
||||
|
||||
return handler.newTemplateStringLiteral(stopStringCompression(), pos());
|
||||
return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@ -9191,20 +9191,7 @@ Parser<ParseHandler>::noSubstitutionUntaggedTemplate()
|
||||
if (!tokenStream.checkForInvalidTemplateEscapeError())
|
||||
return null();
|
||||
|
||||
return handler.newTemplateStringLiteral(stopStringCompression(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
JSAtom * Parser<ParseHandler>::stopStringCompression() {
|
||||
JSAtom* atom = tokenStream.currentToken().atom();
|
||||
|
||||
// Large strings are fast to parse but slow to compress. Stop compression on
|
||||
// them, so we don't wait for a long time for compression to finish at the
|
||||
// end of compilation.
|
||||
const size_t HUGE_STRING = 50000;
|
||||
if (sct && sct->active() && atom->length() >= HUGE_STRING)
|
||||
sct->abort();
|
||||
return atom;
|
||||
return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
@ -9776,7 +9763,7 @@ Parser<ParseHandler>::methodDefinition(uint32_t preludeStart, PropertyType propT
|
||||
|
||||
YieldHandling yieldHandling = GetYieldHandling(generatorKind);
|
||||
|
||||
Node pn = handler.newFunctionExpression();
|
||||
Node pn = handler.newFunctionExpression(pos());
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
|
@ -770,9 +770,6 @@ class ParserBase : public StrictModeGetter
|
||||
// For tracking used names in this parsing session.
|
||||
UsedNameTracker& usedNames;
|
||||
|
||||
/* Compression token for aborting. */
|
||||
SourceCompressionTask* sct;
|
||||
|
||||
ScriptSource* ss;
|
||||
|
||||
/* Root atoms and objects allocated for the parsed tree. */
|
||||
@ -806,8 +803,7 @@ class ParserBase : public StrictModeGetter
|
||||
|
||||
ParserBase(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* chars, size_t length, bool foldConstants,
|
||||
UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser,
|
||||
LazyScript* lazyOuterFunction);
|
||||
UsedNameTracker& usedNames, LazyScript* lazyOuterFunction);
|
||||
~ParserBase();
|
||||
|
||||
const char* getFilename() const { return tokenStream.getFilename(); }
|
||||
@ -896,6 +892,47 @@ class ParserBase : public StrictModeGetter
|
||||
bool warnOnceAboutExprClosure();
|
||||
bool warnOnceAboutForEach();
|
||||
|
||||
bool allowsForEachIn() {
|
||||
#if !JS_HAS_FOR_EACH_IN
|
||||
return false;
|
||||
#else
|
||||
return options().forEachStatementOption && versionNumber() >= JSVERSION_1_6;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
|
||||
/*
|
||||
* Create a new function object given a name (which is optional if this is
|
||||
* a function expression).
|
||||
*/
|
||||
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
HandleObject proto);
|
||||
|
||||
// A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
|
||||
// Parser's state. Note: clients must still take care that any ParseContext
|
||||
// that points into released ParseNodes is destroyed.
|
||||
class Mark
|
||||
{
|
||||
friend class ParserBase;
|
||||
LifoAlloc::Mark mark;
|
||||
ObjectBox* traceListHead;
|
||||
};
|
||||
Mark mark() const {
|
||||
Mark m;
|
||||
m.mark = alloc.mark();
|
||||
m.traceListHead = traceListHead;
|
||||
return m;
|
||||
}
|
||||
void release(Mark m) {
|
||||
alloc.release(m.mark);
|
||||
traceListHead = m.traceListHead;
|
||||
}
|
||||
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
|
||||
protected:
|
||||
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
|
||||
enum ForInitLocation { InForInit, NotInForInit };
|
||||
@ -1037,26 +1074,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
|
||||
bool checkOptions();
|
||||
|
||||
// A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
|
||||
// Parser's state. Note: clients must still take care that any ParseContext
|
||||
// that points into released ParseNodes is destroyed.
|
||||
class Mark
|
||||
{
|
||||
friend class Parser;
|
||||
LifoAlloc::Mark mark;
|
||||
ObjectBox* traceListHead;
|
||||
};
|
||||
Mark mark() const {
|
||||
Mark m;
|
||||
m.mark = alloc.mark();
|
||||
m.traceListHead = traceListHead;
|
||||
return m;
|
||||
}
|
||||
void release(Mark m) {
|
||||
alloc.release(m.mark);
|
||||
traceListHead = m.traceListHead;
|
||||
}
|
||||
|
||||
friend void js::frontend::TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
||||
|
||||
/*
|
||||
@ -1064,31 +1081,16 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
*/
|
||||
Node parse();
|
||||
|
||||
/*
|
||||
* Allocate a new parsed object or function container from
|
||||
* cx->tempLifoAlloc.
|
||||
*/
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t preludeStart,
|
||||
Directives directives,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB);
|
||||
|
||||
/*
|
||||
* Create a new function object given a name (which is optional if this is
|
||||
* a function expression).
|
||||
*/
|
||||
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
HandleObject proto);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
private:
|
||||
Parser* thisForCtor() { return this; }
|
||||
|
||||
JSAtom* stopStringCompression();
|
||||
|
||||
Node stringLiteral();
|
||||
Node noSubstitutionTaggedTemplate();
|
||||
Node noSubstitutionUntaggedTemplate();
|
||||
@ -1407,14 +1409,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
|
||||
bool matchLabel(YieldHandling yieldHandling, MutableHandle<PropertyName*> label);
|
||||
|
||||
bool allowsForEachIn() {
|
||||
#if !JS_HAS_FOR_EACH_IN
|
||||
return false;
|
||||
#else
|
||||
return options().forEachStatementOption && versionNumber() >= JSVERSION_1_6;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool matchInOrOf(bool* isForInp, bool* isForOfp);
|
||||
|
||||
bool hasUsedFunctionSpecialName(HandlePropertyName name);
|
||||
@ -1459,8 +1453,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
void reportMissingClosing(unsigned errorNumber, unsigned noteNumber, uint32_t openedPos);
|
||||
|
||||
void reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, TokenPos pos,
|
||||
|
@ -261,8 +261,6 @@ class SyntaxParseHandler
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) { return NodeGeneric; }
|
||||
Node newBinary(ParseNodeKind kind, Node left, JSOp op = JSOP_NOP) { return NodeGeneric; }
|
||||
Node newBinary(ParseNodeKind kind, Node left, Node right, JSOp op = JSOP_NOP) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
@ -283,8 +281,8 @@ class SyntaxParseHandler
|
||||
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
void addArrayElement(Node literal, Node element) { }
|
||||
|
||||
Node newCall() { return NodeFunctionCall; }
|
||||
Node newTaggedTemplate() { return NodeGeneric; }
|
||||
Node newCall(const TokenPos& pos) { return NodeFunctionCall; }
|
||||
Node newTaggedTemplate(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
@ -336,6 +334,7 @@ class SyntaxParseHandler
|
||||
Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; }
|
||||
Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; }
|
||||
Node newExpressionBody(Node expr) { return NodeReturn; }
|
||||
Node newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
|
||||
|
||||
Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) {
|
||||
@ -362,9 +361,9 @@ class SyntaxParseHandler
|
||||
|
||||
void checkAndSetIsDirectRHSAnonFunction(Node pn) {}
|
||||
|
||||
Node newFunctionStatement() { return NodeFunctionDefinition; }
|
||||
Node newFunctionExpression() { return NodeFunctionDefinition; }
|
||||
Node newArrowFunction() { return NodeFunctionDefinition; }
|
||||
Node newFunctionStatement(const TokenPos& pos) { return NodeFunctionDefinition; }
|
||||
Node newFunctionExpression(const TokenPos& pos) { return NodeFunctionDefinition; }
|
||||
Node newArrowFunction(const TokenPos& pos) { return NodeFunctionDefinition; }
|
||||
|
||||
bool setComprehensionLambdaBody(Node pn, Node body) { return true; }
|
||||
void setFunctionFormalParametersAndBody(Node pn, Node kid) {}
|
||||
@ -409,28 +408,32 @@ class SyntaxParseHandler
|
||||
return tokenStream.currentToken().pos;
|
||||
}
|
||||
|
||||
Node newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
Node newList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
MOZ_ASSERT(kind != PNK_LET);
|
||||
MOZ_ASSERT(kind != PNK_CONST);
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
private:
|
||||
Node newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
return newList(kind, op);
|
||||
}
|
||||
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
return newList(kind, op);
|
||||
return newList(kind, TokenPos(begin, begin + 1), op);
|
||||
}
|
||||
|
||||
Node newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
template<typename T>
|
||||
Node newList(ParseNodeKind kind, const T& begin, JSOp op = JSOP_NOP) = delete;
|
||||
|
||||
public:
|
||||
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
return newList(kind, TokenPos(), op);
|
||||
}
|
||||
|
||||
Node newDeclarationList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
|
||||
if (kind == PNK_VAR)
|
||||
return NodeVarDeclaration;
|
||||
MOZ_ASSERT(kind == PNK_LET || kind == PNK_CONST);
|
||||
return NodeLexicalDeclaration;
|
||||
}
|
||||
Node newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
return newDeclarationList(kind, op);
|
||||
}
|
||||
|
||||
bool isDeclarationList(Node node) {
|
||||
return node == NodeVarDeclaration || node == NodeLexicalDeclaration;
|
||||
@ -456,8 +459,8 @@ class SyntaxParseHandler
|
||||
return NodeUnparenthesizedName;
|
||||
}
|
||||
|
||||
Node newCatchList() {
|
||||
return newList(PNK_CATCHLIST, JSOP_NOP);
|
||||
Node newCatchList(const TokenPos& pos) {
|
||||
return newList(PNK_CATCHLIST, pos, JSOP_NOP);
|
||||
}
|
||||
|
||||
Node newCommaExpressionList(Node kid) {
|
||||
@ -474,6 +477,15 @@ class SyntaxParseHandler
|
||||
list == NodeFunctionCall);
|
||||
}
|
||||
|
||||
Node newNewExpression(uint32_t begin, Node ctor) {
|
||||
Node newExpr = newList(PNK_NEW, begin, JSOP_NEW);
|
||||
if (!newExpr)
|
||||
return newExpr;
|
||||
|
||||
addList(newExpr, ctor);
|
||||
return newExpr;
|
||||
}
|
||||
|
||||
Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
|
||||
if (kind == PNK_ASSIGN)
|
||||
return NodeUnparenthesizedAssignment;
|
||||
|
@ -305,7 +305,7 @@ TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
TokenStream::SourceCoords::fill(const TokenStream::SourceCoords& other)
|
||||
TokenStreamBase::SourceCoords::fill(const TokenStreamBase::SourceCoords& other)
|
||||
{
|
||||
MOZ_ASSERT(lineStartOffsets_.back() == MAX_PTR);
|
||||
MOZ_ASSERT(other.lineStartOffsets_.back() == MAX_PTR);
|
||||
@ -324,7 +324,7 @@ TokenStream::SourceCoords::fill(const TokenStream::SourceCoords& other)
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE uint32_t
|
||||
TokenStream::SourceCoords::lineIndexOf(uint32_t offset) const
|
||||
TokenStreamBase::SourceCoords::lineIndexOf(uint32_t offset) const
|
||||
{
|
||||
uint32_t iMin, iMax, iMid;
|
||||
|
||||
@ -375,14 +375,14 @@ TokenStream::SourceCoords::lineIndexOf(uint32_t offset) const
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TokenStream::SourceCoords::lineNum(uint32_t offset) const
|
||||
TokenStreamBase::SourceCoords::lineNum(uint32_t offset) const
|
||||
{
|
||||
uint32_t lineIndex = lineIndexOf(offset);
|
||||
return lineIndexToNum(lineIndex);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TokenStream::SourceCoords::columnIndex(uint32_t offset) const
|
||||
TokenStreamBase::SourceCoords::columnIndex(uint32_t offset) const
|
||||
{
|
||||
uint32_t lineIndex = lineIndexOf(offset);
|
||||
uint32_t lineStartOffset = lineStartOffsets_[lineIndex];
|
||||
@ -391,8 +391,8 @@ TokenStream::SourceCoords::columnIndex(uint32_t offset) const
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::SourceCoords::lineNumAndColumnIndex(uint32_t offset, uint32_t* lineNum,
|
||||
uint32_t* columnIndex) const
|
||||
TokenStreamBase::SourceCoords::lineNumAndColumnIndex(uint32_t offset, uint32_t* lineNum,
|
||||
uint32_t* columnIndex) const
|
||||
{
|
||||
uint32_t lineIndex = lineIndexOf(offset);
|
||||
*lineNum = lineIndexToNum(lineIndex);
|
||||
@ -427,7 +427,7 @@ TokenStreamBase::TokenStreamBase(JSContext* cx, const ReadOnlyCompileOptions& op
|
||||
}
|
||||
|
||||
TokenStream::TokenStream(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* base, size_t length, StrictModeGetter* smg)
|
||||
const CharT* base, size_t length, StrictModeGetter* smg)
|
||||
: TokenStreamBase(cx, options, smg),
|
||||
userbuf(cx, base, length, options.column),
|
||||
tokenbuf(cx)
|
||||
@ -451,7 +451,7 @@ TokenStream::TokenStream(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
#endif
|
||||
|
||||
bool
|
||||
TokenStream::checkOptions()
|
||||
TokenStreamBase::checkOptions()
|
||||
{
|
||||
// Constrain starting columns to half of the range of a signed 32-bit value,
|
||||
// to avoid overflow.
|
||||
@ -604,7 +604,7 @@ TokenStream::peekChars(int n, char16_t* cp)
|
||||
size_t
|
||||
TokenStream::TokenBuf::findEOLMax(size_t start, size_t max)
|
||||
{
|
||||
const char16_t* p = rawCharPtrAt(start);
|
||||
const CharT* p = rawCharPtrAt(start);
|
||||
|
||||
size_t n = 0;
|
||||
while (true) {
|
||||
@ -622,7 +622,7 @@ TokenStream::TokenBuf::findEOLMax(size_t start, size_t max)
|
||||
bool
|
||||
TokenStream::advance(size_t position)
|
||||
{
|
||||
const char16_t* end = userbuf.rawCharPtrAt(position);
|
||||
const CharT* end = userbuf.rawCharPtrAt(position);
|
||||
while (userbuf.addressOfNextRawChar() < end) {
|
||||
int32_t c;
|
||||
if (!getChar(&c))
|
||||
@ -686,7 +686,7 @@ TokenStream::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32
|
||||
return false;
|
||||
|
||||
if (strictMode) {
|
||||
compileError(Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -694,31 +694,23 @@ TokenStream::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32
|
||||
errorNumber, args);
|
||||
}
|
||||
|
||||
void
|
||||
CompileError::throwError(JSContext* cx)
|
||||
bool
|
||||
TokenStreamBase::compileWarning(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
|
||||
unsigned flags, unsigned errorNumber, va_list args)
|
||||
{
|
||||
if (JSREPORT_IS_WARNING(flags)) {
|
||||
CallWarningReporter(cx, this);
|
||||
return;
|
||||
if (options().werrorOption) {
|
||||
flags &= ~JSREPORT_WARNING;
|
||||
ReportCompileError(cx, Move(metadata), Move(notes), flags, errorNumber, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there's a runtime exception type associated with this error
|
||||
// number, set that as the pending exception. For errors occuring at
|
||||
// compile time, this is very likely to be a JSEXN_SYNTAXERR.
|
||||
//
|
||||
// If an exception is thrown but not caught, the JSREPORT_EXCEPTION
|
||||
// flag will be set in report.flags. Proper behavior for an error
|
||||
// reporter is to ignore a report with this flag for all but top-level
|
||||
// compilation errors. The exception will remain pending, and so long
|
||||
// as the non-top-level "load", "eval", or "compile" native function
|
||||
// returns false, the top-level reporter will eventually receive the
|
||||
// uncaught exception report.
|
||||
ErrorToException(cx, this, nullptr, nullptr);
|
||||
return ReportCompileWarning(cx, Move(metadata), Move(notes), flags, errorNumber, args);
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::computeErrorMetadataNoOffset(ErrorMetadata* err)
|
||||
TokenStreamBase::computeErrorMetadataNoOffset(ErrorMetadata* err)
|
||||
{
|
||||
err->isMuted = mutedErrors;
|
||||
err->filename = filename;
|
||||
err->lineNumber = 0;
|
||||
err->columnNumber = 0;
|
||||
@ -734,6 +726,8 @@ TokenStream::computeErrorMetadata(ErrorMetadata* err, uint32_t offset)
|
||||
return true;
|
||||
}
|
||||
|
||||
err->isMuted = mutedErrors;
|
||||
|
||||
// If this TokenStream doesn't have location information, try to get it
|
||||
// from the caller.
|
||||
if (!filename && !cx->helperThread()) {
|
||||
@ -816,82 +810,6 @@ TokenStream::computeLineOfContext(ErrorMetadata* err, uint32_t offset)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::compileError(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, unsigned flags,
|
||||
unsigned errorNumber, va_list args)
|
||||
{
|
||||
// On the active thread, report the error immediately. When compiling off
|
||||
// thread, save the error so that the thread finishing the parse can report
|
||||
// it later.
|
||||
CompileError tempErr;
|
||||
CompileError* err = &tempErr;
|
||||
if (cx->helperThread() && !cx->addPendingCompileError(&err))
|
||||
return;
|
||||
|
||||
err->notes = Move(notes);
|
||||
err->flags = flags;
|
||||
err->errorNumber = errorNumber;
|
||||
err->isMuted = mutedErrors;
|
||||
|
||||
err->filename = metadata.filename;
|
||||
err->lineno = metadata.lineNumber;
|
||||
err->column = metadata.columnNumber;
|
||||
|
||||
if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext))
|
||||
err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset);
|
||||
|
||||
if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber,
|
||||
nullptr, ArgumentsAreLatin1, err, args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cx->helperThread())
|
||||
err->throwError(cx);
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::compileWarning(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
|
||||
unsigned flags, unsigned errorNumber, va_list args)
|
||||
{
|
||||
if (options().werrorOption) {
|
||||
flags &= ~JSREPORT_WARNING;
|
||||
compileError(Move(metadata), Move(notes), flags, errorNumber, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// On the active thread, report the error immediately. When compiling off
|
||||
// thread, save the error so that the thread finishing the parse can report
|
||||
// it later.
|
||||
CompileError tempErr;
|
||||
CompileError* err = &tempErr;
|
||||
if (cx->helperThread() && !cx->addPendingCompileError(&err))
|
||||
return false;
|
||||
|
||||
err->notes = Move(notes);
|
||||
err->flags = flags;
|
||||
err->errorNumber = errorNumber;
|
||||
err->isMuted = mutedErrors;
|
||||
|
||||
err->filename = metadata.filename;
|
||||
err->lineno = metadata.lineNumber;
|
||||
err->column = metadata.columnNumber;
|
||||
|
||||
if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext))
|
||||
err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset);
|
||||
|
||||
if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber,
|
||||
nullptr, ArgumentsAreLatin1, err, args))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cx->helperThread())
|
||||
err->throwError(cx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportStrictModeError(unsigned errorNumber, ...)
|
||||
{
|
||||
@ -911,13 +829,13 @@ TokenStream::reportError(unsigned errorNumber, ...)
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (computeErrorMetadata(&metadata, currentToken().pos.begin))
|
||||
compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
|
||||
TokenStreamBase::reportErrorNoOffset(unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
@ -925,7 +843,7 @@ TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
|
||||
ErrorMetadata metadata;
|
||||
computeErrorMetadataNoOffset(&metadata);
|
||||
|
||||
compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -968,7 +886,7 @@ TokenStream::error(unsigned errorNumber, ...)
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (computeErrorMetadata(&metadata, currentToken().pos.begin))
|
||||
compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -981,7 +899,7 @@ TokenStream::errorAt(uint32_t offset, unsigned errorNumber, ...)
|
||||
|
||||
ErrorMetadata metadata;
|
||||
if (computeErrorMetadata(&metadata, offset))
|
||||
compileError(Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
ReportCompileError(cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -999,7 +917,7 @@ TokenStream::peekUnicodeEscape(uint32_t* codePoint)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char16_t cp[3];
|
||||
CharT cp[3];
|
||||
uint32_t length;
|
||||
c = getCharIgnoreEOL();
|
||||
if (JS7_ISHEX(c) && peekChars(3, cp) &&
|
||||
@ -1034,7 +952,7 @@ TokenStream::peekExtendedUnicodeEscape(uint32_t* codePoint)
|
||||
c = getCharIgnoreEOL();
|
||||
}
|
||||
|
||||
char16_t cp[6];
|
||||
CharT cp[6];
|
||||
size_t i = 0;
|
||||
uint32_t code = 0;
|
||||
while (JS7_ISHEX(c) && i < 6) {
|
||||
@ -1084,12 +1002,15 @@ TokenStream::matchUnicodeEscapeIdent(uint32_t* codePoint)
|
||||
|
||||
// Helper function which returns true if the first length(q) characters in p are
|
||||
// the same as the characters in q.
|
||||
template<typename CharT>
|
||||
static bool
|
||||
CharsMatch(const char16_t* p, const char* q) {
|
||||
CharsMatch(const CharT* p, const char* q)
|
||||
{
|
||||
while (*q) {
|
||||
if (*p++ != *q++)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1263,7 +1184,7 @@ TokenStream::putIdentInTokenbuf(const char16_t* identStart)
|
||||
{
|
||||
int32_t c;
|
||||
uint32_t qc;
|
||||
const char16_t* tmp = userbuf.addressOfNextRawChar();
|
||||
const CharT* tmp = userbuf.addressOfNextRawChar();
|
||||
userbuf.setAddressOfNextRawChar(identStart);
|
||||
|
||||
tokenbuf.clear();
|
||||
@ -1387,10 +1308,10 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
||||
uint32_t qc;
|
||||
Token* tp;
|
||||
FirstCharKind c1kind;
|
||||
const char16_t* numStart;
|
||||
const CharT* numStart;
|
||||
bool hasExp;
|
||||
DecimalPoint decimalPoint;
|
||||
const char16_t* identStart;
|
||||
const CharT* identStart;
|
||||
bool hadUnicodeEscape;
|
||||
|
||||
// Check if in the middle of a template string. Have to get this out of
|
||||
@ -1523,7 +1444,7 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
||||
// Identifiers containing no Unicode escapes can be processed directly
|
||||
// from userbuf. The rest must use the escapes converted via tokenbuf
|
||||
// before atomizing.
|
||||
const char16_t* chars;
|
||||
const CharT* chars;
|
||||
size_t length;
|
||||
if (hadUnicodeEscape) {
|
||||
if (!putIdentInTokenbuf(identStart))
|
||||
@ -1612,7 +1533,7 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
||||
if (!GetDecimalInteger(cx, numStart, userbuf.addressOfNextRawChar(), &dval))
|
||||
goto error;
|
||||
} else {
|
||||
const char16_t* dummy;
|
||||
const CharT* dummy;
|
||||
if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
|
||||
goto error;
|
||||
}
|
||||
@ -2151,7 +2072,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
||||
break;
|
||||
}
|
||||
|
||||
char16_t cp[4];
|
||||
CharT cp[4];
|
||||
if (peekChars(4, cp) &&
|
||||
JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3]))
|
||||
{
|
||||
@ -2173,7 +2094,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
||||
|
||||
// Hexadecimal character specification.
|
||||
case 'x': {
|
||||
char16_t cp[2];
|
||||
CharT cp[2];
|
||||
if (peekChars(2, cp) && JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
|
||||
c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
|
||||
skipChars(2);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "frontend/TokenKind.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
@ -241,11 +242,6 @@ struct Token
|
||||
}
|
||||
};
|
||||
|
||||
class CompileError : public JSErrorReport {
|
||||
public:
|
||||
void throwError(JSContext* cx);
|
||||
};
|
||||
|
||||
extern const char*
|
||||
ReservedWordToCharZ(PropertyName* str);
|
||||
|
||||
@ -270,37 +266,6 @@ class StrictModeGetter {
|
||||
virtual bool strictMode() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata for a compilation error (or warning) at a particular offset, or at
|
||||
* no offset (i.e. with respect to a script overall).
|
||||
*/
|
||||
struct ErrorMetadata
|
||||
{
|
||||
// The file/URL where the error occurred.
|
||||
const char* filename;
|
||||
|
||||
// The line and column numbers where the error occurred. If the error
|
||||
// is with respect to the entire script and not with respect to a
|
||||
// particular location, these will both be zero.
|
||||
uint32_t lineNumber;
|
||||
uint32_t columnNumber;
|
||||
|
||||
// If the error occurs at a particular location, context surrounding the
|
||||
// location of the error: the line that contained the error, or a small
|
||||
// portion of it if the line is long.
|
||||
//
|
||||
// This information is provided on a best-effort basis: code populating
|
||||
// ErrorMetadata instances isn't obligated to supply this.
|
||||
UniqueTwoByteChars lineOfContext;
|
||||
|
||||
// If |lineOfContext| is non-null, its length.
|
||||
size_t lineLength;
|
||||
|
||||
// If |lineOfContext| is non-null, the offset within it of the token that
|
||||
// triggered the error.
|
||||
size_t tokenOffset;
|
||||
};
|
||||
|
||||
class TokenStreamBase
|
||||
{
|
||||
protected:
|
||||
@ -329,6 +294,8 @@ class TokenStreamBase
|
||||
JSVersion versionNumber() const { return VersionNumber(options().version); }
|
||||
JSVersion versionWithFlags() const { return options().version; }
|
||||
|
||||
MOZ_MUST_USE bool checkOptions();
|
||||
|
||||
protected:
|
||||
PropertyName* reservedWordToPropertyName(TokenKind tt) const;
|
||||
|
||||
@ -583,6 +550,15 @@ class TokenStreamBase
|
||||
|
||||
bool hasLookahead() const { return lookahead > 0; }
|
||||
|
||||
public:
|
||||
MOZ_MUST_USE bool compileWarning(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
|
||||
unsigned flags, unsigned errorNumber, va_list args);
|
||||
|
||||
void reportErrorNoOffset(unsigned errorNumber, ...);
|
||||
|
||||
// Compute error metadata for an error at no offset.
|
||||
void computeErrorMetadataNoOffset(ErrorMetadata* err);
|
||||
|
||||
protected:
|
||||
// Options used for parsing/tokenizing.
|
||||
const ReadOnlyCompileOptions& options_;
|
||||
@ -646,12 +622,11 @@ class TokenStreamBase
|
||||
class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
{
|
||||
public:
|
||||
using CharBuffer = Vector<char16_t, 32>;
|
||||
using CharT = char16_t;
|
||||
using CharBuffer = Vector<CharT, 32>;
|
||||
|
||||
TokenStream(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* base, size_t length, StrictModeGetter* smg);
|
||||
|
||||
MOZ_MUST_USE bool checkOptions();
|
||||
const CharT* base, size_t length, StrictModeGetter* smg);
|
||||
|
||||
const CharBuffer& getTokenbuf() const { return tokenbuf; }
|
||||
|
||||
@ -667,7 +642,6 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
|
||||
// TokenStream-specific error reporters.
|
||||
void reportError(unsigned errorNumber, ...);
|
||||
void reportErrorNoOffset(unsigned errorNumber, ...);
|
||||
|
||||
// Report the given error at the current offset.
|
||||
void error(unsigned errorNumber, ...);
|
||||
@ -685,21 +659,12 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
MOZ_MUST_USE bool computeLineOfContext(ErrorMetadata* err, uint32_t offset);
|
||||
|
||||
public:
|
||||
// Compute error metadata for an error at no offset.
|
||||
void computeErrorMetadataNoOffset(ErrorMetadata* err);
|
||||
|
||||
// Compute error metadata for an error at the given offset.
|
||||
MOZ_MUST_USE bool computeErrorMetadata(ErrorMetadata* err, uint32_t offset);
|
||||
|
||||
// General-purpose error reporters. You should avoid calling these
|
||||
// directly, and instead use the more succinct alternatives (error(),
|
||||
// warning(), &c.) in TokenStream, Parser, and BytecodeEmitter.
|
||||
void compileError(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, unsigned flags,
|
||||
unsigned errorNumber, va_list args);
|
||||
|
||||
MOZ_MUST_USE bool compileWarning(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
|
||||
unsigned flags, unsigned errorNumber, va_list args);
|
||||
|
||||
bool reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
bool strictMode, unsigned errorNumber, va_list args);
|
||||
bool reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
@ -708,8 +673,8 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
JSAtom* getRawTemplateStringAtom() {
|
||||
MOZ_ASSERT(currentToken().type == TOK_TEMPLATE_HEAD ||
|
||||
currentToken().type == TOK_NO_SUBS_TEMPLATE);
|
||||
const char16_t* cur = userbuf.rawCharPtrAt(currentToken().pos.begin + 1);
|
||||
const char16_t* end;
|
||||
const CharT* cur = userbuf.rawCharPtrAt(currentToken().pos.begin + 1);
|
||||
const CharT* end;
|
||||
if (currentToken().type == TOK_TEMPLATE_HEAD) {
|
||||
// Of the form |`...${| or |}...${|
|
||||
end = userbuf.rawCharPtrAt(currentToken().pos.end - 2);
|
||||
@ -720,7 +685,7 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
|
||||
CharBuffer charbuf(cx);
|
||||
while (cur < end) {
|
||||
int32_t ch = *cur;
|
||||
CharT ch = *cur;
|
||||
if (ch == '\r') {
|
||||
ch = '\n';
|
||||
if ((cur + 1 < end) && (*(cur + 1) == '\n'))
|
||||
@ -759,7 +724,7 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
}
|
||||
|
||||
static JSAtom* atomize(JSContext* cx, CharBuffer& cb);
|
||||
MOZ_MUST_USE bool putIdentInTokenbuf(const char16_t* identStart);
|
||||
MOZ_MUST_USE bool putIdentInTokenbuf(const CharT* identStart);
|
||||
|
||||
public:
|
||||
// Advance to the next token. If the token stream encountered an error,
|
||||
@ -914,7 +879,7 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
private:
|
||||
Position(const Position&) = delete;
|
||||
friend class TokenStream;
|
||||
const char16_t* buf;
|
||||
const CharT* buf;
|
||||
Flags flags;
|
||||
unsigned lineno;
|
||||
size_t linebase;
|
||||
@ -929,11 +894,11 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
void seek(const Position& pos);
|
||||
MOZ_MUST_USE bool seek(const Position& pos, const TokenStream& other);
|
||||
|
||||
const char16_t* rawCharPtrAt(size_t offset) const {
|
||||
const CharT* rawCharPtrAt(size_t offset) const {
|
||||
return userbuf.rawCharPtrAt(offset);
|
||||
}
|
||||
|
||||
const char16_t* rawLimit() const {
|
||||
const CharT* rawLimit() const {
|
||||
return userbuf.limit();
|
||||
}
|
||||
|
||||
@ -950,7 +915,7 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
// begins, the offset of |buf[0]|.
|
||||
class TokenBuf {
|
||||
public:
|
||||
TokenBuf(JSContext* cx, const char16_t* buf, size_t length, size_t startOffset)
|
||||
TokenBuf(JSContext* cx, const CharT* buf, size_t length, size_t startOffset)
|
||||
: base_(buf),
|
||||
startOffset_(startOffset),
|
||||
limit_(buf + length),
|
||||
@ -973,25 +938,25 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
return startOffset_ + mozilla::PointerRangeSize(base_, ptr);
|
||||
}
|
||||
|
||||
const char16_t* rawCharPtrAt(size_t offset) const {
|
||||
const CharT* rawCharPtrAt(size_t offset) const {
|
||||
MOZ_ASSERT(startOffset_ <= offset);
|
||||
MOZ_ASSERT(offset - startOffset_ <= mozilla::PointerRangeSize(base_, limit_));
|
||||
return base_ + (offset - startOffset_);
|
||||
}
|
||||
|
||||
const char16_t* limit() const {
|
||||
const CharT* limit() const {
|
||||
return limit_;
|
||||
}
|
||||
|
||||
char16_t getRawChar() {
|
||||
CharT getRawChar() {
|
||||
return *ptr++; // this will nullptr-crash if poisoned
|
||||
}
|
||||
|
||||
char16_t peekRawChar() const {
|
||||
CharT peekRawChar() const {
|
||||
return *ptr; // this will nullptr-crash if poisoned
|
||||
}
|
||||
|
||||
bool matchRawChar(char16_t c) {
|
||||
bool matchRawChar(CharT c) {
|
||||
if (*ptr == c) { // this will nullptr-crash if poisoned
|
||||
ptr++;
|
||||
return true;
|
||||
@ -999,7 +964,7 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matchRawCharBackwards(char16_t c) {
|
||||
bool matchRawCharBackwards(CharT c) {
|
||||
MOZ_ASSERT(ptr); // make sure it hasn't been poisoned
|
||||
if (*(ptr - 1) == c) {
|
||||
ptr--;
|
||||
@ -1013,13 +978,13 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
ptr--;
|
||||
}
|
||||
|
||||
const char16_t* addressOfNextRawChar(bool allowPoisoned = false) const {
|
||||
const CharT* addressOfNextRawChar(bool allowPoisoned = false) const {
|
||||
MOZ_ASSERT_IF(!allowPoisoned, ptr); // make sure it hasn't been poisoned
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Use this with caution!
|
||||
void setAddressOfNextRawChar(const char16_t* a, bool allowPoisoned = false) {
|
||||
void setAddressOfNextRawChar(const CharT* a, bool allowPoisoned = false) {
|
||||
MOZ_ASSERT_IF(!allowPoisoned, a);
|
||||
ptr = a;
|
||||
}
|
||||
@ -1040,10 +1005,10 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
size_t findEOLMax(size_t start, size_t max);
|
||||
|
||||
private:
|
||||
const char16_t* base_; // base of buffer
|
||||
const CharT* base_; // base of buffer
|
||||
uint32_t startOffset_; // offset of base_[0]
|
||||
const char16_t* limit_; // limit for quick bounds check
|
||||
const char16_t* ptr; // next char to get
|
||||
const CharT* limit_; // limit for quick bounds check
|
||||
const CharT* ptr; // next char to get
|
||||
};
|
||||
|
||||
MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
|
||||
@ -1065,13 +1030,13 @@ class MOZ_STACK_CLASS TokenStream final : public TokenStreamBase
|
||||
uint32_t matchUnicodeEscapeIdStart(uint32_t* codePoint);
|
||||
bool matchUnicodeEscapeIdent(uint32_t* codePoint);
|
||||
bool matchTrailForLeadSurrogate(char16_t lead, char16_t* trail, uint32_t* codePoint);
|
||||
bool peekChars(int n, char16_t* cp);
|
||||
bool peekChars(int n, CharT* cp);
|
||||
|
||||
MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
||||
const char* directive, uint8_t directiveLength,
|
||||
const char* errorMsgPragma,
|
||||
UniquePtr<char16_t[], JS::FreePolicy>* destination);
|
||||
UniquePtr<CharT[], JS::FreePolicy>* destination);
|
||||
MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
|
||||
|
@ -134,13 +134,6 @@ js::Nursery::Nursery(JSRuntime* rt)
|
||||
bool
|
||||
js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGC& lock)
|
||||
{
|
||||
/* maxNurseryBytes parameter is rounded down to a multiple of chunk size. */
|
||||
maxNurseryChunks_ = maxNurseryBytes >> ChunkShift;
|
||||
|
||||
/* If no chunks are specified then the nursery is permanently disabled. */
|
||||
if (maxNurseryChunks_ == 0)
|
||||
return true;
|
||||
|
||||
if (!mallocedBuffers.init())
|
||||
return false;
|
||||
|
||||
@ -148,6 +141,13 @@ js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGC& lock)
|
||||
if (!freeMallocedBuffersTask || !freeMallocedBuffersTask->init())
|
||||
return false;
|
||||
|
||||
/* maxNurseryBytes parameter is rounded down to a multiple of chunk size. */
|
||||
maxNurseryChunks_ = maxNurseryBytes >> ChunkShift;
|
||||
|
||||
/* If no chunks are specified then the nursery is permanently disabled. */
|
||||
if (maxNurseryChunks_ == 0)
|
||||
return true;
|
||||
|
||||
AutoMaybeStartBackgroundAllocation maybeBgAlloc;
|
||||
updateNumChunksLocked(1, maybeBgAlloc, lock);
|
||||
if (numChunks() == 0)
|
||||
|
@ -67,7 +67,7 @@ using namespace js::jit;
|
||||
|
||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
Mode mode, int registers_to_save)
|
||||
: RegExpMacroAssembler(*alloc, shared, registers_to_save),
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, registers_to_save),
|
||||
cx(cx), mode_(mode)
|
||||
{
|
||||
// Find physical registers for each compiler register.
|
||||
|
@ -1808,7 +1808,7 @@ irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompile
|
||||
native_assembler.emplace(cx, &alloc, shared, mode, (data->capture_count + 1) * 2);
|
||||
assembler = native_assembler.ptr();
|
||||
} else {
|
||||
interpreted_assembler.emplace(&alloc, shared, (data->capture_count + 1) * 2);
|
||||
interpreted_assembler.emplace(cx, &alloc, shared, (data->capture_count + 1) * 2);
|
||||
assembler = interpreted_assembler.ptr();
|
||||
}
|
||||
|
||||
|
@ -97,9 +97,10 @@ irregexp::CaseInsensitiveCompareUCStrings(const char16_t* substring1,
|
||||
const char16_t* substring2,
|
||||
size_t byteLength);
|
||||
|
||||
InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(LifoAlloc* alloc, RegExpShared* shared,
|
||||
InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc,
|
||||
RegExpShared* shared,
|
||||
size_t numSavedRegisters)
|
||||
: RegExpMacroAssembler(*alloc, shared, numSavedRegisters),
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, numSavedRegisters),
|
||||
pc_(0),
|
||||
advance_current_start_(0),
|
||||
advance_current_offset_(0),
|
||||
|
@ -41,13 +41,14 @@ namespace irregexp {
|
||||
class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
RegExpMacroAssembler(LifoAlloc& alloc, RegExpShared* shared, size_t numSavedRegisters)
|
||||
RegExpMacroAssembler(JSContext* cx, LifoAlloc& alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters)
|
||||
: slow_safe_compiler_(false),
|
||||
global_mode_(NOT_GLOBAL),
|
||||
alloc_(alloc),
|
||||
num_registers_(numSavedRegisters),
|
||||
num_saved_registers_(numSavedRegisters),
|
||||
shared(shared)
|
||||
shared(cx, shared)
|
||||
{}
|
||||
|
||||
enum StackCheckFlag {
|
||||
@ -215,7 +216,7 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
}
|
||||
|
||||
public:
|
||||
RegExpShared* shared;
|
||||
RootedRegExpShared shared;
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
@ -230,7 +231,8 @@ CaseInsensitiveCompareUCStrings(const CharT* substring1, const CharT* substring2
|
||||
class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
InterpretedRegExpMacroAssembler(LifoAlloc* alloc, RegExpShared* shared, size_t numSavedRegisters);
|
||||
InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters);
|
||||
~InterpretedRegExpMacroAssembler();
|
||||
|
||||
// Inherited virtual methods.
|
||||
|
@ -246,6 +246,22 @@ BaselineCacheIRCompiler::emitGuardGroup()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitGuardGroupHasUnanalyzedNewScript()
|
||||
{
|
||||
Address addr(stubAddress(reader.stubOffset()));
|
||||
AutoScratchRegister scratch1(allocator, masm);
|
||||
AutoScratchRegister scratch2(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(addr, scratch1);
|
||||
masm.guardGroupHasUnanalyzedNewScript(scratch1, scratch2, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitGuardProto()
|
||||
{
|
||||
|
@ -1021,6 +1021,11 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
||||
ICStubEngine::Baseline, frame->script(),
|
||||
stub, &attached);
|
||||
if (newStub) {
|
||||
if (gen.shouldNotePreliminaryObjectStub())
|
||||
newStub->toCacheIR_Updated()->notePreliminaryObject();
|
||||
else if (gen.shouldUnlinkPreliminaryObjectStubs())
|
||||
StripPreliminaryObjectStubs(cx, stub);
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
|
||||
SetUpdateStubData(newStub->toCacheIR_Updated(), gen.typeCheckInfo());
|
||||
return true;
|
||||
@ -1589,6 +1594,11 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
ICStubEngine::Baseline, frame->script(),
|
||||
stub, &attached);
|
||||
if (newStub) {
|
||||
if (gen.shouldNotePreliminaryObjectStub())
|
||||
newStub->toCacheIR_Updated()->notePreliminaryObject();
|
||||
else if (gen.shouldUnlinkPreliminaryObjectStubs())
|
||||
StripPreliminaryObjectStubs(cx, stub);
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
|
||||
SetUpdateStubData(newStub->toCacheIR_Updated(), gen.typeCheckInfo());
|
||||
}
|
||||
|
@ -3143,19 +3143,24 @@ SetPropIRGenerator::tryAttachAddSlotStub(HandleObjectGroup oldGroup, HandleShape
|
||||
}
|
||||
}
|
||||
|
||||
// Don't attach if we are adding a property to an object which the new
|
||||
// script properties analysis hasn't been performed for yet, as there
|
||||
// may be a shape change required here afterwards.
|
||||
if (oldGroup->newScript() && !oldGroup->newScript()->analyzed()) {
|
||||
*isTemporarilyUnoptimizable_ = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjOperandId objId = writer.guardIsObject(objValId);
|
||||
maybeEmitIdGuard(id);
|
||||
|
||||
writer.guardGroup(objId, oldGroup);
|
||||
|
||||
// If we are adding a property to an object for which the new script
|
||||
// properties analysis hasn't been performed yet, make sure the stub fails
|
||||
// after we run the analysis as a group change may be required here. The
|
||||
// group change is not required for correctness but improves type
|
||||
// information elsewhere.
|
||||
if (oldGroup->newScript() && !oldGroup->newScript()->analyzed()) {
|
||||
writer.guardGroupHasUnanalyzedNewScript(oldGroup);
|
||||
MOZ_ASSERT(IsPreliminaryObject(obj));
|
||||
preliminaryObjectAction_ = PreliminaryObjectAction::NotePreliminary;
|
||||
} else {
|
||||
preliminaryObjectAction_ = PreliminaryObjectAction::Unlink;
|
||||
}
|
||||
|
||||
// Shape guard the holder.
|
||||
ObjOperandId holderId = objId;
|
||||
if (!obj->isNative()) {
|
||||
|
@ -176,6 +176,7 @@ extern const char* CacheKindNames[];
|
||||
_(GuardAndLoadUnboxedExpando) \
|
||||
_(GuardAndGetIndexFromString) \
|
||||
_(GuardHasGetterSetter) \
|
||||
_(GuardGroupHasUnanalyzedNewScript) \
|
||||
_(LoadObject) \
|
||||
_(LoadProto) \
|
||||
_(LoadEnclosingEnvironment) \
|
||||
@ -544,6 +545,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
||||
writeOpWithOperandId(CacheOp::GuardHasGetterSetter, obj);
|
||||
addStubField(uintptr_t(shape), StubField::Type::Shape);
|
||||
}
|
||||
void guardGroupHasUnanalyzedNewScript(ObjectGroup* group) {
|
||||
writeOp(CacheOp::GuardGroupHasUnanalyzedNewScript);
|
||||
addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
|
||||
}
|
||||
|
||||
void loadFrameCalleeResult() {
|
||||
writeOp(CacheOp::LoadFrameCalleeResult);
|
||||
|
@ -255,7 +255,7 @@ CacheRegisterAllocator::defineValueRegister(MacroAssembler& masm, ValOperandId v
|
||||
}
|
||||
|
||||
void
|
||||
CacheRegisterAllocator::freeDeadOperandRegisters()
|
||||
CacheRegisterAllocator::freeDeadOperandLocations(MacroAssembler& masm)
|
||||
{
|
||||
// See if any operands are dead so we can reuse their registers. Note that
|
||||
// we skip the input operands, as those are also used by failure paths, and
|
||||
@ -272,9 +272,13 @@ CacheRegisterAllocator::freeDeadOperandRegisters()
|
||||
case OperandLocation::ValueReg:
|
||||
availableRegs_.add(loc.valueReg());
|
||||
break;
|
||||
case OperandLocation::Uninitialized:
|
||||
case OperandLocation::PayloadStack:
|
||||
masm.propagateOOM(freePayloadSlots_.append(loc.payloadStack()));
|
||||
break;
|
||||
case OperandLocation::ValueStack:
|
||||
masm.propagateOOM(freeValueSlots_.append(loc.valueStack()));
|
||||
break;
|
||||
case OperandLocation::Uninitialized:
|
||||
case OperandLocation::BaselineFrame:
|
||||
case OperandLocation::Constant:
|
||||
case OperandLocation::DoubleReg:
|
||||
@ -297,13 +301,15 @@ CacheRegisterAllocator::discardStack(MacroAssembler& masm)
|
||||
masm.addToStackPtr(Imm32(stackPushed_));
|
||||
stackPushed_ = 0;
|
||||
}
|
||||
freePayloadSlots_.clear();
|
||||
freeValueSlots_.clear();
|
||||
}
|
||||
|
||||
Register
|
||||
CacheRegisterAllocator::allocateRegister(MacroAssembler& masm)
|
||||
{
|
||||
if (availableRegs_.empty())
|
||||
freeDeadOperandRegisters();
|
||||
freeDeadOperandLocations(masm);
|
||||
|
||||
if (availableRegs_.empty()) {
|
||||
// Still no registers available, try to spill unused operands to
|
||||
@ -356,7 +362,7 @@ CacheRegisterAllocator::allocateFixedRegister(MacroAssembler& masm, Register reg
|
||||
// still available.
|
||||
MOZ_ASSERT(!currentOpRegs_.has(reg), "Register is in use");
|
||||
|
||||
freeDeadOperandRegisters();
|
||||
freeDeadOperandLocations(masm);
|
||||
|
||||
if (availableRegs_.has(reg)) {
|
||||
availableRegs_.take(reg);
|
||||
@ -562,6 +568,14 @@ CacheRegisterAllocator::spillOperandToStack(MacroAssembler& masm, OperandLocatio
|
||||
MOZ_ASSERT(loc >= operandLocations_.begin() && loc < operandLocations_.end());
|
||||
|
||||
if (loc->kind() == OperandLocation::ValueReg) {
|
||||
if (!freeValueSlots_.empty()) {
|
||||
uint32_t stackPos = freeValueSlots_.popCopy();
|
||||
MOZ_ASSERT(stackPos <= stackPushed_);
|
||||
masm.storeValue(loc->valueReg(), Address(masm.getStackPointer(),
|
||||
stackPushed_ - stackPos));
|
||||
loc->setValueStack(stackPos);
|
||||
return;
|
||||
}
|
||||
stackPushed_ += sizeof(js::Value);
|
||||
masm.pushValue(loc->valueReg());
|
||||
loc->setValueStack(stackPushed_);
|
||||
@ -570,6 +584,14 @@ CacheRegisterAllocator::spillOperandToStack(MacroAssembler& masm, OperandLocatio
|
||||
|
||||
MOZ_ASSERT(loc->kind() == OperandLocation::PayloadReg);
|
||||
|
||||
if (!freePayloadSlots_.empty()) {
|
||||
uint32_t stackPos = freePayloadSlots_.popCopy();
|
||||
MOZ_ASSERT(stackPos <= stackPushed_);
|
||||
masm.storePtr(loc->payloadReg(), Address(masm.getStackPointer(),
|
||||
stackPushed_ - stackPos));
|
||||
loc->setPayloadStack(stackPos, loc->payloadType());
|
||||
return;
|
||||
}
|
||||
stackPushed_ += sizeof(uintptr_t);
|
||||
masm.push(loc->payloadReg());
|
||||
loc->setPayloadStack(stackPushed_, loc->payloadType());
|
||||
@ -617,6 +639,7 @@ CacheRegisterAllocator::popPayload(MacroAssembler& masm, OperandLocation* loc, R
|
||||
} else {
|
||||
MOZ_ASSERT(loc->payloadStack() < stackPushed_);
|
||||
masm.loadPtr(Address(masm.getStackPointer(), stackPushed_ - loc->payloadStack()), dest);
|
||||
masm.propagateOOM(freePayloadSlots_.append(loc->payloadStack()));
|
||||
}
|
||||
|
||||
loc->setPayloadReg(dest, loc->payloadType());
|
||||
@ -636,6 +659,7 @@ CacheRegisterAllocator::popValue(MacroAssembler& masm, OperandLocation* loc, Val
|
||||
} else {
|
||||
MOZ_ASSERT(loc->valueStack() < stackPushed_);
|
||||
masm.loadValue(Address(masm.getStackPointer(), stackPushed_ - loc->valueStack()), dest);
|
||||
masm.propagateOOM(freeValueSlots_.append(loc->valueStack()));
|
||||
}
|
||||
|
||||
loc->setValueReg(dest);
|
||||
|
@ -252,6 +252,10 @@ class MOZ_RAII CacheRegisterAllocator
|
||||
// The current location of each operand.
|
||||
Vector<OperandLocation, 8, SystemAllocPolicy> operandLocations_;
|
||||
|
||||
// Free lists for value- and payload-slots on stack
|
||||
Vector<uint32_t, 2, SystemAllocPolicy> freeValueSlots_;
|
||||
Vector<uint32_t, 2, SystemAllocPolicy> freePayloadSlots_;
|
||||
|
||||
// The registers allocated while emitting the current CacheIR op.
|
||||
// This prevents us from allocating a register and then immediately
|
||||
// clobbering it for something else, while we're still holding on to it.
|
||||
@ -280,7 +284,7 @@ class MOZ_RAII CacheRegisterAllocator
|
||||
CacheRegisterAllocator(const CacheRegisterAllocator&) = delete;
|
||||
CacheRegisterAllocator& operator=(const CacheRegisterAllocator&) = delete;
|
||||
|
||||
void freeDeadOperandRegisters();
|
||||
void freeDeadOperandLocations(MacroAssembler& masm);
|
||||
|
||||
void spillOperandToStack(MacroAssembler& masm, OperandLocation* loc);
|
||||
void spillOperandToStackOrRegister(MacroAssembler& masm, OperandLocation* loc);
|
||||
|
@ -192,7 +192,7 @@ CacheRegisterAllocator::saveIonLiveRegisters(MacroAssembler& masm, LiveRegisterS
|
||||
// work. Try to keep it simple by taking one small step at a time.
|
||||
|
||||
// Step 1. Discard any dead operands so we can reuse their registers.
|
||||
freeDeadOperandRegisters();
|
||||
freeDeadOperandLocations(masm);
|
||||
|
||||
// Step 2. Figure out the size of our live regs.
|
||||
size_t sizeOfLiveRegsInBytes =
|
||||
@ -292,6 +292,8 @@ CacheRegisterAllocator::saveIonLiveRegisters(MacroAssembler& masm, LiveRegisterS
|
||||
}
|
||||
masm.PushRegsInMask(liveRegs);
|
||||
}
|
||||
freePayloadSlots_.clear();
|
||||
freeValueSlots_.clear();
|
||||
|
||||
MOZ_ASSERT(masm.framePushed() == ionScript->frameSize() + sizeOfLiveRegsInBytes);
|
||||
|
||||
@ -535,6 +537,22 @@ IonCacheIRCompiler::emitGuardGroup()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitGuardGroupHasUnanalyzedNewScript()
|
||||
{
|
||||
ObjectGroup* group = groupStubField(reader.stubOffset());
|
||||
AutoScratchRegister scratch1(allocator, masm);
|
||||
AutoScratchRegister scratch2(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.movePtr(ImmGCPtr(group), scratch1);
|
||||
masm.guardGroupHasUnanalyzedNewScript(scratch1, scratch2, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitGuardProto()
|
||||
{
|
||||
|
@ -2272,6 +2272,22 @@ MTypeBarrier::congruentTo(const MDefinition* def) const
|
||||
return congruentIfOperandsEqual(other);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
MTypeBarrier::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
MIRType type = resultTypeSet()->getKnownMIRType();
|
||||
if (type == MIRType::Value || type == MIRType::Object)
|
||||
return this;
|
||||
|
||||
if (!input()->isConstant())
|
||||
return this;
|
||||
|
||||
if (input()->type() != type)
|
||||
return this;
|
||||
|
||||
return input();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
MPhi::assertLoopPhi() const
|
||||
|
@ -12825,6 +12825,7 @@ class MTypeBarrier
|
||||
BarrierKind barrierKind() const {
|
||||
return barrierKind_;
|
||||
}
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
|
||||
bool alwaysBails() const {
|
||||
// If mirtype of input doesn't agree with mirtype of barrier,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user