Merge m-c to autoland, a=merge

MozReview-Commit-ID: D96bIJACwZe
This commit is contained in:
Wes Kocher 2017-08-15 19:16:12 -07:00
commit 3945278423
188 changed files with 3919 additions and 1971 deletions

View File

@ -1088,6 +1088,14 @@ function _loadURIWithFlags(browser, uri, params) {
}
let mustChangeProcess = requiredRemoteType != currentRemoteType;
let newFrameloader = false;
if (browser.getAttribute("isPreloadBrowser") == "true" && uri != "about:newtab") {
// Leaving about:newtab from a used to be preloaded browser should run the process
// selecting algorithm again.
mustChangeProcess = true;
newFrameloader = true;
browser.removeAttribute("isPreloadBrowser");
}
// !requiredRemoteType means we're loading in the parent/this process.
if (!requiredRemoteType) {
@ -1122,7 +1130,8 @@ function _loadURIWithFlags(browser, uri, params) {
referrer: referrer ? referrer.spec : null,
referrerPolicy,
remoteType: requiredRemoteType,
postData
postData,
newFrameloader,
}
if (params.userContextId) {
@ -1167,6 +1176,11 @@ function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) {
// Called when a docshell has attempted to load a page in an incorrect process.
// This function is responsible for loading the page in the correct process.
function RedirectLoad({ target: browser, data }) {
if (browser.getAttribute("isPreloadBrowser") == "true") {
browser.removeAttribute("isPreloadBrowser");
data.loadOptions.newFrameloader = true;
}
if (data.loadOptions.reloadInFreshProcess) {
// Convert the fresh process load option into a large allocation remote type
// to use common processing from this point.
@ -5236,8 +5250,9 @@ nsBrowserAccess.prototype = {
return browser;
},
createContentWindow(aURI, aOpener, aWhere, aFlags) {
return this.getContentWindowOrOpenURI(null, aOpener, aWhere, aFlags);
createContentWindow(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
return this.getContentWindowOrOpenURI(null, aOpener, aWhere, aFlags,
aTriggeringPrincipal);
},
openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {

View File

@ -2118,6 +2118,10 @@
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
}
if (aParams.isPreloadBrowser) {
b.setAttribute("isPreloadBrowser", "true");
}
if (this.hasAttribute("selectmenulist"))
b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));

View File

@ -20,11 +20,13 @@ var tests = [
location: "http://test1.example.org/",
effectiveHost: "test1.example.org"
},
/* This part is perma-crashing, see: Bug 1315092
{
name: "view-source",
location: "view-source:http://example.com/",
effectiveHost: null
},
*/
{
name: "normal HTTPS",
location: "https://example.com/",

View File

@ -6,7 +6,7 @@
*/
add_task(async function() {
let input = "i-definitely-dont-exist.example.com";
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
// NB: CPOW usage because new tab pages can be preloaded, in which case no
// load events fire.
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
@ -29,7 +29,7 @@ add_task(async function() {
add_task(async function() {
let input = "To be or not to be-that is the question";
await SpecialPowers.pushPrefEnv({set: [["keyword.enabled", false]]});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
// NB: CPOW usage because new tab pages can be preloaded, in which case no
// load events fire.
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)

View File

@ -243,6 +243,14 @@ this.E10SUtils = {
this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI);
}
if (sessionHistory.count == 1 && webNav.currentURI.spec == "about:newtab") {
// This is possibly a preloaded browser and we're about to navigate away for
// the first time. On the child side there is no way to tell for sure if that
// is the case, so let's redirect this request to the parent to decide if a new
// process is needed.
return false;
}
// If the URI can be loaded in the current process then continue
return this.shouldLoadURIInThisProcess(aURI);
},

View File

@ -763,6 +763,11 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
}
}
if (!first_executable) {
fprintf(stderr, "Couldn't find executable section. Skipping\n");
return -1;
}
unsigned int old_exec = first_executable->getOffset();
relhack->insertBefore(section);

View File

@ -21839,8 +21839,10 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = function (name, props) {
// eslint-disable-line
if (!svg[name]) {
throw new Error("Unknown SVG: " + name);
console.warn("Unknown SVG: " + name);
return null;
}
var className = name;
if (props && props.className) {
className = `${name} ${props.className}`;

View File

@ -319,6 +319,11 @@ ObjectActor.prototype = {
let obj = this.obj;
let level = 0, i = 0;
// Do not search safe getters in proxy objects.
if (obj.isProxy) {
return safeGetterValues;
}
// Most objects don't have any safe getters but inherit some from their
// prototype. Avoid calling getOwnPropertyNames on objects that may have
// many properties like Array, strings or js objects. That to avoid
@ -329,7 +334,8 @@ ObjectActor.prototype = {
level++;
}
while (obj) {
// Stop iterating when the prototype chain ends or a proxy is found.
while (obj && !obj.isProxy) {
let getters = this._findSafeGetters(obj);
for (let name of getters) {
// Avoid overwriting properties from prototypes closer to this.obj. Also

View File

@ -0,0 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable no-shadow, max-nested-callbacks */
"use strict";
var gDebuggee;
var gClient;
var gThreadClient;
var gCallback;
function run_test() {
run_test_with_server(DebuggerServer, function () {
run_test_with_server(WorkerDebuggerServer, do_test_finished);
});
do_test_pending();
}
function addTestNullPrincipalGlobal(name, server = DebuggerServer) {
// System principal objects are considered safe even when not wrapped in Xray,
// and therefore proxy traps may run. So the test needs to use a null principal.
let global = Cu.Sandbox(null);
global.__name = name;
server.addTestGlobal(global);
return global;
}
async function run_test_with_server(server, callback) {
gCallback = callback;
initTestDebuggerServer(server);
gDebuggee = addTestNullPrincipalGlobal("test-grips", server);
gDebuggee.eval(function stopMe(arg1, arg2) {
debugger;
}.toString());
gClient = new DebuggerClient(server.connectPipe());
await gClient.connect();
const [,, threadClient] = await attachTestTabAndResume(gClient, "test-grips");
gThreadClient = threadClient;
test_proxy_grip();
}
async function test_proxy_grip() {
gThreadClient.addOneTimeListener("paused", async function (event, packet) {
let [proxyGrip, inheritsProxyGrip] = packet.frame.arguments;
// Check the grip of the proxy object.
check_proxy_grip(proxyGrip);
// Retrieve the properties of the object which inherits from a proxy,
// and check the grip of its prototype.
let objClient = gThreadClient.pauseGrip(inheritsProxyGrip);
let response = await objClient.getPrototypeAndProperties();
check_prototype_and_properties(response);
// Check that none of the above ran proxy traps.
let trapDidRun = gDebuggee.eval("trapDidRun");
strictEqual(trapDidRun, false, "No proxy trap did run.");
await gThreadClient.resume();
await gClient.close();
gCallback();
});
gDebuggee.eval(`{
var trapDidRun = false;
var proxy = new Proxy({}, new Proxy({}, {get: (_, trap) => {
trapDidRun = true;
throw new Error("proxy " + trap + " trap was called.");
}}));
var inheritsProxy = Object.create(proxy, {x:{value:1}});
stopMe(proxy, inheritsProxy);
}`);
}
function check_proxy_grip(grip) {
strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
ok(grip.proxyTarget, "There is a [[ProxyTarget]] grip.");
ok(grip.proxyHandler, "There is a [[ProxyHandler]] grip.");
const {preview} = grip;
strictEqual(preview.ownPropertiesLength, 2, "The preview has 2 properties.");
let target = preview.ownProperties["<target>"].value;
strictEqual(target, grip.proxyTarget, "<target> contains the [[ProxyTarget]].");
let handler = preview.ownProperties["<handler>"].value;
strictEqual(handler, grip.proxyHandler, "<handler> contains the [[ProxyHandler]].");
}
function check_prototype_and_properties(response) {
let ownPropertiesLength = Reflect.ownKeys(response.ownProperties).length;
strictEqual(ownPropertiesLength, 1, "1 own property was retrieved.");
strictEqual(response.ownProperties.x.value, 1, "The property has the right value.");
check_proxy_grip(response.prototype);
}

View File

@ -172,6 +172,7 @@ reason = only ran on B2G
[test_objectgrips-14.js]
[test_objectgrips-15.js]
[test_objectgrips-16.js]
[test_objectgrips-17.js]
[test_promise_state-01.js]
[test_promise_state-02.js]
[test_promise_state-03.js]

View File

@ -17,6 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=565388
/** Test for Bug 565388 **/
SimpleTest.waitForExplicitFinish();
function test() {
var Ci = Components.interfaces;
var Cc = Components.classes;
@ -71,6 +72,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=565388
});
win.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
}
addLoadEvent(function onLoad() {
SpecialPowers.pushPrefEnv({"set": [
["security.data_uri.unique_opaque_origin", false]]}, test);
});
]]>
</script>

View File

@ -2231,6 +2231,7 @@ GK_ATOM(DisplayPortMargins, "_displayportmargins")
GK_ATOM(DisplayPortBase, "_displayportbase")
GK_ATOM(AsyncScrollLayerCreationFailed, "_asyncscrolllayercreationfailed")
GK_ATOM(forcemessagemanager, "forcemessagemanager")
GK_ATOM(isPreloadBrowser, "isPreloadBrowser")
// Names for system metrics
GK_ATOM(color_picker_available, "color-picker-available")

View File

@ -1586,6 +1586,9 @@ private:
// Set if the element might have any kind of anonymous content children,
// which would not be found through the element's children list.
ElementMayHaveAnonymousChildren,
// Set if this node has at some point (and may still have)
// display:none or display:contents children.
NodeMayHaveChildrenWithLayoutBoxesDisabled,
// Guard value
BooleanFlagCount
};
@ -1728,6 +1731,19 @@ public:
void SetMayHaveAnonymousChildren() { SetBoolFlag(ElementMayHaveAnonymousChildren); }
bool MayHaveAnonymousChildren() const { return GetBoolFlag(ElementMayHaveAnonymousChildren); }
void SetMayHaveChildrenWithLayoutBoxesDisabled()
{
SetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
}
void UnsetMayHaveChildrenWithLayoutBoxesDisabled()
{
ClearBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
}
bool MayHaveChildrenWithLayoutBoxesDisabled() const
{
return GetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
}
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetIsInDocument() { SetBoolFlag(IsInDocument); }

View File

@ -1,6 +1,7 @@
[DEFAULT]
support-files =
audio.ogg
dummy.html
empty.html
file_audioLoop.html
file_audioLoopInIframe.html
@ -35,6 +36,7 @@ tags = mcb
[browser_force_process_selector.js]
skip-if = !e10s # this only makes sense with e10s-multi
[browser_messagemanager_loadprocessscript.js]
[browser_aboutnewtab_process_selection.js]
[browser_messagemanager_targetframeloader.js]
[browser_messagemanager_unload.js]
[browser_pagehide_on_tab_close.js]

View File

@ -0,0 +1,76 @@
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
var ppmm = Services.ppmm;
add_task(async function(){
// We want to count processes in this test, so let's disable the pre-allocated process manager.
await SpecialPowers.pushPrefEnv({"set": [
["dom.ipc.processPrelaunch.enabled", false],
["dom.ipc.processCount", 10],
["dom.ipc.keepProcessesAlive.web", 10],
]});
});
// Ensure that the preloaded browser exists, and it's finished loading.
async function ensurePreloaded(gBrowser) {
gBrowser._createPreloadBrowser();
// We cannot use the regular BrowserTestUtils helper for waiting here, since that
// would try to insert the preloaded browser, which would only break things.
await BrowserTestUtils.waitForCondition( () => {
return gBrowser._preloadedBrowser.contentDocument.readyState == "complete";
});
}
add_task(async function(){
// This test is only relevant in e10s.
if (!gMultiProcessBrowser)
return;
ppmm.releaseCachedProcesses();
// Wait for the preloaded browser to load.
await ensurePreloaded(gBrowser);
// Store the number of processes (note: +1 for the parent process).
const { childCount: originalChildCount } = ppmm;
// Use the preloaded browser and create another one.
BrowserOpenTab();
let tab1 = gBrowser.selectedTab;
await ensurePreloaded(gBrowser);
// Check that the process count did not change.
is(ppmm.childCount, originalChildCount, "Preloaded browser should not create a new content process.")
// Let's do another round.
BrowserOpenTab();
let tab2 = gBrowser.selectedTab;
await ensurePreloaded(gBrowser);
// Check that the process count did not change.
is(ppmm.childCount, originalChildCount, "Preloaded browser should (still) not create a new content process.")
// Navigate to a content page from the parent side.
tab2.linkedBrowser.loadURI(TEST_URL);
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, TEST_URL);
is(ppmm.childCount, originalChildCount + 1,
"Navigating away from the preloaded browser (parent side) should create a new content process.")
// Navigate to a content page from the child side.
await BrowserTestUtils.switchTab(gBrowser, tab1);
await ContentTask.spawn(tab1.linkedBrowser, null, async function() {
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
content.location.href = TEST_URL;
});
await BrowserTestUtils.browserLoaded(tab1.linkedBrowser, false, TEST_URL);
is(ppmm.childCount, originalChildCount + 2,
"Navigating away from the preloaded browser (child side) should create a new content process.")
await BrowserTestUtils.removeTab(tab1);
await BrowserTestUtils.removeTab(tab2);
// Since we kept alive all the processes, we can shut down the ones that do
// not host any tabs reliably.
ppmm.releaseCachedProcesses();
is(ppmm.childCount, originalChildCount, "We're back to the original process count.");
});

9
dom/base/test/dummy.html Normal file
View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Dummy test page</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
</head>
<body>
<p>Dummy test page</p>
</body>
</html>

View File

@ -53,7 +53,11 @@ function done() {
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
addLoadEvent(doTest);
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [
["browser.newtab.preload", false]
]}, doTest);
});
</script>

View File

@ -762,11 +762,11 @@ ContentParent::MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
/*static*/ already_AddRefed<ContentParent>
ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
ProcessPriority aPriority,
ContentParent* aOpener)
ContentParent* aOpener,
bool aPreferUsed)
{
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
// We never want to re-use Large-Allocation processes.
if (contentParents.Length() >= maxContentParents) {
@ -775,11 +775,18 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
aOpener);
}
} else {
nsTArray<nsIContentProcessInfo*> infos(contentParents.Length());
uint32_t numberOfParents = contentParents.Length();
nsTArray<nsIContentProcessInfo*> infos(numberOfParents);
for (auto* cp : contentParents) {
infos.AppendElement(cp->mScriptableHelper);
}
if (aPreferUsed && numberOfParents) {
// For the preloaded browser we don't want to create a new process but reuse an
// existing one.
maxContentParents = numberOfParents;
}
nsCOMPtr<nsIContentProcessProvider> cpp =
do_GetService("@mozilla.org/ipc/processselector;1");
nsIContentProcessInfo* openerInfo = aOpener ? aOpener->mScriptableHelper.get() : nullptr;
@ -1131,6 +1138,13 @@ ContentParent::CreateBrowser(const TabContext& aContext,
remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
}
bool isPreloadBrowser = false;
nsAutoString isPreloadBrowserStr;
if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::isPreloadBrowser,
isPreloadBrowserStr)) {
isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("true");
}
RefPtr<nsIContentParent> constructorSender;
if (isInContentProcess) {
MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
@ -1146,7 +1160,8 @@ ContentParent::CreateBrowser(const TabContext& aContext,
initialPriority);
} else {
constructorSender =
GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr);
GetNewOrUsedBrowserProcess(remoteType, initialPriority,
nullptr, isPreloadBrowser);
}
if (!constructorSender) {
return nullptr;

View File

@ -172,7 +172,8 @@ public:
GetNewOrUsedBrowserProcess(const nsAString& aRemoteType = NS_LITERAL_STRING(NO_REMOTE_TYPE),
hal::ProcessPriority aPriority =
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
ContentParent* aOpener = nullptr);
ContentParent* aOpener = nullptr,
bool aPreferUsed = false);
/**
* Get or create a content process for a JS plugin. aPluginID is the id of the JS plugin

View File

@ -2254,38 +2254,3 @@ NPObjectMember_toPrimitive(JSContext *cx, unsigned argc, JS::Value *vp)
}
return true;
}
// static
bool
nsJSObjWrapper::HasOwnProperty(NPObject *npobj, NPIdentifier npid)
{
NPP npp = NPPStack::Peek();
nsIGlobalObject* globalObject = GetGlobalObject(npp);
if (NS_WARN_IF(!globalObject)) {
return false;
}
dom::AutoEntryScript aes(globalObject, "NPAPI HasOwnProperty");
JSContext *cx = aes.cx();
if (!npobj) {
ThrowJSExceptionASCII(cx,
"Null npobj in nsJSObjWrapper::NP_HasOwnProperty!");
return false;
}
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
bool found, ok = false;
AutoJSExceptionSuppressor suppressor(aes, npjsobj);
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
JSAutoCompartment ac(cx, jsobj);
MarkCrossZoneNPIdentifier(cx, npid);
NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
"id must be either string or int!\n");
JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
ok = ::JS_AlreadyHasOwnPropertyById(cx, jsobj, id, &found);
return ok && found;
}

View File

@ -59,7 +59,6 @@ public:
bool mDestroyPending;
static NPObject* GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj);
static bool HasOwnProperty(NPObject* npobj, NPIdentifier npid);
void trace(JSTracer* trc) {
JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapper");

View File

@ -11,6 +11,10 @@
namespace mozilla {
namespace dom {
#undef LOG
#define LOG(args) \
MOZ_LOG(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug, args)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest)
NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
@ -53,6 +57,14 @@ ModuleLoadRequest::Cancel()
void
ModuleLoadRequest::SetReady()
{
// Mark a module as ready to execute. This means that this module and all it
// dependencies have had their source loaded, parsed as a module and the
// modules instantiated.
//
// The mReady promise is used to ensure that when all dependencies of a module
// have become ready, DependenciesLoaded is called on that module
// request. This is set up in StartFetchingModuleDependencies.
#ifdef DEBUG
for (size_t i = 0; i < mImports.Length(); i++) {
MOZ_ASSERT(mImports[i]->IsReadyToRun());
@ -69,6 +81,8 @@ ModuleLoadRequest::ModuleLoaded()
// A module that was found to be marked as fetching in the module map has now
// been loaded.
LOG(("ScriptLoadRequest (%p): Module loaded", this));
mModuleScript = mLoader->GetFetchedModule(mURI);
mLoader->StartFetchingModuleDependencies(this);
}
@ -79,6 +93,8 @@ ModuleLoadRequest::DependenciesLoaded()
// The module and all of its dependencies have been successfully fetched and
// compiled.
LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
if (!mLoader->InstantiateModuleTree(this)) {
LoadFailed();
return;
@ -93,6 +109,8 @@ ModuleLoadRequest::DependenciesLoaded()
void
ModuleLoadRequest::LoadFailed()
{
LOG(("ScriptLoadRequest (%p): Module load failed", this));
Cancel();
mLoader->ProcessLoadedModuleTree(this);
mLoader = nullptr;

View File

@ -72,9 +72,12 @@ namespace dom {
LazyLogModule ScriptLoader::gCspPRLog("CSP");
LazyLogModule ScriptLoader::gScriptLoaderLog("ScriptLoader");
#undef LOG
#define LOG(args) \
MOZ_LOG(gScriptLoaderLog, mozilla::LogLevel::Debug, args)
#define LOG_ENABLED() \
MOZ_LOG_TEST(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug)
// Alternate Data MIME type used by the ScriptLoader to register that we want to
// store bytecode without reading it.
@ -357,6 +360,13 @@ ScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest*
{
// Update module map with the result of fetching a single module script. The
// module script pointer is nullptr on error.
//
// If any requests for the same URL are waiting on this one to complete, they
// will have ModuleLoaded or LoadFailed on them when the promise is
// resolved/rejected. This is set up in StartLoad.
LOG(("ScriptLoadRequest (%p): Module fetch finished (result == %u)",
aRequest, unsigned(aResult)));
MOZ_ASSERT(!aRequest->IsReadyToRun());
@ -400,6 +410,12 @@ ScriptLoader::WaitForModuleFetch(ModuleLoadRequest* aRequest)
ModuleScript*
ScriptLoader::GetFetchedModule(nsIURI* aURL) const
{
if (LOG_ENABLED()) {
nsAutoCString url;
aURL->GetAsciiSpec(url);
LOG(("GetFetchedModule %s", url.get()));
}
bool found;
ModuleScript* ms = mFetchedModules.GetWeak(aURL, &found);
MOZ_ASSERT(found);
@ -646,8 +662,13 @@ void
ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mModuleScript);
MOZ_ASSERT(!aRequest->mModuleScript->InstantiationFailed());
MOZ_ASSERT(!aRequest->IsReadyToRun());
if (aRequest->mModuleScript->InstantiationFailed()) {
aRequest->LoadFailed();
return;
}
aRequest->mProgress = ModuleLoadRequest::Progress::FetchingImports;
nsCOMArray<nsIURI> urls;
@ -790,6 +811,8 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
MOZ_ASSERT(aRequest);
LOG(("ScriptLoadRequest (%p): Instantiate module tree", aRequest));
ModuleScript* ms = aRequest->mModuleScript;
MOZ_ASSERT(ms);
if (!ms->ModuleRecord()) {
@ -809,6 +832,7 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
JS::RootedValue exception(jsapi.cx());
if (!ok) {
LOG(("ScriptLoadRequest (%p): Instantiate failed", aRequest));
MOZ_ASSERT(jsapi.HasException());
if (!jsapi.StealException(&exception)) {
return false;
@ -877,11 +901,18 @@ ScriptLoader::StartLoad(ScriptLoadRequest* aRequest)
return NS_OK;
}
if (LOG_ENABLED()) {
nsAutoCString url;
aRequest->mURI->GetAsciiSpec(url);
LOG(("ScriptLoadRequest (%p): Start Load (url = %s)", aRequest, url.get()));
}
if (aRequest->IsModuleRequest()) {
// Check whether the module has been fetched or is currently being fetched,
// and if so wait for it.
ModuleLoadRequest* request = aRequest->AsModuleRequest();
if (ModuleMapContainsModule(request)) {
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
WaitForModuleFetch(request)
->Then(GetMainThreadSerialEventTarget(), __func__, request,
&ModuleLoadRequest::ModuleLoaded,
@ -891,6 +922,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest* aRequest)
// Otherwise put the URL in the module map and mark it as fetching.
SetModuleFetchStarted(request);
LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
}
nsContentPolicyType contentPolicyType = aRequest->IsPreload()

View File

@ -15,17 +15,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=841850
var blankTarget = document.getElementById("blankTarget");
blankTarget.click();
var os = SpecialPowers.Cc["@mozilla.org/observer-service;1"].
getService(SpecialPowers.Components.interfaces.nsIObserverService);
var observer = {
observe: function(subject, topic, data) {
if(topic == "content-document-global-created" && data =="http://example.com") {
parent.parent.postMessage({"test": "blankTarget", "msg": "opened an http link with target=_blank from a secure page"}, "http://mochi.test:8888");
os.removeObserver(observer, "content-document-global-created");
SpecialPowers.removeAsyncObserver(observer, "content-document-global-created");
}
}
}
os.addObserver(observer, "content-document-global-created");
SpecialPowers.addAsyncObserver(observer, "content-document-global-created");
</script>
</body>

View File

@ -312,7 +312,9 @@ function checkChangeIsEnabled(aWindow, aNext)
.then(aNext);
}
SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false]]}, function() {
SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false],
["security.data_uri.unique_opaque_origin", false]]},
function() {
SimpleTest.waitForFocus(function() {
if (screen.width <= 200 || screen.height <= 200) {
todo(false, "The screen needs to be bigger than 200px*200px to run this test.");

View File

@ -215,67 +215,75 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=565541
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
if (screen.width <= 200 || screen.height <= 200) {
todo(false, "The screen is too small to run this test.");
SimpleTest.finish();
}
backValues();
function test() {
SimpleTest.waitForFocus(function() {
if (screen.width <= 200 || screen.height <= 200) {
todo(false, "The screen is too small to run this test.");
SimpleTest.finish();
}
// We are in a chrome context, we can change the size and position.
checkChangeIsEnabled(window.top, function() {
// We create a window and check that the size and position can be set with
// window.open parameters and can be changed by the created window.
var w = window.open("data:text/html,<script>" +
"function check(next) {" +
" var is_range = function(aTest, aValue, aRange, aMsg) {" +
" ok(aTest < aValue + aRange && aTest > aValue - aRange, aMsg);" +
" };" +
" is_range(window.innerWidth, 170, 5, 'parameter width should be taken into account');" +
" is_range(window.innerHeight, 170, 5, 'parameter height should be taken into account');" +
" is_range(window.screenX, 25, 5, 'parameter screenX should be taken into account');" +
" is_range(window.screenY, 25, 5, 'parameter screenY should be taken into account');" +
" checkChangeIsEnabled(window, next);" +
"} <\/script>", '',
'width=170,height=170,screenX=25,screenY=25');
backValues();
SimpleTest.waitForFocus(function() {
// This test relies on passing cross-origin windows to a chrome function,
// which is generally forbidden if we don't twiddle the knob below.
Components.utils.forcePermissiveCOWs();
w.wrappedJSObject.ok = SimpleTest.ok;
w.wrappedJSObject.checkChangeIsEnabled = window.checkChangeIsEnabled;
w.wrappedJSObject.check(function() {
// The current window can change the size and position of the created one.
checkChangeIsEnabled(w, function() {
w.close();
// We are in a chrome context, we can change the size and position.
checkChangeIsEnabled(window.top, function() {
// We create a window and check that the size and position can be set with
// window.open parameters and can be changed by the created window.
var w = window.open("data:text/html,<script>" +
"function check(next) {" +
" var is_range = function(aTest, aValue, aRange, aMsg) {" +
" ok(aTest < aValue + aRange && aTest > aValue - aRange, aMsg);" +
" };" +
" is_range(window.innerWidth, 170, 5, 'parameter width should be taken into account');" +
" is_range(window.innerHeight, 170, 5, 'parameter height should be taken into account');" +
" is_range(window.screenX, 25, 5, 'parameter screenX should be taken into account');" +
" is_range(window.screenY, 25, 5, 'parameter screenY should be taken into account');" +
" checkChangeIsEnabled(window, next);" +
"} <\/script>", '',
'width=170,height=170,screenX=25,screenY=25');
// If we call window.open with an empty string as a third parameter,
// by default, it will create a new tab instead of a new window.
// In a chrome context, the size and position can change.
w = window.open("data:text/html,<script>" +
"function check(next) {" +
" checkChangeIsEnabled(window, next);" +
"} <\/script>", '', '');
SimpleTest.waitForFocus(function() {
// This test relies on passing cross-origin windows to a chrome function,
// which is generally forbidden if we don't twiddle the knob below.
Components.utils.forcePermissiveCOWs();
w.wrappedJSObject.ok = SimpleTest.ok;
w.wrappedJSObject.checkChangeIsEnabled = window.checkChangeIsEnabled;
w.wrappedJSObject.check(function() {
// The current window can change the size and position of the created one.
checkChangeIsEnabled(w, function() {
w.close();
SimpleTest.waitForFocus(function() {
w.wrappedJSObject.checkChangeIsEnabled = window.checkChangeIsEnabled;
w.wrappedJSObject.check(function() {
// The current window can change the size and position of the new tab.
// Because we are in a chrome context.
checkChangeIsEnabled(w, function() {
w.close();
// If we call window.open with an empty string as a third parameter,
// by default, it will create a new tab instead of a new window.
// In a chrome context, the size and position can change.
w = window.open("data:text/html,<script>" +
"function check(next) {" +
" checkChangeIsEnabled(window, next);" +
"} <\/script>", '', '');
restoreValues();
SimpleTest.finish();
SimpleTest.waitForFocus(function() {
w.wrappedJSObject.checkChangeIsEnabled = window.checkChangeIsEnabled;
w.wrappedJSObject.check(function() {
// The current window can change the size and position of the new tab.
// Because we are in a chrome context.
checkChangeIsEnabled(w, function() {
w.close();
restoreValues();
SimpleTest.finish();
});
});
});
}, w, false);
}, w, false);
});
});
});
}, w, false);
}, w, false);
});
});
}
addLoadEvent(function onLoad() {
SpecialPowers.pushPrefEnv({"set": [
["security.data_uri.unique_opaque_origin", false]]}, test);
});
]]>
</script>

View File

@ -13,7 +13,10 @@
<script>
add_task(async function() {
// Push the correct preferences for the test
await SpecialPowers.pushPrefEnv({'set': [['dom.select_events.enabled', true]]});
await SpecialPowers.pushPrefEnv({'set': [
['dom.select_events.enabled', true],
['dom.select_events.textcontrols.enabled', true],
]});
// Start the actual test
await new Promise((done) => {

View File

@ -41,6 +41,7 @@ add_task(function setupPrefs() {
return SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["browser.newtab.preload", false],
]});
});

View File

@ -19,11 +19,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=966155
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [
["security.data_uri.unique_opaque_origin", false]]}, nextTest);
});
function nextTest() {
var win = window.open("data:text/html,<input><iframe onload=\"contentDocument.designMode = 'on';\">", "", "test-966155");
win.addEventListener("load", function() {
runTest(win);
}, {once: true});
});
}
function runTest(win) {
SimpleTest.waitForFocus(function() {

View File

@ -19,11 +19,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=966552
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [
["security.data_uri.unique_opaque_origin", false]]}, nextTest);
});
function nextTest() {
var win = window.open("data:text/html,<body onload=\"document.designMode='on'\">test</body>", "", "test-966552");
win.addEventListener("load", function() {
runTest(win);
}, {once: true});
});
}
function runTest(win) {
SimpleTest.waitForFocus(function() {

View File

@ -35,7 +35,7 @@ public:
DECL_GFX_ENV("DUMP_DEBUG", DumpDebug);
// Use WR recording
DECL_GFX_ENV("ENABLE_WR_RENDERING", EnableWebRenderRecording);
DECL_GFX_ENV("ENABLE_WR_RECORDING", EnableWebRenderRecording);
// OpenGL shader debugging in OGLShaderProgram, in DEBUG only
DECL_GFX_ENV("MOZ_DEBUG_SHADERS", DebugShaders);

View File

@ -173,8 +173,7 @@ gfxFontCache::Shutdown()
}
gfxFontCache::gfxFontCache(nsIEventTarget* aEventTarget)
: nsExpirationTracker<gfxFont,3>(FONT_TIMEOUT_SECONDS * 1000,
"gfxFontCache", aEventTarget)
: gfxFontCacheExpirationTracker(aEventTarget)
{
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (obs) {
@ -286,7 +285,7 @@ gfxFontCache::NotifyReleased(gfxFont *aFont)
}
void
gfxFontCache::NotifyExpired(gfxFont *aFont)
gfxFontCache::NotifyExpired(gfxFont* aFont)
{
aFont->ClearCachedWords();
RemoveObject(aFont);

View File

@ -33,6 +33,7 @@
#include "harfbuzz/hb.h"
#include "mozilla/gfx/2D.h"
#include "nsColor.h"
#include "mozilla/ServoUtils.h"
typedef struct _cairo cairo_t;
typedef struct _cairo_scaled_font cairo_scaled_font_t;
@ -255,12 +256,41 @@ struct FontCacheSizes {
size_t mShapedWords; // memory used by the per-font shapedWord caches
};
class gfxFontCache final : public nsExpirationTracker<gfxFont,3> {
class gfxFontCacheExpirationTracker
: public ExpirationTrackerImpl<gfxFont, 3,
::detail::PlaceholderLock,
::detail::PlaceholderAutoLock>
{
protected:
typedef ::detail::PlaceholderLock Lock;
typedef ::detail::PlaceholderAutoLock AutoLock;
Lock mLock;
AutoLock FakeLock()
{
return AutoLock(mLock);
}
Lock& GetMutex() override
{
mozilla::AssertIsMainThreadOrServoFontMetricsLocked();
return mLock;
}
public:
enum {
FONT_TIMEOUT_SECONDS = 10,
SHAPED_WORD_TIMEOUT_SECONDS = 60
};
enum { FONT_TIMEOUT_SECONDS = 10 };
gfxFontCacheExpirationTracker(nsIEventTarget* aEventTarget)
: ExpirationTrackerImpl<gfxFont, 3, Lock, AutoLock>(
FONT_TIMEOUT_SECONDS * 1000, "gfxFontCache", aEventTarget)
{
}
};
class gfxFontCache final : private gfxFontCacheExpirationTracker {
public:
enum { SHAPED_WORD_TIMEOUT_SECONDS = 60 };
explicit gfxFontCache(nsIEventTarget* aEventTarget);
~gfxFontCache();
@ -294,10 +324,6 @@ public:
// amount of time.
void NotifyReleased(gfxFont *aFont);
// This gets called when the timeout has expired on a zero-refcount
// font; we just delete it.
virtual void NotifyExpired(gfxFont *aFont) override;
// Cleans out the hashtable and removes expired fonts waiting for cleanup.
// Other gfxFont objects may be still in use but they will be pushed
// into the expiration queues and removed.
@ -314,6 +340,16 @@ public:
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const;
void AgeAllGenerations()
{
AgeAllGenerationsLocked(FakeLock());
}
void RemoveObject(gfxFont* aFont)
{
RemoveObjectLocked(aFont, FakeLock());
}
protected:
class MemoryReporter final : public nsIMemoryReporter
{
@ -333,6 +369,20 @@ protected:
NS_DECL_NSIOBSERVER
};
nsresult AddObject(gfxFont* aFont)
{
return AddObjectLocked(aFont, FakeLock());
}
// This gets called when the timeout has expired on a zero-refcount
// font; we just delete it.
virtual void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&) override
{
NotifyExpired(aFont);
}
void NotifyExpired(gfxFont* aFont);
void DestroyFont(gfxFont *aFont);
static gfxFontCache *gGlobalCache;

View File

@ -43,14 +43,9 @@ AnimationSurfaceProvider::DropImageReference()
return; // Nothing to do.
}
// RasterImage objects need to be destroyed on the main thread. We also need
// to destroy them asynchronously, because if our surface cache entry is
// destroyed and we were the only thing keeping |mImage| alive, RasterImage's
// destructor may call into the surface cache while whatever code caused us to
// get evicted is holding the surface cache lock, causing deadlock.
RefPtr<RasterImage> image = mImage;
mImage = nullptr;
NS_ReleaseOnMainThreadSystemGroup(image.forget(), /* aAlwaysProxy = */ true);
// RasterImage objects need to be destroyed on the main thread.
NS_ReleaseOnMainThreadSystemGroup("AnimationSurfaceProvider::mImage",
mImage.forget());
}
DrawableFrameRef

View File

@ -253,12 +253,14 @@ public:
return mSurfaces.Put(aSurface->GetSurfaceKey(), aSurface, fallible);
}
void Remove(NotNull<CachedSurface*> aSurface)
already_AddRefed<CachedSurface> Remove(NotNull<CachedSurface*> aSurface)
{
MOZ_ASSERT(mSurfaces.GetWeak(aSurface->GetSurfaceKey()),
"Should not be removing a surface we don't have");
mSurfaces.Remove(aSurface->GetSurfaceKey());
RefPtr<CachedSurface> surface;
mSurfaces.Remove(aSurface->GetSurfaceKey(), getter_AddRefs(surface));
return surface.forget();
}
already_AddRefed<CachedSurface> Lookup(const SurfaceKey& aSurfaceKey)
@ -515,10 +517,14 @@ public:
}
StopTracking(aSurface, aAutoLock);
cache->Remove(aSurface);
// Remove the per-image cache if it's unneeded now. (Keep it if the image is
// locked, since the per-image cache is where we store that state.)
// Individual surfaces must be freed outside the lock.
mCachedSurfacesDiscard.AppendElement(cache->Remove(aSurface));
// Remove the per-image cache if it's unneeded now. Keep it if the image is
// locked, since the per-image cache is where we store that state. Note that
// we don't push it into mImageCachesDiscard because all of its surfaces
// have been removed, so it is safe to free while holding the lock.
if (cache->IsEmpty() && !cache->IsLocked()) {
mImageCaches.Remove(imageKey);
}
@ -728,11 +734,12 @@ public:
/* aStaticOnly = */ !gfxPrefs::ImageMemAnimatedDiscardable(), aAutoLock);
}
void RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
already_AddRefed<ImageSurfaceCache>
RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
{
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
if (!cache) {
return; // No cached surfaces for this image, so nothing to do.
return nullptr; // No cached surfaces for this image, so nothing to do.
}
// Discard all of the cached surfaces for this image.
@ -747,6 +754,10 @@ public:
// The per-image cache isn't needed anymore, so remove it as well.
// This implicitly unlocks the image if it was locked.
mImageCaches.Remove(aImageKey);
// Since we did not actually remove any of the surfaces from the cache
// itself, only stopped tracking them, we should free it outside the lock.
return cache.forget();
}
void DiscardAll(const StaticMutexAutoLock& aAutoLock)
@ -785,6 +796,13 @@ public:
}
}
void TakeDiscard(nsTArray<RefPtr<CachedSurface>>& aDiscard,
const StaticMutexAutoLock& aAutoLock)
{
MOZ_ASSERT(aDiscard.IsEmpty());
aDiscard = Move(mCachedSurfacesDiscard);
}
void LockSurface(NotNull<CachedSurface*> aSurface,
const StaticMutexAutoLock& aAutoLock)
{
@ -908,10 +926,12 @@ private:
Remove(WrapNotNull(surface), aAutoLock);
}
struct SurfaceTracker : public ExpirationTrackerImpl<CachedSurface, 2,
StaticMutex,
StaticMutexAutoLock>
class SurfaceTracker final :
public ExpirationTrackerImpl<CachedSurface, 2,
StaticMutex,
StaticMutexAutoLock>
{
public:
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
: ExpirationTrackerImpl<CachedSurface, 2,
StaticMutex, StaticMutexAutoLock>(
@ -926,23 +946,40 @@ private:
sInstance->Remove(WrapNotNull(aSurface), aAutoLock);
}
void NotifyHandlerEndLocked(const StaticMutexAutoLock& aAutoLock) override
{
sInstance->TakeDiscard(mDiscard, aAutoLock);
}
void NotifyHandlerEnd() override
{
nsTArray<RefPtr<CachedSurface>> discard(Move(mDiscard));
}
StaticMutex& GetMutex() override
{
return sInstanceMutex;
}
nsTArray<RefPtr<CachedSurface>> mDiscard;
};
struct MemoryPressureObserver : public nsIObserver
class MemoryPressureObserver final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Observe(nsISupports*,
const char* aTopic,
const char16_t*) override
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
sInstance->DiscardForMemoryPressure(lock);
nsTArray<RefPtr<CachedSurface>> discard;
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
sInstance->DiscardForMemoryPressure(lock);
sInstance->TakeDiscard(discard, lock);
}
}
return NS_OK;
}
@ -954,6 +991,7 @@ private:
nsTArray<CostEntry> mCosts;
nsRefPtrHashtable<nsPtrHashKey<Image>,
ImageSurfaceCache> mImageCaches;
nsTArray<RefPtr<CachedSurface>> mCachedSurfacesDiscard;
SurfaceTracker mExpirationTracker;
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
const uint32_t mDiscardFactor;
@ -1029,45 +1067,72 @@ SurfaceCache::Initialize()
/* static */ void
SurfaceCache::Shutdown()
{
StaticMutexAutoLock lock(sInstanceMutex);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
sInstance = nullptr;
RefPtr<SurfaceCacheImpl> cache;
{
StaticMutexAutoLock lock(sInstanceMutex);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
cache = sInstance.forget();
}
}
/* static */ LookupResult
SurfaceCache::Lookup(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey)
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return LookupResult(MatchType::NOT_FOUND);
nsTArray<RefPtr<CachedSurface>> discard;
LookupResult rv(MatchType::NOT_FOUND);
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return rv;
}
rv = sInstance->Lookup(aImageKey, aSurfaceKey, lock);
sInstance->TakeDiscard(discard, lock);
}
return sInstance->Lookup(aImageKey, aSurfaceKey, lock);
return rv;
}
/* static */ LookupResult
SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey)
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return LookupResult(MatchType::NOT_FOUND);
nsTArray<RefPtr<CachedSurface>> discard;
LookupResult rv(MatchType::NOT_FOUND);
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return rv;
}
rv = sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
sInstance->TakeDiscard(discard, lock);
}
return sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
return rv;
}
/* static */ InsertOutcome
SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return InsertOutcome::FAILURE;
nsTArray<RefPtr<CachedSurface>> discard;
InsertOutcome rv(InsertOutcome::FAILURE);
{
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
return rv;
}
rv = sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
sInstance->TakeDiscard(discard, lock);
}
return sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
return rv;
}
/* static */ bool
@ -1134,18 +1199,25 @@ SurfaceCache::UnlockEntries(const ImageKey aImageKey)
/* static */ void
SurfaceCache::RemoveImage(const ImageKey aImageKey)
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance) {
sInstance->RemoveImage(aImageKey, lock);
RefPtr<ImageSurfaceCache> discard;
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance) {
discard = sInstance->RemoveImage(aImageKey, lock);
}
}
}
/* static */ void
SurfaceCache::DiscardAll()
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance) {
sInstance->DiscardAll(lock);
nsTArray<RefPtr<CachedSurface>> discard;
{
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance) {
sInstance->DiscardAll(lock);
sInstance->TakeDiscard(discard, lock);
}
}
}

View File

@ -287,10 +287,27 @@ imgRequestProxy::GetEventTarget() const
return target.forget();
}
void
imgRequestProxy::Dispatch(already_AddRefed<nsIRunnable> aEvent)
nsresult
imgRequestProxy::DispatchWithTargetIfAvailable(already_AddRefed<nsIRunnable> aEvent)
{
LOG_FUNC(gImgLog, "imgRequestProxy::Dispatch");
LOG_FUNC(gImgLog, "imgRequestProxy::DispatchWithTargetIfAvailable");
// This method should only be used when it is *expected* that we are
// dispatching an event (e.g. we want to handle an event asynchronously)
// rather we need to (e.g. we are in the wrong scheduler group context).
// As such, we do not set mHadDispatch for telemetry purposes.
if (mEventTarget) {
mEventTarget->Dispatch(Move(aEvent), NS_DISPATCH_NORMAL);
return NS_OK;
}
return NS_DispatchToMainThread(Move(aEvent));
}
void
imgRequestProxy::DispatchWithTarget(already_AddRefed<nsIRunnable> aEvent)
{
LOG_FUNC(gImgLog, "imgRequestProxy::DispatchWithTarget");
MOZ_ASSERT(mListener || mTabGroup);
MOZ_ASSERT(mEventTarget);
@ -410,7 +427,7 @@ imgRequestProxy::Cancel(nsresult status)
mCanceled = true;
nsCOMPtr<nsIRunnable> ev = new imgCancelRunnable(this, status);
return NS_DispatchToCurrentThread(ev);
return DispatchWithTargetIfAvailable(ev.forget());
}
void
@ -451,8 +468,10 @@ imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
mIsInLoadGroup = oldIsInLoadGroup;
if (mIsInLoadGroup) {
NS_DispatchToCurrentThread(NewRunnableMethod("imgRequestProxy::DoRemoveFromLoadGroup",
this, &imgRequestProxy::DoRemoveFromLoadGroup));
nsCOMPtr<nsIRunnable> ev =
NewRunnableMethod("imgRequestProxy::DoRemoveFromLoadGroup",
this, &imgRequestProxy::DoRemoveFromLoadGroup);
DispatchWithTargetIfAvailable(ev.forget());
}
NullOutListener();
@ -929,12 +948,12 @@ imgRequestProxy::Notify(int32_t aType, const mozilla::gfx::IntRect* aRect)
RefPtr<imgRequestProxy> self(this);
if (aRect) {
const mozilla::gfx::IntRect rect = *aRect;
Dispatch(NS_NewRunnableFunction("imgRequestProxy::Notify",
DispatchWithTarget(NS_NewRunnableFunction("imgRequestProxy::Notify",
[self, rect, aType]() -> void {
self->Notify(aType, &rect);
}));
} else {
Dispatch(NS_NewRunnableFunction("imgRequestProxy::Notify",
DispatchWithTarget(NS_NewRunnableFunction("imgRequestProxy::Notify",
[self, aType]() -> void {
self->Notify(aType, nullptr);
}));
@ -964,7 +983,7 @@ imgRequestProxy::OnLoadComplete(bool aLastPart)
RefPtr<imgRequestProxy> self(this);
if (!IsOnEventTarget()) {
Dispatch(NS_NewRunnableFunction("imgRequestProxy::OnLoadComplete",
DispatchWithTarget(NS_NewRunnableFunction("imgRequestProxy::OnLoadComplete",
[self, aLastPart]() -> void {
self->OnLoadComplete(aLastPart);
}));
@ -1019,7 +1038,7 @@ imgRequestProxy::BlockOnload()
if (!IsOnEventTarget()) {
RefPtr<imgRequestProxy> self(this);
Dispatch(NS_NewRunnableFunction("imgRequestProxy::BlockOnload",
DispatchWithTarget(NS_NewRunnableFunction("imgRequestProxy::BlockOnload",
[self]() -> void {
self->BlockOnload();
}));
@ -1046,7 +1065,7 @@ imgRequestProxy::UnblockOnload()
if (!IsOnEventTarget()) {
RefPtr<imgRequestProxy> self(this);
Dispatch(NS_NewRunnableFunction("imgRequestProxy::UnblockOnload",
DispatchWithTarget(NS_NewRunnableFunction("imgRequestProxy::UnblockOnload",
[self]() -> void {
self->UnblockOnload();
}));

View File

@ -214,7 +214,8 @@ private:
void AddToOwner(nsIDocument* aLoadingDocument);
void Dispatch(already_AddRefed<nsIRunnable> aEvent);
nsresult DispatchWithTargetIfAvailable(already_AddRefed<nsIRunnable> aEvent);
void DispatchWithTarget(already_AddRefed<nsIRunnable> aEvent);
// The URI of our request.
RefPtr<ImageURL> mURI;

View File

@ -13,8 +13,7 @@
#include "gc/Heap.h"
#include "vm/SelfHosting.h"
#include "jsobjinlines.h"
#include "vm/List-inl.h"
#include "vm/NativeObject-inl.h"
using namespace js;
@ -318,53 +317,13 @@ RejectNonGenericMethod(JSContext* cx, const CallArgs& args,
inline static MOZ_MUST_USE NativeObject*
SetNewList(JSContext* cx, HandleNativeObject container, uint32_t slot)
{
NativeObject* list = NewObjectWithNullTaggedProto<PlainObject>(cx);
NativeObject* list = NewList(cx);
if (!list)
return nullptr;
container->setFixedSlot(slot, ObjectValue(*list));
return list;
}
inline static MOZ_MUST_USE bool
AppendToList(JSContext* cx, HandleNativeObject list, HandleValue value)
{
uint32_t length = list->getDenseInitializedLength();
if (!list->ensureElements(cx, length + 1))
return false;
list->ensureDenseInitializedLength(cx, length, 1);
list->setDenseElement(length, value);
return true;
}
template<class T>
inline static MOZ_MUST_USE T*
PeekList(NativeObject* list)
{
MOZ_ASSERT(list->getDenseInitializedLength() > 0);
return &list->getDenseElement(0).toObject().as<T>();
}
template<class T>
inline static MOZ_MUST_USE T*
ShiftFromList(JSContext* cx, HandleNativeObject list)
{
uint32_t length = list->getDenseInitializedLength();
MOZ_ASSERT(length > 0);
Rooted<T*> entry(cx, &list->getDenseElement(0).toObject().as<T>());
if (!list->tryShiftDenseElements(1)) {
list->moveDenseElements(0, 1, length - 1);
list->shrinkElements(cx, length - 1);
}
list->setDenseInitializedLength(length - 1);
return entry;
}
class ByteStreamChunk : public NativeObject
{
private:

View File

@ -3911,12 +3911,6 @@ Parser<ParseHandler, CharT>::functionStmt(uint32_t toStringStart, YieldHandling
GeneratorKind generatorKind = NotGenerator;
if (tt == TOK_MUL) {
if (!asyncIterationSupported()) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
return null();
@ -3986,12 +3980,6 @@ Parser<ParseHandler, CharT>::functionExpr(uint32_t toStringStart, InvokedPredict
return null();
if (tt == TOK_MUL) {
if (!asyncIterationSupported()) {
if (asyncKind != SyncFunction) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
return null();
@ -6299,16 +6287,14 @@ Parser<ParseHandler, CharT>::forStatement(YieldHandling yieldHandling)
}
}
if (asyncIterationSupported()) {
if (pc->isAsync()) {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_AWAIT))
return null();
if (pc->isAsync()) {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_AWAIT))
return null();
if (matched) {
iflags |= JSITER_FORAWAITOF;
iterKind = IteratorKind::Async;
}
if (matched) {
iflags |= JSITER_FORAWAITOF;
iterKind = IteratorKind::Async;
}
}
@ -9717,12 +9703,6 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
}
if (ltok == TOK_MUL) {
if (!asyncIterationSupported()) {
if (isAsync) {
error(JSMSG_ASYNC_GENERATOR);
return null();
}
}
isGenerator = true;
if (!tokenStream.getToken(&ltok))
return null();

View File

@ -180,16 +180,6 @@ class ParserBase : public StrictModeGetter
pc->isLegacyGenerator();
}
bool asyncIterationSupported() {
#ifdef RELEASE_OR_BETA
return false;
#else
// Expose Async Iteration only to web content until the spec proposal
// gets stable.
return !options().isProbablySystemOrAddonCode;
#endif
}
virtual bool strictMode() { return pc->sc()->strict(); }
bool setLocalStrictMode(bool strict) {
MOZ_ASSERT(tokenStream.debugHasNoLookahead());

View File

@ -0,0 +1,10 @@
Object.defineProperty(Array.prototype, "2", {
set: function () {}
});
async function* f() {
yield {};
}
var x = f();
x.next();
x.next();
x.next();

View File

@ -0,0 +1,14 @@
Object.prototype.set = function () {};
let f = async function* () {
yield;
};
let x = f();
x.next();
x.next().then(function () {
x.next();
});
Object.defineProperty(Array.prototype, "0", {
get: function () {
return 1;
}
});

View File

@ -0,0 +1,11 @@
if (helperThreadCount() === 0)
quit();
setGCCallback({
action: "majorGC"
});
gcparam("allocationThreshold", 1);
offThreadCompileScript("");
for (let i = 0; i < 40000; i++)
Symbol.for(i);
eval(0);

View File

@ -0,0 +1,8 @@
function f(x) {
var count = 0;
for (var i = 0; i < x.length; ++i)
count++;
return count;
}
assertEq(f(Error()), 0);
assertEq(f([[]]), 1);

View File

@ -11367,8 +11367,13 @@ IonBuilder::getPropAddCache(MDefinition* obj, PropertyName* name,
MOZ_TRY(resumeAfter(load));
MIRType rvalType = types->getKnownMIRType();
if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
if (barrier != BarrierKind::NoBarrier) {
rvalType = MIRType::Value;
} else {
load->setResultTypeSet(types);
if (IsNullOrUndefined(rvalType))
rvalType = MIRType::Value;
}
load->setResultType(rvalType);
if (*pc != JSOP_CALLPROP || !IsNullOrUndefined(obj->type())) {

View File

@ -188,7 +188,6 @@ MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array compre
MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initializer too large")
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "await is only valid in async functions")
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")

View File

@ -6781,6 +6781,9 @@ GCRuntime::budgetIncrementalGC(bool nonincrementalByAPI, JS::gcreason::Reason re
bool reset = false;
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
if (!zone->canCollect())
continue;
if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) {
MOZ_ASSERT(zone->isGCScheduled());
budget.makeUnlimited();
@ -6812,6 +6815,9 @@ class AutoScheduleZonesForGC
public:
explicit AutoScheduleZonesForGC(JSRuntime* rt) : rt_(rt) {
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
if (!zone->canCollect())
continue;
if (rt->gc.gcMode() == JSGC_MODE_GLOBAL)
zone->scheduleGC();

View File

@ -41,10 +41,6 @@ skip-if(!Array.prototype.values) script test262/built-ins/Array/prototype/Symbol
skip-if(!Array.prototype.values) include test262/built-ins/Array/prototype/values/jstests.list
skip-if(!String.prototype.normalize) include test262/built-ins/String/prototype/normalize/jstests.list
# Async generator is non-release-or-beta only.
skip-if(release_or_beta) include test262/language/expressions/async-generators/jstests.list
skip-if(release_or_beta) include test262/language/statements/async-generator/jstests.list
# Requires ICU to detect Final_Sigma case mapping context
skip-if(!this.hasOwnProperty("Intl")) script test262/built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js
skip-if(!this.hasOwnProperty("Intl")) script test262/built-ins/String/prototype/toLowerCase/special_casing_conditional.js

View File

@ -18,6 +18,7 @@
#include "jscntxtinlines.h"
#include "jsobjinlines.h"
#include "vm/List-inl.h"
#include "vm/NativeObject-inl.h"
using namespace js;
@ -325,25 +326,24 @@ AsyncGeneratorObject::enqueueRequest(JSContext* cx, Handle<AsyncGeneratorObject*
return true;
}
RootedArrayObject queue(cx, NewDenseEmptyArray(cx));
RootedNativeObject queue(cx, NewList(cx));
if (!queue)
return false;
if (!NewbornArrayPush(cx, queue, ObjectValue(*asyncGenObj->singleQueueRequest())))
RootedValue requestVal(cx, ObjectValue(*asyncGenObj->singleQueueRequest()));
if (!AppendToList(cx, queue, requestVal))
return false;
if (!NewbornArrayPush(cx, queue, ObjectValue(*request)))
requestVal = ObjectValue(*request);
if (!AppendToList(cx, queue, requestVal))
return false;
asyncGenObj->setQueue(queue);
return true;
}
RootedArrayObject queue(cx, asyncGenObj->queue());
FixedInvokeArgs<1> args(cx);
args[0].setObject(*request);
args.setThis(ObjectValue(*queue));
return CallJSNative(cx, array_push, args);
RootedNativeObject queue(cx, asyncGenObj->queue());
RootedValue requestVal(cx, ObjectValue(*request));
return AppendToList(cx, queue, requestVal);
}
/* static */ AsyncGeneratorRequest*
@ -355,14 +355,8 @@ AsyncGeneratorObject::dequeueRequest(JSContext* cx, Handle<AsyncGeneratorObject*
return request;
}
RootedArrayObject queue(cx, asyncGenObj->queue());
FixedInvokeArgs<0> args(cx);
args.setThis(ObjectValue(*queue));
if (!CallJSNative(cx, array_shift, args))
return nullptr;
return &args.rval().toObject().as<AsyncGeneratorRequest>();
RootedNativeObject queue(cx, asyncGenObj->queue());
return ShiftFromList<AsyncGeneratorRequest>(cx, queue);
}
/* static */ AsyncGeneratorRequest*
@ -371,13 +365,7 @@ AsyncGeneratorObject::peekRequest(JSContext* cx, Handle<AsyncGeneratorObject*> a
if (asyncGenObj->isSingleQueue())
return asyncGenObj->singleQueueRequest();
RootedArrayObject queue(cx, asyncGenObj->queue());
RootedValue requestVal(cx);
if (!GetElement(cx, queue, queue, 0, &requestVal))
return nullptr;
return &requestVal.toObject().as<AsyncGeneratorRequest>();
return PeekList<AsyncGeneratorRequest>(asyncGenObj->queue());
}
const Class AsyncGeneratorRequest::class_ = {

View File

@ -146,8 +146,8 @@ class AsyncGeneratorObject : public NativeObject
return &getFixedSlot(Slot_QueueOrRequest).toObject().as<AsyncGeneratorRequest>();
}
ArrayObject* queue() const {
return &getFixedSlot(Slot_QueueOrRequest).toObject().as<ArrayObject>();
NativeObject* queue() const {
return &getFixedSlot(Slot_QueueOrRequest).toObject().as<NativeObject>();
}
void setQueue(JSObject* queue_) {
setFixedSlot(Slot_QueueOrRequest, ObjectValue(*queue_));
@ -217,7 +217,7 @@ class AsyncGeneratorObject : public NativeObject
bool isQueueEmpty() const {
if (isSingleQueue())
return isSingleQueueEmpty();
return queue()->length() == 0;
return queue()->getDenseInitializedLength() == 0;
}
};

69
js/src/vm/List-inl.h Normal file
View File

@ -0,0 +1,69 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef vm_List_inl_h
#define vm_List_inl_h
#include "jscntxt.h"
#include "gc/Rooting.h"
#include "vm/NativeObject.h"
#include "jsobjinlines.h"
#include "vm/NativeObject-inl.h"
namespace js {
inline MOZ_MUST_USE NativeObject*
NewList(JSContext* cx)
{
return NewObjectWithNullTaggedProto<PlainObject>(cx);
}
inline MOZ_MUST_USE bool
AppendToList(JSContext* cx, HandleNativeObject list, HandleValue value)
{
uint32_t length = list->getDenseInitializedLength();
if (!list->ensureElements(cx, length + 1))
return false;
list->ensureDenseInitializedLength(cx, length, 1);
list->setDenseElement(length, value);
return true;
}
template<class T>
inline MOZ_MUST_USE T*
PeekList(NativeObject* list)
{
MOZ_ASSERT(list->getDenseInitializedLength() > 0);
return &list->getDenseElement(0).toObject().as<T>();
}
template<class T>
inline MOZ_MUST_USE T*
ShiftFromList(JSContext* cx, HandleNativeObject list)
{
uint32_t length = list->getDenseInitializedLength();
MOZ_ASSERT(length > 0);
Rooted<T*> entry(cx, &list->getDenseElement(0).toObject().as<T>());
if (!list->tryShiftDenseElements(1)) {
list->moveDenseElements(0, 1, length - 1);
list->shrinkElements(cx, length - 1);
}
list->setDenseInitializedLength(length - 1);
return entry;
}
} /* namespace js */
#endif /* vm_List_inl_h */

View File

@ -118,4 +118,3 @@ skip-if = os == 'win' || os == 'mac' || (os == 'linux' && !debug) # bug 1131110,
[test_wrappers.xul]
[test_xrayic.xul]
[test_xrayToJS.xul]
[test_asyncIteration.xul]

View File

@ -1,43 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1331092
-->
<window title="Mozilla Bug 1331092"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1331092"
target="_blank">Mozilla Bug 1331092</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
try {
eval(`
async function* f() {
}
`);
ok(false, "should throw");
} catch (e) {
ok(e instanceof SyntaxError, "Async Generator shouldn't be supported in chrome code");
}
try {
eval(`
async function f() {
for await (let x of []) {
}
}
`);
ok(false, "should throw");
} catch (e) {
ok(e instanceof SyntaxError, "for-await-of shouldn't be supported in chrome code");
}
]]></script>
</window>

View File

@ -90,16 +90,22 @@ public:
// Removes all entries from the hash table
void Clear();
protected:
LinkedList<UndisplayedNode>* GetListFor(nsIContent* aParentContent);
LinkedList<UndisplayedNode>* GetOrCreateListFor(nsIContent* aParentContent);
void AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
/**
* Get the applicable parent for the map lookup. This is almost always the
* provided argument, except if it's a <xbl:children> element, in which case
* it's the parent of the children element.
*
* All functions that are entry points into code that handles "parent"
* objects (used as the hash table keys) must ensure that the parent objects
* that they act on (and pass to other code) have been normalized by calling
* this method.
*/
nsIContent* GetApplicableParent(nsIContent* aParent);
static nsIContent* GetApplicableParent(nsIContent* aParent);
protected:
LinkedList<UndisplayedNode>* GetListFor(nsIContent* aParentContent);
LinkedList<UndisplayedNode>* GetOrCreateListFor(nsIContent* aParentContent);
void AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
};
//----------------------------------------------------------------------
@ -132,14 +138,17 @@ nsFrameManager::Destroy()
//----------------------------------------------------------------------
static nsIContent*
ParentForUndisplayedMap(const nsIContent* aContent)
/* static */ nsIContent*
nsFrameManager::ParentForUndisplayedMap(const nsIContent* aContent)
{
MOZ_ASSERT(aContent);
nsIContent* parent = aContent->GetParentElementCrossingShadowRoot();
MOZ_ASSERT(parent || !aContent->GetParent(), "no non-elements");
// Normalize the parent:
parent = UndisplayedMap::GetApplicableParent(parent);
return parent;
}
@ -158,7 +167,13 @@ nsFrameManager::GetUndisplayedNodeInMapFor(UndisplayedMap* aMap,
if (!aContent) {
return nullptr;
}
// This function is an entry point into UndisplayedMap handling code, so the
// parent that we act on must be normalized by GetApplicableParent (as per
// that function's documentation). We rely on ParentForUndisplayedMap to
// have done that for us.
nsIContent* parent = ParentForUndisplayedMap(aContent);
for (UndisplayedNode* node = aMap->GetFirstNode(parent);
node; node = node->getNext()) {
if (node->mContent == aContent)
@ -198,7 +213,12 @@ nsFrameManager::SetStyleContextInMap(UndisplayedMap* aMap,
MOZ_ASSERT(!GetStyleContextInMap(aMap, aContent),
"Already have an entry for aContent");
// This function is an entry point into UndisplayedMap handling code, so the
// parent that we act on must be normalized by GetApplicableParent (as per
// that function's documentation). We rely on ParentForUndisplayedMap to
// have done that for us.
nsIContent* parent = ParentForUndisplayedMap(aContent);
#ifdef DEBUG
nsIPresShell* shell = aStyleContext->PresContext()->PresShell();
NS_ASSERTION(parent || (shell && shell->GetDocument() &&
@ -206,6 +226,16 @@ nsFrameManager::SetStyleContextInMap(UndisplayedMap* aMap,
"undisplayed content must have a parent, unless it's the root "
"element");
#endif
// We set this bit as an optimization so that we can can know when a content
// node may have |display:none| or |display:contents| children. This allows
// other parts of the code to avoid checking for such children in
// mDisplayNoneMap and mDisplayContentsMap if the bit isn't present on a node
// that it's handling.
if (parent) {
parent->SetMayHaveChildrenWithLayoutBoxesDisabled();
}
aMap->AddNodeFor(parent, aContent, aStyleContext);
}
@ -231,7 +261,13 @@ nsFrameManager::ChangeStyleContextInMap(UndisplayedMap* aMap,
printf("ChangeStyleContextInMap(%d): p=%p \n", i++, (void *)aContent);
#endif
for (UndisplayedNode* node = aMap->GetFirstNode(aContent->GetParent());
// This function is an entry point into UndisplayedMap handling code, so the
// parent that we act on must be normalized by GetApplicableParent (as per
// that function's documentation). We rely on ParentForUndisplayedMap to
// have done that for us.
nsIContent* parent = ParentForUndisplayedMap(aContent);
for (UndisplayedNode* node = aMap->GetFirstNode(parent);
node; node = node->getNext()) {
if (node->mContent == aContent) {
node->mStyle = aStyleContext;
@ -255,8 +291,23 @@ nsFrameManager::UnregisterDisplayNoneStyleFor(nsIContent* aContent,
return;
}
for (UndisplayedNode* node = mDisplayNoneMap->GetFirstNode(aParentContent);
node; node = node->getNext()) {
// This function is an entry point into UndisplayedMap handling code, so we
// must call GetApplicableParent so the parent we pass around is correct.
aParentContent = UndisplayedMap::GetApplicableParent(aParentContent);
if (aParentContent &&
!aParentContent->MayHaveChildrenWithLayoutBoxesDisabled()) {
MOZ_ASSERT(!mDisplayNoneMap->GetFirstNode(aParentContent),
"MayHaveChildrenWithLayoutBoxesDisabled bit out of sync - "
"may fail to remove node from mDisplayNoneMap");
return;
}
UndisplayedNode* node = mDisplayNoneMap->GetFirstNode(aParentContent);
const bool haveOneDisplayNoneChild = node && !node->getNext();
for (; node; node = node->getNext()) {
if (node->mContent == aContent) {
mDisplayNoneMap->RemoveNodeFor(aParentContent, node);
@ -266,6 +317,22 @@ nsFrameManager::UnregisterDisplayNoneStyleFor(nsIContent* aContent,
// make sure that there are no more entries for the same content
MOZ_ASSERT(!GetDisplayNoneStyleFor(aContent),
"Found more undisplayed content data after removal");
if (haveOneDisplayNoneChild) {
// There are no more children of aParentContent in mDisplayNoneMap.
MOZ_ASSERT(!mDisplayNoneMap->GetFirstNode(aParentContent),
"Bad UnsetMayHaveChildrenWithLayoutBoxesDisabled call");
// If we also know that none of its children are in mDisplayContentsMap
// then we can call UnsetMayHaveChildrenWithLayoutBoxesDisabled. We
// don't want to check mDisplayContentsMap though since that involves a
// hash table lookup in relatively hot code. Still, we know there are
// no children in mDisplayContentsMap if the map is empty, so we do
// check for that.
if (aParentContent && !mDisplayContentsMap) {
aParentContent->UnsetMayHaveChildrenWithLayoutBoxesDisabled();
}
}
return;
}
}
@ -283,19 +350,37 @@ nsFrameManager::ClearAllMapsFor(nsIContent* aParentContent)
printf("ClearAllMapsFor(%d): parent=%p \n", i++, aParentContent);
#endif
if (mDisplayNoneMap) {
mDisplayNoneMap->RemoveNodesFor(aParentContent);
}
if (mDisplayContentsMap) {
nsAutoPtr<LinkedList<UndisplayedNode>> list =
mDisplayContentsMap->UnlinkNodesFor(aParentContent);
if (list) {
while (UndisplayedNode* node = list->popFirst()) {
ClearAllMapsFor(node->mContent);
delete node;
if (!aParentContent ||
aParentContent->MayHaveChildrenWithLayoutBoxesDisabled()) {
if (mDisplayNoneMap) {
mDisplayNoneMap->RemoveNodesFor(aParentContent);
}
if (mDisplayContentsMap) {
nsAutoPtr<LinkedList<UndisplayedNode>> list =
mDisplayContentsMap->UnlinkNodesFor(aParentContent);
if (list) {
while (UndisplayedNode* node = list->popFirst()) {
ClearAllMapsFor(node->mContent);
delete node;
}
}
}
if (aParentContent) {
aParentContent->UnsetMayHaveChildrenWithLayoutBoxesDisabled();
}
}
#ifdef DEBUG
else {
if (mDisplayNoneMap) {
MOZ_ASSERT(!mDisplayNoneMap->GetFirstNode(aParentContent),
"We failed to remove a node from mDisplayNoneMap");
}
if (mDisplayContentsMap) {
MOZ_ASSERT(!mDisplayContentsMap->GetFirstNode(aParentContent),
"We failed to remove a node from mDisplayContentsMap");
}
}
#endif
// Need to look at aParentContent's content list due to XBL insertions.
// Nodes in aParentContent's content list do not have aParentContent as a
@ -342,8 +427,23 @@ nsFrameManager::UnregisterDisplayContentsStyleFor(nsIContent* aContent,
return;
}
for (UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent);
node; node = node->getNext()) {
// This function is an entry point into UndisplayedMap handling code, so we
// must call GetApplicableParent so the parent we pass around is correct.
aParentContent = UndisplayedMap::GetApplicableParent(aParentContent);
if (aParentContent &&
!aParentContent->MayHaveChildrenWithLayoutBoxesDisabled()) {
MOZ_ASSERT(!mDisplayContentsMap->GetFirstNode(aParentContent),
"MayHaveChildrenWithLayoutBoxesDisabled bit out of sync - "
"may fail to remove node from mDisplayContentsMap");
return;
}
UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent);
const bool haveOneDisplayContentsChild = node && !node->getNext();
for (; node; node = node->getNext()) {
if (node->mContent == aContent) {
mDisplayContentsMap->RemoveNodeFor(aParentContent, node);
@ -354,6 +454,22 @@ nsFrameManager::UnregisterDisplayContentsStyleFor(nsIContent* aContent,
MOZ_ASSERT(!GetDisplayContentsStyleFor(aContent),
"Found more entries for aContent after removal");
ClearAllMapsFor(aContent);
if (haveOneDisplayContentsChild) {
// There are no more children of aParentContent in mDisplayContentsMap.
MOZ_ASSERT(!mDisplayContentsMap->GetFirstNode(aParentContent),
"Bad UnsetMayHaveChildrenWithLayoutBoxesDisabled call");
// If we also know that none of its children are in mDisplayNoneMap
// then we can call UnsetMayHaveChildrenWithLayoutBoxesDisabled. We
// don't want to check mDisplayNoneMap though since that involves a
// hash table lookup in relatively hot code. Still, we know there are
// no children in mDisplayNoneMap if the map is empty, so we do
// check for that.
if (aParentContent && !mDisplayNoneMap) {
aParentContent->UnsetMayHaveChildrenWithLayoutBoxesDisabled();
}
}
return;
}
}
@ -618,7 +734,8 @@ nsFrameManagerBase::UndisplayedMap::GetApplicableParent(nsIContent* aParent)
LinkedList<UndisplayedNode>*
nsFrameManagerBase::UndisplayedMap::GetListFor(nsIContent* aParent)
{
aParent = GetApplicableParent(aParent);
MOZ_ASSERT(aParent == GetApplicableParent(aParent),
"The parent that we use as the hash key must have been normalized");
LinkedList<UndisplayedNode>* list;
if (Get(aParent, &list)) {
@ -631,7 +748,9 @@ nsFrameManagerBase::UndisplayedMap::GetListFor(nsIContent* aParent)
LinkedList<UndisplayedNode>*
nsFrameManagerBase::UndisplayedMap::GetOrCreateListFor(nsIContent* aParent)
{
aParent = GetApplicableParent(aParent);
MOZ_ASSERT(aParent == GetApplicableParent(aParent),
"The parent that we use as the hash key must have been normalized");
return LookupOrAdd(aParent);
}

View File

@ -209,6 +209,8 @@ public:
void RestoreFrameStateFor(nsIFrame* aFrame, nsILayoutHistoryState* aState);
protected:
static nsIContent* ParentForUndisplayedMap(const nsIContent* aContent);
void ClearAllMapsFor(nsIContent* aParentContent);
static nsStyleContext* GetStyleContextInMap(UndisplayedMap* aMap,

View File

@ -13913,15 +13913,15 @@ CSSParserImpl::ParseContent()
// We need to divide the 'content' keywords into two classes for
// ParseVariant's sake, so we can't just use nsCSSProps::kContentKTable.
static const KTableEntry kContentListKWs[] = {
{ eCSSKeyword_open_quote, NS_STYLE_CONTENT_OPEN_QUOTE },
{ eCSSKeyword_close_quote, NS_STYLE_CONTENT_CLOSE_QUOTE },
{ eCSSKeyword_no_open_quote, NS_STYLE_CONTENT_NO_OPEN_QUOTE },
{ eCSSKeyword_no_close_quote, NS_STYLE_CONTENT_NO_CLOSE_QUOTE },
{ eCSSKeyword_open_quote, uint8_t(StyleContent::OpenQuote) },
{ eCSSKeyword_close_quote, uint8_t(StyleContent::CloseQuote) },
{ eCSSKeyword_no_open_quote, uint8_t(StyleContent::NoOpenQuote) },
{ eCSSKeyword_no_close_quote, uint8_t(StyleContent::NoCloseQuote) },
{ eCSSKeyword_UNKNOWN, -1 }
};
static const KTableEntry kContentSolitaryKWs[] = {
{ eCSSKeyword__moz_alt_content, NS_STYLE_CONTENT_ALT_CONTENT },
{ eCSSKeyword__moz_alt_content, uint8_t(StyleContent::AltContent) },
{ eCSSKeyword_UNKNOWN, -1 }
};

View File

@ -1147,11 +1147,11 @@ const KTableEntry nsCSSProps::kColorKTable[] = {
};
const KTableEntry nsCSSProps::kContentKTable[] = {
{ eCSSKeyword_open_quote, NS_STYLE_CONTENT_OPEN_QUOTE },
{ eCSSKeyword_close_quote, NS_STYLE_CONTENT_CLOSE_QUOTE },
{ eCSSKeyword_no_open_quote, NS_STYLE_CONTENT_NO_OPEN_QUOTE },
{ eCSSKeyword_no_close_quote, NS_STYLE_CONTENT_NO_CLOSE_QUOTE },
{ eCSSKeyword__moz_alt_content, NS_STYLE_CONTENT_ALT_CONTENT },
{ eCSSKeyword_open_quote, uint8_t(StyleContent::OpenQuote) },
{ eCSSKeyword_close_quote, uint8_t(StyleContent::CloseQuote) },
{ eCSSKeyword_no_open_quote, uint8_t(StyleContent::NoOpenQuote) },
{ eCSSKeyword_no_close_quote, uint8_t(StyleContent::NoCloseQuote) },
{ eCSSKeyword__moz_alt_content, uint8_t(StyleContent::AltContent) },
{ eCSSKeyword_UNKNOWN, -1 }
};

View File

@ -1541,6 +1541,7 @@ struct SetEnumValueHelper
DEFINE_ENUM_CLASS_SETTER(StyleBoxPack, Start, Justify)
DEFINE_ENUM_CLASS_SETTER(StyleBoxSizing, Content, Border)
DEFINE_ENUM_CLASS_SETTER(StyleClear, None, Both)
DEFINE_ENUM_CLASS_SETTER(StyleContent, OpenQuote, AltContent)
DEFINE_ENUM_CLASS_SETTER(StyleFillRule, Nonzero, Evenodd)
DEFINE_ENUM_CLASS_SETTER(StyleFloat, None, InlineEnd)
DEFINE_ENUM_CLASS_SETTER(StyleFloatEdge, ContentBox, MarginBox)
@ -8971,7 +8972,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
break;
case eCSSUnit_Enumerated: {
MOZ_ASSERT(contentValue->GetIntValue() == NS_STYLE_CONTENT_ALT_CONTENT,
MOZ_ASSERT(contentValue->GetIntValue() == int32_t(StyleContent::AltContent),
"unrecognized solitary content keyword");
content->AllocateContents(1);
content->ContentAt(0).SetKeyword(eStyleContentType_AltContent);
@ -9036,16 +9037,16 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
}
case eCSSUnit_Enumerated:
switch (value.GetIntValue()) {
case NS_STYLE_CONTENT_OPEN_QUOTE:
case uint8_t(StyleContent::OpenQuote):
data.SetKeyword(eStyleContentType_OpenQuote);
break;
case NS_STYLE_CONTENT_CLOSE_QUOTE:
case uint8_t(StyleContent::CloseQuote):
data.SetKeyword(eStyleContentType_CloseQuote);
break;
case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
case uint8_t(StyleContent::NoOpenQuote):
data.SetKeyword(eStyleContentType_NoOpenQuote);
break;
case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
case uint8_t(StyleContent::NoCloseQuote):
data.SetKeyword(eStyleContentType_NoCloseQuote);
break;
default:

View File

@ -406,11 +406,13 @@ enum class StyleImageLayerRepeat : uint8_t {
#define NS_STYLE_BORDER_IMAGE_SLICE_FILL 1
// See nsStyleContent
#define NS_STYLE_CONTENT_OPEN_QUOTE 0
#define NS_STYLE_CONTENT_CLOSE_QUOTE 1
#define NS_STYLE_CONTENT_NO_OPEN_QUOTE 2
#define NS_STYLE_CONTENT_NO_CLOSE_QUOTE 3
#define NS_STYLE_CONTENT_ALT_CONTENT 4
enum class StyleContent : uint8_t {
OpenQuote,
CloseQuote,
NoOpenQuote,
NoCloseQuote,
AltContent
};
// See nsStyleColor
#define NS_STYLE_CURSOR_AUTO 1

View File

@ -689,8 +689,12 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
!decoder_database_->IsComfortNoise(main_payload_type)) {
// The list can be empty here if we got nothing but DTMF payloads.
AudioDecoder* decoder = decoder_database_->GetDecoder(main_payload_type);
RTC_DCHECK(decoder); // Should always get a valid object, since we have
// already checked that the payload types are known.
// In Mozilla webrtc.org builds we can not assume a valid decoder for each
// known payload type as some codecs are not built.
if (!decoder) {
LOG(LS_WARNING) << "Unsupported rtp payload type: " << main_payload_type;
return kUnknownRtpPayloadType;
}
decoder->IncomingPacket(packet_list.front().payload.data(),
packet_list.front().payload.size(),
packet_list.front().sequence_number,

View File

@ -3493,7 +3493,7 @@ nsSocketTransport::CloseSocket(PRFileDesc *aFd, nsSocketTransportService *aSTS)
int err = WSAGetLastError();
SOCKET_LOG(("nsSocketTransport::CloseSocket - "
"GetOverlappedResult err=%x\n", err));
if (err != ERROR_IO_PENDING) {
if (err != ERROR_IO_INCOMPLETE) {
canClose = true;
}
}

View File

@ -1738,7 +1738,7 @@ nsSocketTransportService::CheckOverlappedPendingSocketsAreDone()
int err = WSAGetLastError();
SOCKET_LOG(("STS CheckOverlappedPendingSocketsAreDone "
"GetOverlappedResult failed error=%x \n", err));
if (err != ERROR_IO_PENDING) {
if (err != ERROR_IO_INCOMPLETE) {
canClose = true;
}
}

View File

@ -4351,6 +4351,12 @@ nsHalfOpenSocket::SetFastOpenConnected(nsresult aError, bool aWillRetry)
// Check if we want to restart connection!
if (aWillRetry &&
((aError == NS_ERROR_CONNECTION_REFUSED) ||
#if defined(_WIN64) && defined(WIN95)
// On Windows PR_ContinueConnect can return NS_ERROR_FAILURE.
// This will be fixed in bug 1386719 and this is just a temporary
// work around.
(aError == NS_ERROR_FAILURE) ||
#endif
(aError == NS_ERROR_NET_TIMEOUT))) {
if (mEnt->mUseFastOpen) {
gHttpHandler->IncrementFastOpenConsecutiveFailureCounter();

View File

@ -2,7 +2,6 @@
# 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/.
import errno
import os
import tempfile
import tarfile

View File

@ -178,7 +178,6 @@ HistoryStore.prototype = {
async applyIncomingBatch(records) {
let failed = [];
let blockers = [];
// Convert incoming records to mozIPlaceInfo objects. Some records can be
// ignored or handled directly, so we're rewriting the array in-place.
@ -189,9 +188,7 @@ HistoryStore.prototype = {
try {
if (record.deleted) {
let promise = this.remove(record);
promise = promise.catch(ex => failed.push(record.id));
blockers.push(promise);
await this.remove(record);
// No further processing needed. Remove it from the list.
shouldApply = false;
@ -213,20 +210,9 @@ HistoryStore.prototype = {
records.length = k; // truncate array
if (records.length) {
blockers.push(new Promise(resolve => {
let updatePlacesCallback = {
handleResult: function handleResult() {},
handleError: function handleError(resultCode, placeInfo) {
failed.push(placeInfo.guid);
},
handleCompletion: resolve,
};
this._asyncHistory.updatePlaces(records, updatePlacesCallback);
}));
await PlacesUtils.history.insertMany(records)
}
// failed is updated asynchronously, hence the await on blockers.
await Promise.all(blockers);
return failed;
},
@ -239,11 +225,8 @@ HistoryStore.prototype = {
*/
async _recordToPlaceInfo(record) {
// Sort out invalid URIs and ones Places just simply doesn't want.
record.url = PlacesUtils.normalizeToURLOrGUID(record.histUri);
record.uri = Utils.makeURI(record.histUri);
if (!record.uri) {
this._log.warn("Attempted to process invalid URI, skipping.");
throw new Error("Invalid URI in record");
}
if (!Utils.checkGUID(record.id)) {
this._log.warn("Encountered record with invalid GUID: " + record.id);
@ -300,8 +283,8 @@ HistoryStore.prototype = {
continue;
}
visit.visitDate = visit.date;
visit.transitionType = visit.type;
visit.date = PlacesUtils.toDate(visit.date);
visit.transition = visit.type;
k += 1;
}
record.visits.length = k; // truncate array

View File

@ -85,17 +85,17 @@ NS_INTERFACE_MAP_END
#define XPC_MAP_CLASSNAME AsyncStatementJSHelper
#define XPC_MAP_QUOTED_CLASSNAME "AsyncStatementJSHelper"
#define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_GETPROPERTY | \
#define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_RESOLVE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
#include "xpc_map_end.h"
NS_IMETHODIMP
AsyncStatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
jsid aId,
JS::Value *_result,
bool *_retval)
AsyncStatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
jsid aId,
bool *resolvedp,
bool *_retval)
{
if (!JSID_IS_STRING(aId))
return NS_OK;
@ -115,8 +115,14 @@ AsyncStatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
}
#endif
if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "params"))
return getParams(stmt, aCtx, scope, _result);
if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "params")) {
JS::RootedValue val(aCtx);
nsresult rv = getParams(stmt, aCtx, scope, val.address());
NS_ENSURE_SUCCESS(rv, rv);
*_retval = ::JS_DefinePropertyById(aCtx, scope, id, val, JSPROP_RESOLVING);
*resolvedp = true;
return NS_OK;
}
return NS_OK;
}

View File

@ -184,18 +184,15 @@ NS_INTERFACE_MAP_END
#define XPC_MAP_CLASSNAME StatementJSHelper
#define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper"
#define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_GETPROPERTY | \
XPC_SCRIPTABLE_WANT_RESOLVE | \
#define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_RESOLVE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
#include "xpc_map_end.h"
NS_IMETHODIMP
StatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
jsid aId,
JS::Value *_result,
bool *_retval)
StatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx, JSObject *aScopeObj,
jsid aId, bool *aResolvedp,
bool *_retval)
{
if (!JSID_IS_STRING(aId))
return NS_OK;
@ -215,33 +212,32 @@ StatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
static_cast<mozIStorageStatement *>(aWrapper->Native())
);
JSFlatString *str = JSID_TO_FLAT_STRING(id);
if (::JS_FlatStringEqualsAscii(str, "row"))
return getRow(stmt, aCtx, scope, _result);
if (::JS_FlatStringEqualsAscii(str, "params"))
return getParams(stmt, aCtx, scope, _result);
return NS_OK;
}
NS_IMETHODIMP
StatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx, JSObject *aScopeObj,
jsid aId, bool *aResolvedp,
bool *_retval)
{
if (!JSID_IS_STRING(aId))
return NS_OK;
JS::RootedObject scope(aCtx, aScopeObj);
if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) {
JSFlatString* str = JSID_TO_FLAT_STRING(id);
if (::JS_FlatStringEqualsAscii(str, "step")) {
*_retval = ::JS_DefineFunction(aCtx, scope, "step", stepFunc,
0, JSPROP_RESOLVING) != nullptr;
*aResolvedp = true;
return NS_OK;
}
JS::RootedValue val(aCtx);
if (::JS_FlatStringEqualsAscii(str, "row")) {
nsresult rv = getRow(stmt, aCtx, scope, val.address());
NS_ENSURE_SUCCESS(rv, rv);
*_retval = ::JS_DefinePropertyById(aCtx, scope, id, val, JSPROP_RESOLVING);
*aResolvedp = true;
return NS_OK;
}
if (::JS_FlatStringEqualsAscii(str, "params")) {
nsresult rv = getParams(stmt, aCtx, scope, val.address());
NS_ENSURE_SUCCESS(rv, rv);
*_retval = ::JS_DefinePropertyById(aCtx, scope, id, val, JSPROP_RESOLVING);
*aResolvedp = true;
return NS_OK;
}
return NS_OK;
}

View File

@ -17,8 +17,6 @@ only-for-attributes:
- nightly
not-for-build-platforms:
- linux-nightly/opt
- linux64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt

View File

@ -14,8 +14,6 @@ kind-dependencies:
- repackage-signing
only-for-build-platforms:
- linux-nightly/opt
- linux64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt

View File

@ -16,8 +16,6 @@ only-for-attributes:
- nightly
not-for-build-platforms:
- linux-nightly/opt
- linux64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt

View File

@ -15,8 +15,6 @@ kind-dependencies:
- nightly-l10n-signing
only-for-build-platforms:
- linux-nightly/opt
- linux64-nightly/opt
- macosx64-nightly/opt
- win32-nightly/opt
- win64-nightly/opt

View File

@ -15,10 +15,6 @@ kind-dependencies:
- repackage-l10n
only-for-build-platforms:
- linux-nightly/opt
- linux-devedition-nightly/opt
- linux64-nightly/opt
- linux64-devedition-nightly/opt
- macosx64-nightly/opt
- macosx64-devedition-nightly/opt
- win32-nightly/opt

View File

@ -15,10 +15,6 @@ kind-dependencies:
- build-signing
only-for-build-platforms:
- linux-nightly/opt
- linux-devedition-nightly/opt
- linux64-nightly/opt
- linux64-devedition-nightly/opt
- macosx64-nightly/opt
- macosx64-devedition-nightly/opt
- win32-nightly/opt

View File

@ -16,8 +16,6 @@ from taskgraph.transforms.task import task_description_schema
from voluptuous import Any, Required, Optional
import logging
import re
logger = logging.getLogger(__name__)
@ -65,15 +63,21 @@ _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N = [
# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
# See example in bug 1348286
UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
r'^(linux(|64)|macosx64)-nightly$': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
'host/bin/mar',
'host/bin/mbsdiff',
'macosx64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
"host/bin/mar",
"host/bin/mbsdiff",
],
r'^win(32|64)-nightly$': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
'macosx64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
'win64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
"host/bin/mar.exe",
"host/bin/mbsdiff.exe",
],
r'^(linux(|64)|macosx64|win(32|64))-nightly-l10n$': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
'win64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
'win32-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
"host/bin/mar.exe",
"host/bin/mbsdiff.exe",
],
'win32-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_L10N,
}
# Until bug 1331141 is fixed, if you are adding any new artifacts here that
@ -81,8 +85,10 @@ UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
# See example in bug 1348286
UPSTREAM_ARTIFACT_SIGNED_PATHS = {
r'^linux(|64)-nightly(|-l10n)$': ['target.tar.bz2', 'target.tar.bz2.asc'],
r'^win(32|64)-nightly(|-l10n)$': ['target.zip'],
'win64-nightly': ['target.zip'],
'win64-nightly-l10n': ['target.zip'],
'win32-nightly': ['target.zip'],
'win32-nightly-l10n': ['target.zip'],
}
# Until bug 1331141 is fixed, if you are adding any new artifacts here that
@ -90,32 +96,30 @@ UPSTREAM_ARTIFACT_SIGNED_PATHS = {
# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
# See example in bug 1348286
UPSTREAM_ARTIFACT_REPACKAGE_PATHS = {
r'^macosx64-nightly(|-l10n)$': ['target.dmg'],
'macosx64-nightly': ['target.dmg'],
'macosx64-nightly-l10n': ['target.dmg'],
}
# Until bug 1331141 is fixed, if you are adding any new artifacts here that
# need to be transfered to S3, please be aware you also need to follow-up
# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
# See example in bug 1348286
UPSTREAM_ARTIFACT_SIGNED_REPACKAGE_PATHS = {
r'^(linux(|64)|macosx64)-nightly(|-l10n)$': ['target.complete.mar'],
r'^win64-nightly(|-l10n)$': ['target.complete.mar', 'target.installer.exe'],
r'^win32-nightly(|-l10n)$': [
'macosx64-nightly': ['target.complete.mar'],
'macosx64-nightly-l10n': ['target.complete.mar'],
'win64-nightly': ['target.complete.mar', 'target.installer.exe'],
'win64-nightly-l10n': ['target.complete.mar', 'target.installer.exe'],
'win32-nightly': [
'target.complete.mar',
'target.installer.exe',
'target.stub-installer.exe'
],
'win32-nightly-l10n': [
'target.complete.mar',
'target.installer.exe',
'target.stub-installer.exe'
],
}
# Compile every regex once at import time
for dict_ in (
UPSTREAM_ARTIFACT_UNSIGNED_PATHS, UPSTREAM_ARTIFACT_SIGNED_PATHS,
UPSTREAM_ARTIFACT_REPACKAGE_PATHS, UPSTREAM_ARTIFACT_SIGNED_REPACKAGE_PATHS,
):
for uncompiled_regex, value in dict_.iteritems():
compiled_regex = re.compile(uncompiled_regex)
del dict_[uncompiled_regex]
dict_[compiled_regex] = value
# Voluptuous uses marker objects as dictionary *keys*, but they are not
# comparable, so we cast all of the keys back to regular strings
task_description_schema = {str(k): v for k, v in task_description_schema.schema.iteritems()}
@ -267,37 +271,18 @@ def generate_upstream_artifacts(build_task_ref, build_signing_task_ref,
]
for ref, tasktype, mapping in zip(task_refs, tasktypes, mapping):
plarform_was_previously_matched_by_regex = None
for platform_regex, paths in mapping.iteritems():
if platform_regex.match(platform) is not None:
_check_platform_matched_only_one_regex(
tasktype, platform, plarform_was_previously_matched_by_regex, platform_regex
)
upstream_artifacts.append({
"taskId": {"task-reference": ref},
"taskType": tasktype,
"paths": ["{}/{}".format(artifact_prefix, path) for path in paths],
"locale": locale or "en-US",
})
plarform_was_previously_matched_by_regex = platform_regex
if platform in mapping:
upstream_artifacts.append({
"taskId": {"task-reference": ref},
"taskType": tasktype,
"paths": ["{}/{}".format(artifact_prefix, p)
for p in mapping[platform]],
"locale": locale or "en-US",
})
return upstream_artifacts
def _check_platform_matched_only_one_regex(
task_type, platform, plarform_was_previously_matched_by_regex, platform_regex
):
if plarform_was_previously_matched_by_regex is not None:
raise Exception('In task type "{task_type}", platform "{platform}" matches at \
least 2 regular expressions. First matched: "{first_matched}". Second matched: \
"{second_matched}"'.format(
task_type=task_type, platform=platform,
first_matched=plarform_was_previously_matched_by_regex.pattern,
second_matched=platform_regex.pattern
))
def is_valid_beetmover_job(job):
# windows builds don't have docker-image, so fewer dependencies
if any(b in job['attributes']['build_platform'] for b in _WINDOWS_BUILD_PLATFORMS):

View File

@ -8,8 +8,6 @@ Transform the signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.signed_artifacts import generate_specifications_of_artifacts_to_sign
transforms = TransformSequence()
@ -36,26 +34,66 @@ def add_signed_routes(config, jobs):
@transforms.add
def define_upstream_artifacts(config, jobs):
def make_signing_description(config, jobs):
for job in jobs:
dep_job = job['dependent-task']
build_platform = dep_job.attributes.get('build_platform')
artifacts_specifications = generate_specifications_of_artifacts_to_sign(
build_platform,
dep_job.attributes.get('nightly'),
keep_locale_template=False
job['upstream-artifacts'] = _generate_upstream_artifacts(
dep_job.attributes.get('build_platform'),
dep_job.attributes.get('nightly')
)
if 'android' in build_platform:
# We're in the job that creates both multilocale and en-US APKs
artifacts_specifications[0]['artifacts'].append('public/build/en-US/target.apk')
job['upstream-artifacts'] = [{
'taskId': {'task-reference': '<build>'},
'taskType': 'build',
'paths': spec['artifacts'],
'formats': spec['formats'],
} for spec in artifacts_specifications]
yield job
def _generate_upstream_artifacts(build_platform, is_nightly=False):
if 'android' in build_platform:
artifacts_specificities = [{
'artifacts': [
'public/build/target.apk',
'public/build/en-US/target.apk'
],
'format': 'jar',
}]
# XXX: Mac and Windows don't sign mars because internal aren't signed at
# this stage of the release
elif 'macosx' in build_platform:
artifacts_specificities = [{
'artifacts': ['public/build/target.dmg'],
'format': 'macapp',
}]
elif 'win64' in build_platform:
artifacts_specificities = [{
'artifacts': [
'public/build/target.zip',
'public/build/setup.exe'
],
'format': 'sha2signcode',
}]
elif 'win32' in build_platform:
artifacts_specificities = [{
'artifacts': [
'public/build/target.zip',
'public/build/setup.exe',
],
'format': 'sha2signcode',
}]
if is_nightly:
artifacts_specificities[0]['artifacts'] += ['public/build/setup-stub.exe']
elif 'linux' in build_platform:
artifacts_specificities = [{
'artifacts': ['public/build/target.tar.bz2'],
'format': 'gpg',
}, {
'artifacts': ['public/build/update/target.complete.mar'],
'format': 'mar_sha384',
}]
else:
raise Exception("Platform not implemented for signing")
return [{
'taskId': {'task-reference': '<build>'},
'taskType': 'build',
'paths': specificity['artifacts'],
'formats': [specificity['format']],
} for specificity in artifacts_specificities]

View File

@ -31,10 +31,6 @@ JOB_NAME_WHITELIST = set([
'browser-haz-debug',
'linux-debug',
'linux-devedition',
'linux-devedition-nightly-repackage',
'linux-devedition-nightly-repackage-signing',
'linux-nightly-repackage',
'linux-nightly-repackage-signing',
'linux-opt',
'linux-pgo',
'linux64-add-on-devel',
@ -48,11 +44,7 @@ JOB_NAME_WHITELIST = set([
'linux64-clang-tidy',
'linux64-debug',
'linux64-devedition',
'linux64-devedition-nightly-repackage',
'linux64-devedition-nightly-repackage-signing',
'linux64-jsdcov-opt',
'linux64-nightly-repackage',
'linux64-nightly-repackage-signing',
'linux64-noopt-debug',
'linux64-opt',
'linux64-pgo',

View File

@ -8,7 +8,6 @@ Transform the signing task into an actual task description.
from __future__ import absolute_import, print_function, unicode_literals
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.signed_artifacts import generate_specifications_of_artifacts_to_sign
from taskgraph.util.treeherder import join_symbol
transforms = TransformSequence()
@ -20,6 +19,72 @@ def make_signing_description(config, jobs):
job['depname'] = 'unsigned-repack'
dep_job = job['dependent-task']
dep_platform = dep_job.attributes.get('build_platform')
job['upstream-artifacts'] = []
if 'android' in dep_platform:
job_specs = [
{
'artifacts': ['public/build/{locale}/target.apk'],
'format': 'jar',
},
]
elif 'macosx' in dep_platform:
job_specs = [
{
'artifacts': ['public/build/{locale}/target.dmg'],
'format': 'macapp',
}
]
elif 'win32' in dep_platform:
job_specs = [
{
'artifacts': [
'public/build/{locale}/target.zip',
'public/build/{locale}/setup.exe',
'public/build/{locale}/setup-stub.exe'
],
'format': 'sha2signcode',
}
]
elif 'win64' in dep_platform:
job_specs = [
{
'artifacts': [
'public/build/{locale}/target.zip',
'public/build/{locale}/setup.exe',
],
'format': 'sha2signcode',
}
]
elif 'linux' in dep_platform:
job_specs = [
{
'artifacts': ['public/build/{locale}/target.tar.bz2'],
'format': 'gpg',
}, {
'artifacts': ['public/build/{locale}/target.complete.mar'],
'format': 'mar_sha384',
}
]
else:
raise Exception("Platform not implemented for signing")
upstream_artifacts = []
for spec in job_specs:
fmt = spec['format']
upstream_artifacts.append({
"taskId": {"task-reference": "<unsigned-repack>"},
"taskType": "l10n",
# Set paths based on artifacts in the specs (above) one per
# locale present in the chunk this is signing stuff for.
"paths": [f.format(locale=l)
for l in dep_job.attributes.get('chunk_locales', [])
for f in spec['artifacts']],
"formats": [fmt]
})
job['upstream-artifacts'] = upstream_artifacts
# add the chunk number to the TH symbol
symbol = 'Ns{}'.format(dep_job.attributes.get('l10n_chunk'))
@ -30,34 +95,3 @@ def make_signing_description(config, jobs):
}
yield job
@transforms.add
def define_upstream_artifacts(config, jobs):
for job in jobs:
dep_job = job['dependent-task']
locale_specifications = generate_specifications_of_artifacts_to_sign(
dep_job.attributes.get('build_platform'),
is_nightly=True,
keep_locale_template=True
)
upstream_artifacts = []
for spec in locale_specifications:
upstream_artifacts.append({
'taskId': {'task-reference': '<unsigned-repack>'},
'taskType': 'l10n',
# Set paths based on artifacts in the specs (above) one per
# locale present in the chunk this is signing stuff for.
'paths': [
path_template.format(locale=locale)
for locale in dep_job.attributes.get('chunk_locales', [])
for path_template in spec['artifacts']
],
'formats': spec['formats']
})
job['upstream-artifacts'] = upstream_artifacts
yield job

View File

@ -148,15 +148,8 @@ def make_job_description(config, jobs):
if build_platform.startswith('win'):
worker_type = 'aws-provisioner-v1/gecko-%s-b-win2012' % level
run['use-magic-mh-args'] = False
else:
if build_platform.startswith('macosx'):
worker_type = 'aws-provisioner-v1/gecko-%s-b-macosx64' % level
elif build_platform.startswith('linux'):
worker_type = 'aws-provisioner-v1/gecko-%s-b-linux' % level
else:
raise NotImplementedError(
'Unsupported build_platform: "{}"'.format(build_platform)
)
elif build_platform.startswith('macosx'):
worker_type = 'aws-provisioner-v1/gecko-%s-b-macosx64' % level
run['tooltool-downloads'] = 'internal'
worker['docker-image'] = {"in-tree": "desktop-build"}
@ -192,26 +185,20 @@ def make_job_description(config, jobs):
def _generate_task_mozharness_config(build_platform):
if build_platform.startswith('macosx'):
return ['repackage/osx_signed.py']
elif build_platform.startswith('win'):
return ['repackage/win32_signed.py'] if '32' in build_platform \
else ['repackage/win64_signed.py']
else:
bits = 32 if '32' in build_platform else 64
if build_platform.startswith('linux'):
return ['repackage/linux{}_signed.py'.format(bits)]
elif build_platform.startswith('win'):
return ['repackage/win{}_signed.py'.format(bits)]
raise NotImplementedError('Unsupported build_platform: "{}"'.format(build_platform))
raise NotImplemented('Unsupported build_platform: "{}"'.format(build_platform))
def _generate_task_env(build_platform, build_task_ref, signing_task_ref, locale=None):
mar_prefix = _generate_taskcluster_prefix(build_task_ref, postfix='host/bin/', locale=None)
signed_prefix = _generate_taskcluster_prefix(signing_task_ref, locale=locale)
if build_platform.startswith('linux') or build_platform.startswith('macosx'):
tarball_extension = 'bz2' if build_platform.startswith('linux') else 'gz'
if build_platform.startswith('macosx'):
return {
'SIGNED_INPUT': {'task-reference': '{}target.tar.{}'.format(
signed_prefix, tarball_extension
)},
'SIGNED_INPUT': {'task-reference': '{}target.tar.gz'.format(signed_prefix)},
'UNSIGNED_MAR': {'task-reference': '{}mar'.format(mar_prefix)},
}
elif build_platform.startswith('win'):
@ -228,7 +215,8 @@ def _generate_task_env(build_platform, build_task_ref, signing_task_ref, locale=
}
return task_env
raise NotImplementedError('Unsupported build_platform: "{}"'.format(build_platform))
else:
raise NotImplemented('Unsupported build_platform: "{}"'.format(build_platform))
def _generate_taskcluster_prefix(task_id, postfix='', locale=None):
@ -240,23 +228,18 @@ def _generate_taskcluster_prefix(task_id, postfix='', locale=None):
def _generate_task_output_files(build_platform, locale=None):
locale_output_path = '{}/'.format(locale) if locale else ''
if build_platform.startswith('linux') or build_platform.startswith('macosx'):
output_files = [{
if build_platform.startswith('macosx'):
return [{
'type': 'file',
'path': '/home/worker/workspace/build/artifacts/{}target.dmg'
.format(locale_output_path),
'name': 'public/build/{}target.dmg'.format(locale_output_path),
}, {
'type': 'file',
'path': '/home/worker/workspace/build/artifacts/{}target.complete.mar'
.format(locale_output_path),
'name': 'public/build/{}target.complete.mar'.format(locale_output_path),
}]
if build_platform.startswith('macosx'):
output_files.append({
'type': 'file',
'path': '/home/worker/workspace/build/artifacts/{}target.dmg'
.format(locale_output_path),
'name': 'public/build/{}target.dmg'.format(locale_output_path),
})
elif build_platform.startswith('win'):
output_files = [{
'type': 'file',
@ -276,7 +259,6 @@ def _generate_task_output_files(build_platform, locale=None):
'name': 'public/build/{}target.stub-installer.exe'.format(locale_output_path),
})
if output_files:
return output_files
raise NotImplementedError('Unsupported build_platform: "{}"'.format(build_platform))
else:
raise NotImplemented('Unsupported build_platform: "{}"'.format(build_platform))

View File

@ -130,8 +130,6 @@ def make_repackage_signing_description(config, jobs):
}
funsize_platforms = [
'linux-nightly',
'linux64-nightly',
'macosx64-nightly',
'win32-nightly',
'win64-nightly'

View File

@ -136,6 +136,11 @@ def make_task_description(config, jobs):
'routes': job.get('routes', []),
}
if 'linux' in dep_job.attributes.get('build_platform') and \
dep_job.attributes.get('nightly'):
task['routes'].append("project.releng.funsize.level-{level}.{project}".format(
project=config.params['project'], level=config.params['level']))
yield task

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More