diff --git a/.eslintignore b/.eslintignore
index 86e31991e58..545843dd9ae 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -39,7 +39,6 @@ parser/**
probes/**
python/**
rdf/**
-services/**
startupcache/**
testing/**
tools/**
@@ -170,6 +169,11 @@ mobile/android/components/Snippets.js
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
mobile/android/modules/HomeProvider.jsm
+# services/ exclusions
+
+# Uses `#filter substitution`
+services/sync/modules/constants.js
+
# toolkit/ exclusions
# Not part of the default build
diff --git a/accessible/xpcom/xpcAccessibleGeneric.h b/accessible/xpcom/xpcAccessibleGeneric.h
index 1b7c6c40270..8f6d9878746 100644
--- a/accessible/xpcom/xpcAccessibleGeneric.h
+++ b/accessible/xpcom/xpcAccessibleGeneric.h
@@ -39,7 +39,7 @@ public:
}
xpcAccessibleGeneric(ProxyAccessible* aProxy, uint32_t aInterfaces) :
- mIntl(aProxy)
+ mIntl(aProxy), mSupportedIfaces(0)
{
if (aInterfaces & Interfaces::SELECTION) {
mSupportedIfaces |= eSelectable;
diff --git a/b2g/components/PersistentDataBlock.jsm b/b2g/components/PersistentDataBlock.jsm
index 72085a9b568..a26efe56d82 100644
--- a/b2g/components/PersistentDataBlock.jsm
+++ b/b2g/components/PersistentDataBlock.jsm
@@ -66,7 +66,7 @@ function toHexString(data) {
let hexString = "";
if (typeof data === "string") {
hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join("");
- } else if (typeof data === "array") {
+ } else if (data instanceof Array) {
hexString = data.map(toHexChar).join("");
}
return hexString;
diff --git a/b2g/components/test/unit/file_persistentdatablock.js b/b2g/components/test/unit/file_persistentdatablock.js
index 691cead2ae6..6ce3072ac3a 100644
--- a/b2g/components/test/unit/file_persistentdatablock.js
+++ b/b2g/components/test/unit/file_persistentdatablock.js
@@ -33,7 +33,7 @@ function toHexString(data) {
let hexString = "";
if (typeof data === "string") {
hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join("");
- } else if (typeof data === "array") {
+ } else if (data instanceof Array) {
hexString = data.map(toHexChar).join("");
}
return hexString;
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index 4633a631b9d..4b632ffd65b 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -543,3 +543,5 @@ skip-if = !e10s || !crashreporter
skip-if = !e10s || !crashreporter
[browser_aboutTabCrashed_showForm.js]
skip-if = !e10s || !crashreporter
+[browser_aboutTabCrashed_withoutDump.js]
+skip-if = !e10s
diff --git a/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js b/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js
new file mode 100644
index 00000000000..4a41b16d4d2
--- /dev/null
+++ b/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js
@@ -0,0 +1,44 @@
+"use strict";
+
+const PAGE = "data:text/html,
A%20regular,%20everyday,%20normal%20page.";
+
+/**
+ * Monkey patches TabCrashHandler.getDumpID to return null in order to test
+ * about:tabcrashed when a dump is not available.
+ */
+add_task(function* setup() {
+ let originalGetDumpID = TabCrashHandler.getDumpID;
+ TabCrashHandler.getDumpID = function(browser) { return null; };
+ registerCleanupFunction(() => {
+ TabCrashHandler.getDumpID = originalGetDumpID;
+ });
+});
+
+/**
+ * Tests tab crash page when a dump is not available.
+ */
+add_task(function* test_without_dump() {
+ return BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: PAGE,
+ }, function*(browser) {
+ let tab = gBrowser.getTabForBrowser(browser);
+ yield BrowserTestUtils.crashBrowser(browser);
+
+ let tabRemovedPromise = BrowserTestUtils.removeTab(tab, { dontRemove: true });
+
+ yield ContentTask.spawn(browser, null, function*() {
+ let doc = content.document;
+ ok(!doc.documentElement.classList.contains("crashDumpAvailable"),
+ "doesn't have crash dump");
+
+ let container = doc.getElementById("crash-reporter-container");
+ ok(container, "has crash-reporter-container");
+ ok(container.hidden, "crash-reporter-container is hidden");
+
+ doc.getElementById("closeTab").click();
+ });
+
+ yield tabRemovedPromise;
+ });
+});
diff --git a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
index f0627d61179..53c6d99f411 100644
--- a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
+++ b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
@@ -32,6 +32,7 @@ const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/NetUtil.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
'resource://gre/modules/PrivateBrowsingUtils.jsm');
@@ -304,17 +305,10 @@ ShumwayStreamConverterBase.prototype = {
// Create a new channel that loads the viewer as a chrome resource.
var viewerUrl = 'chrome://shumway/content/viewer.wrapper.html';
- // TODO use only newChannel2 after FF37 is released.
- var channel = Services.io.newChannel2 ?
- Services.io.newChannel2(viewerUrl,
- null,
- null,
- null, // aLoadingNode
- Services.scriptSecurityManager.getSystemPrincipal(),
- null, // aTriggeringPrincipal
- Ci.nsILoadInfo.SEC_NORMAL,
- Ci.nsIContentPolicy.TYPE_OTHER) :
- Services.io.newChannel(viewerUrl, null, null);
+ var channel = NetUtil.newChannel({
+ uri: viewerUrl,
+ loadUsingSystemPrincipal: true
+ });
var converter = this;
var listener = this.listener;
@@ -370,7 +364,7 @@ ShumwayStreamConverterBase.prototype = {
.getService(Ci.nsIScriptSecurityManager);
var resourcePrincipal = securityManager.getSystemPrincipal();
aRequest.owner = resourcePrincipal;
- channel.asyncOpen(proxy, aContext);
+ channel.asyncOpen2(proxy);
},
// nsIRequestObserver::onStopRequest
diff --git a/browser/modules/ContentCrashHandlers.jsm b/browser/modules/ContentCrashHandlers.jsm
index 336dc8ff2c4..4ebef698e5b 100644
--- a/browser/modules/ContentCrashHandlers.jsm
+++ b/browser/modules/ContentCrashHandlers.jsm
@@ -228,7 +228,7 @@ this.TabCrashHandler = {
let dumpID = this.getDumpID(browser);
if (!dumpID) {
- message.target.sendAsyncMessge("SetCrashReportAvailable", {
+ message.target.sendAsyncMessage("SetCrashReportAvailable", {
hasReport: false,
});
return;
diff --git a/config/config.mk b/config/config.mk
index 648b8c455b7..b5cd9c6f6e2 100644
--- a/config/config.mk
+++ b/config/config.mk
@@ -189,19 +189,12 @@ OS_LDFLAGS += $(_DEBUG_LDFLAGS)
# XXX: What does this? Bug 482434 filed for better explanation.
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
-ifdef MOZ_DEBUG
-ifneq (,$(MOZ_BROWSE_INFO)$(MOZ_BSCFILE))
-OS_CFLAGS += -FR
-OS_CXXFLAGS += -FR
-endif
-else # ! MOZ_DEBUG
+ifndef MOZ_DEBUG
# MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
# Used for generating an optimized build with debugging symbols.
# Used in the Windows nightlies to generate symbols for crash reporting.
ifdef MOZ_DEBUG_SYMBOLS
-OS_CXXFLAGS += -UDEBUG -DNDEBUG
-OS_CFLAGS += -UDEBUG -DNDEBUG
ifdef HAVE_64BIT_BUILD
OS_LDFLAGS += -DEBUG -OPT:REF,ICF
else
@@ -211,10 +204,8 @@ endif
#
# Handle DMD in optimized builds.
-# No opt to give sane callstacks.
#
ifdef MOZ_DMD
-MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
ifdef HAVE_64BIT_BUILD
OS_LDFLAGS = -DEBUG -OPT:REF,ICF
else
diff --git a/configure.in b/configure.in
index 41b69e4e1f7..7c1c999be69 100644
--- a/configure.in
+++ b/configure.in
@@ -8748,7 +8748,6 @@ if test -n "$MOZ_TELEMETRY_REPORTING" || test -n "$MOZ_SERVICES_HEALTHREPORT" ||
fi
dnl win32 options
-AC_SUBST(MOZ_BROWSE_INFO)
AC_SUBST(WIN32_REDIST_DIR)
AC_SUBST(MAKENSISU)
diff --git a/devtools/client/preferences/devtools.js b/devtools/client/preferences/devtools.js
index 0da0bfd1bf1..cdb26a42db7 100644
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -294,6 +294,10 @@ pref("devtools.webconsole.persistlog", false);
// any timestamps.
pref("devtools.webconsole.timestampMessages", false);
+// Web Console automatic multiline mode: |true| if you want incomplete statements
+// to automatically trigger multiline editing (equivalent to shift + enter).
+pref("devtools.webconsole.autoMultiline", true);
+
// The number of lines that are displayed in the web console for the Net,
// CSS, JS and Web Developer categories. These defaults should be kept in sync
// with DEFAULT_LOG_LIMIT in the webconsole frontend.
diff --git a/devtools/client/webconsole/test/browser.ini b/devtools/client/webconsole/test/browser.ini
index 2f0d875f8af..ccef9fd6f7e 100644
--- a/devtools/client/webconsole/test/browser.ini
+++ b/devtools/client/webconsole/test/browser.ini
@@ -329,6 +329,7 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
[browser_webconsole_live_filtering_of_message_types.js]
[browser_webconsole_live_filtering_on_search_strings.js]
[browser_webconsole_message_node_id.js]
+[browser_webconsole_multiline_input.js]
[browser_webconsole_netlogging.js]
[browser_webconsole_netlogging_basic.js]
[browser_webconsole_netlogging_panel.js]
diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
index f790d188ef6..38ce77c6cfc 100644
--- a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
@@ -7,9 +7,13 @@
const TEST_URI = "data:text/html;charset=utf-8,bug 585991 - autocomplete " +
"popup keyboard usage test";
+
+// We should turn off auto-multiline editing during these tests
+const PREF_AUTO_MULTILINE = "devtools.webconsole.autoMultiline";
var HUD, popup, jsterm, inputNode, completeNode;
add_task(function*() {
+ Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, false);
yield loadTab(TEST_URI);
let hud = yield openConsole();
@@ -23,6 +27,7 @@ add_task(function*() {
yield popupHideAfterCompletionInText();
HUD = popup = jsterm = inputNode = completeNode = null;
+ Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, true);
});
var consoleOpened = Task.async(function*(aHud) {
diff --git a/devtools/client/webconsole/test/browser_webconsole_multiline_input.js b/devtools/client/webconsole/test/browser_webconsole_multiline_input.js
new file mode 100644
index 00000000000..f3164590e63
--- /dev/null
+++ b/devtools/client/webconsole/test/browser_webconsole_multiline_input.js
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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/. */
+
+// Tests that the console waits for more input instead of evaluating
+// when valid, but incomplete, statements are present upon pressing enter
+// -or- when the user ends a line with shift + enter.
+
+"use strict";
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+ "test/test-console.html";
+
+let SHOULD_ENTER_MULTILINE = [
+ {input: "function foo() {" },
+ {input: "var a = 1," },
+ {input: "var a = 1;", shiftKey: true },
+ {input: "function foo() { }", shiftKey: true },
+ {input: "function" },
+ {input: "(x) =>" },
+ {input: "let b = {" },
+ {input: "let a = [" },
+ {input: "{" },
+ {input: "{ bob: 3343," },
+ {input: "function x(y=" },
+ {input: "Array.from(" },
+ // shift + enter creates a new line despite parse errors
+ {input: "{2,}", shiftKey: true },
+];
+let SHOULD_EXECUTE = [
+ {input: "function foo() { }" },
+ {input: "var a = 1;" },
+ {input: "function foo() { var a = 1; }" },
+ {input: '"asdf"' },
+ {input: '99 + 3' },
+ {input: '1, 2, 3' },
+ // errors
+ {input: 'function f(x) { let y = 1, }' },
+ {input: 'function f(x=,) {' },
+ {input: '{2,}' },
+];
+
+add_task(function* () {
+ let { tab, browser } = yield loadTab(TEST_URI);
+ let hud = yield openConsole();
+ let inputNode = hud.jsterm.inputNode;
+
+ for (let test of SHOULD_ENTER_MULTILINE) {
+ hud.jsterm.setInputValue(test.input);
+ EventUtils.synthesizeKey("VK_RETURN", { shiftKey: test.shiftKey });
+ let inputValue = hud.jsterm.getInputValue();
+ is(inputNode.selectionStart, inputNode.selectionEnd,
+ "selection is collapsed");
+ is(inputNode.selectionStart, inputValue.length,
+ "caret at end of multiline input");
+ let inputWithNewline = test.input + "\n";
+ is(inputValue, inputWithNewline, "Input value is correct");
+ }
+
+ for (let test of SHOULD_EXECUTE) {
+ hud.jsterm.setInputValue(test.input);
+ EventUtils.synthesizeKey("VK_RETURN", { shiftKey: test.shiftKey });
+ let inputValue = hud.jsterm.getInputValue();
+ is(inputNode.selectionStart, 0, "selection starts/ends at 0");
+ is(inputNode.selectionEnd, 0, "selection starts/ends at 0");
+ is(inputValue, "", "Input value is cleared");
+ }
+
+});
diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js
index 3b12a9eaede..3626684ce3e 100644
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -11,6 +11,7 @@ const {Cc, Ci, Cu} = require("chrome");
const {Utils: WebConsoleUtils, CONSOLE_WORKER_IDS} =
require("devtools/shared/webconsole/utils");
const promise = require("promise");
+const Debugger = require("Debugger");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
@@ -198,6 +199,7 @@ const MIN_FONT_SIZE = 10;
const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout";
const PREF_PERSISTLOG = "devtools.webconsole.persistlog";
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
+const PREF_AUTO_MULTILINE = "devtools.webconsole.autoMultiline";
const PREF_INPUT_HISTORY_COUNT = "devtools.webconsole.inputHistoryCount";
/**
@@ -3880,11 +3882,13 @@ JSTerm.prototype = {
break;
}
return;
- } else if (event.shiftKey &&
- event.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) {
- // shift return
- // TODO: expand the inputNode height by one line
- return;
+ } else if (event.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) {
+ let autoMultiline = Services.prefs.getBoolPref(PREF_AUTO_MULTILINE);
+ if (event.shiftKey ||
+ (!Debugger.isCompilableUnit(inputNode.value) && autoMultiline)) {
+ // shift return or incomplete statement
+ return;
+ }
}
switch (event.keyCode) {
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index fc8826eefc3..2a3f759b50f 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2272,7 +2272,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
// Refresh the principal on the compartment.
if (nsPIDOMWindowInner* win = GetInnerWindow()) {
- win->RefreshCompartmentPrincipal();
+ nsGlobalWindow::Cast(win)->RefreshCompartmentPrincipal();
}
}
@@ -13413,5 +13413,5 @@ nsIDocument::ReportHasScrollLinkedEffect()
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Async Pan/Zoom"),
this, nsContentUtils::eLAYOUT_PROPERTIES,
- "ScrollLinkedEffectFound");
+ "ScrollLinkedEffectFound2");
}
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index edfa2e9919f..57e3aa2db2e 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -480,7 +480,7 @@ public:
bool DispatchResizeEvent(const mozilla::CSSIntSize& aSize);
// Inner windows only.
- virtual void RefreshCompartmentPrincipal() override;
+ void RefreshCompartmentPrincipal();
// For accessing protected field mFullScreen
friend class FullscreenTransitionTask;
@@ -1427,7 +1427,7 @@ public:
// |interval| is in milliseconds.
nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
int32_t interval,
- bool aIsInterval, int32_t* aReturn) override;
+ bool aIsInterval, int32_t* aReturn);
int32_t SetTimeoutOrInterval(JSContext* aCx,
mozilla::dom::Function& aFunction,
int32_t aTimeout,
@@ -1437,13 +1437,7 @@ public:
int32_t aTimeout, bool aIsInterval,
mozilla::ErrorResult& aError);
void ClearTimeoutOrInterval(int32_t aTimerID,
- mozilla::ErrorResult& aError);
- nsresult ClearTimeoutOrInterval(int32_t aTimerID) override
- {
- mozilla::ErrorResult rv;
- ClearTimeoutOrInterval(aTimerID, rv);
- return rv.StealNSResult();
- }
+ mozilla::ErrorResult& aError);
// JS specific timeout functions (JS args grabbed from context).
nsresult ResetTimersForNonBackgroundWindow();
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index c76852e5a65..77bbac8b93e 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -151,32 +151,6 @@ public:
return mParentTarget;
}
- bool HasMutationListeners(uint32_t aMutationEventType) const
- {
- MOZ_ASSERT(IsInnerWindow());
-
- if (!mOuterWindow) {
- NS_ERROR("HasMutationListeners() called on orphan inner window!");
-
- return false;
- }
-
- return (mMutationBits & aMutationEventType) != 0;
- }
-
- void SetMutationListeners(uint32_t aType)
- {
- MOZ_ASSERT(IsInnerWindow());
-
- if (!mOuterWindow) {
- NS_ERROR("HasMutationListeners() called on orphan inner window!");
-
- return;
- }
-
- mMutationBits |= aType;
- }
-
virtual void MaybeUpdateTouchState() {}
nsIDocument* GetExtantDoc() const
@@ -242,14 +216,6 @@ public:
virtual bool IsFrozen() const = 0;
- // Add a timeout to this window.
- virtual nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
- int32_t interval,
- bool aIsInterval, int32_t *aReturn) = 0;
-
- // Clear a timeout from this window.
- virtual nsresult ClearTimeoutOrInterval(int32_t aTimerID) = 0;
-
nsPIDOMWindowOuter* GetOuterWindow()
{
return mIsInnerWindow ? mOuterWindow.get() : AsOuter();
@@ -383,43 +349,6 @@ public:
*/
virtual void FinishFullscreenChange(bool aIsFullscreen) = 0;
- /**
- * Call this to check whether some node (this window, its document,
- * or content in that document) has a mouseenter/leave event listener.
- */
- bool HasMouseEnterLeaveEventListeners()
- {
- return mMayHaveMouseEnterLeaveEventListener;
- }
-
- /**
- * Call this to indicate that some node (this window, its document,
- * or content in that document) has a mouseenter/leave event listener.
- */
- void SetHasMouseEnterLeaveEventListeners()
- {
- mMayHaveMouseEnterLeaveEventListener = true;
- }
-
- /**
- * Call this to check whether some node (this window, its document,
- * or content in that document) has a Pointerenter/leave event listener.
- */
- bool HasPointerEnterLeaveEventListeners()
- {
- return mMayHavePointerEnterLeaveEventListener;
- }
-
- /**
- * Call this to indicate that some node (this window, its document,
- * or content in that document) has a Pointerenter/leave event listener.
- */
- void SetHasPointerEnterLeaveEventListeners()
- {
- mMayHavePointerEnterLeaveEventListener = true;
- }
-
-
virtual JSObject* GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) = 0;
virtual void CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
JS::Handle aHandler) = 0;
@@ -578,14 +507,6 @@ public:
*/
virtual bool DispatchCustomEvent(const nsAString& aEventName) = 0;
- /**
- * Call when the document principal may have changed and the compartment
- * principal needs to be updated.
- *
- * Inner windows only.
- */
- virtual void RefreshCompartmentPrincipal() = 0;
-
/**
* Like nsIDOMWindow::Open, except that we don't navigate to the given URL.
*
@@ -798,6 +719,65 @@ public:
nsPerformance* GetPerformance();
+ bool HasMutationListeners(uint32_t aMutationEventType) const
+ {
+ if (!mOuterWindow) {
+ NS_ERROR("HasMutationListeners() called on orphan inner window!");
+
+ return false;
+ }
+
+ return (mMutationBits & aMutationEventType) != 0;
+ }
+
+ void SetMutationListeners(uint32_t aType)
+ {
+ if (!mOuterWindow) {
+ NS_ERROR("HasMutationListeners() called on orphan inner window!");
+
+ return;
+ }
+
+ mMutationBits |= aType;
+ }
+
+ /**
+ * Call this to check whether some node (this window, its document,
+ * or content in that document) has a mouseenter/leave event listener.
+ */
+ bool HasMouseEnterLeaveEventListeners()
+ {
+ return mMayHaveMouseEnterLeaveEventListener;
+ }
+
+ /**
+ * Call this to indicate that some node (this window, its document,
+ * or content in that document) has a mouseenter/leave event listener.
+ */
+ void SetHasMouseEnterLeaveEventListeners()
+ {
+ mMayHaveMouseEnterLeaveEventListener = true;
+ }
+
+ /**
+ * Call this to check whether some node (this window, its document,
+ * or content in that document) has a Pointerenter/leave event listener.
+ */
+ bool HasPointerEnterLeaveEventListeners()
+ {
+ return mMayHavePointerEnterLeaveEventListener;
+ }
+
+ /**
+ * Call this to indicate that some node (this window, its document,
+ * or content in that document) has a Pointerenter/leave event listener.
+ */
+ void SetHasPointerEnterLeaveEventListeners()
+ {
+ mMayHavePointerEnterLeaveEventListener = true;
+ }
+
+
protected:
void CreatePerformanceObjectIfNeeded();
};
diff --git a/dom/base/nsXHTMLContentSerializer.cpp b/dom/base/nsXHTMLContentSerializer.cpp
index 12e14d3b692..ed3bb84f76c 100644
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -511,7 +511,7 @@ nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
}
bool
-nsXHTMLContentSerializer::CheckElementEnd(Element* aElement,
+nsXHTMLContentSerializer::CheckElementEnd(mozilla::dom::Element* aElement,
bool& aForceFormat,
nsAString& aStr)
{
diff --git a/dom/bindings/GenerateCSS2PropertiesWebIDL.py b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
index 5cf358e73b3..f92b24b45b6 100644
--- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py
+++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
@@ -5,20 +5,34 @@
import sys
import string
+# Generates a line of WebIDL with the given spelling of the property name
+# (whether camelCase, _underscorePrefixed, etc.) and the given array of
+# extended attributes.
+def generateLine(propName, extendedAttrs):
+ return " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs),
+ propName)
propList = eval(sys.stdin.read())
props = ""
for [name, prop, id, flags, pref, proptype] in propList:
if "CSS_PROPERTY_INTERNAL" in flags:
continue
+ # Unfortunately, even some of the getters here are fallible
+ # (e.g. on nsComputedDOMStyle).
extendedAttrs = ["Throws", "TreatNullAs=EmptyString"]
if pref is not "":
extendedAttrs.append('Pref="%s"' % pref)
+
+ # webkit properties get a capitalized "WebkitFoo" accessor (added here)
+ # as well as a camelcase "webkitFoo" accessor (added next).
+ if (prop.startswith("Webkit")):
+ props += generateLine(prop, extendedAttrs)
+
+ # Generate a line with camelCase spelling of property-name (or capitalized,
+ # for Moz-prefixed properties):
if not prop.startswith("Moz"):
prop = prop[0].lower() + prop[1:]
- # Unfortunately, even some of the getters here are fallible
- # (e.g. on nsComputedDOMStyle).
- props += " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs),
- prop)
+ props += generateLine(prop, extendedAttrs)
+
# Per spec, what's actually supposed to happen here is that we're supposed
# to have properties for:
#
@@ -30,18 +44,17 @@ for [name, prop, id, flags, pref, proptype] in propList:
# Note that "float" will cause a property called "float" to exist due to (1)
# in that list.
#
- # In practice, cssFloat is the only case in which "name" doesn't contain "-"
- # but also doesn't match "prop". So the stuff we did with "prop" covers (3)
- # and all of (1) except "float". If we now output attributes for all the
- # cases where "name" doesn't match "prop" and "name" doesn't start with "-",
- # that will cover "float" and (2).
+ # In practice, cssFloat is the only case in which "name" doesn't contain
+ # "-" but also doesn't match "prop". So the above generatePropLine() call
+ # covered (3) and all of (1) except "float". If we now output attributes
+ # for all the cases where "name" doesn't match "prop" and "name" doesn't
+ # start with "-", that will cover "float" and (2).
if prop != name and name[0] != "-":
extendedAttrs.append('BinaryName="%s"' % prop)
# Throw in a '_' before the attribute name, because some of these
# property names collide with IDL reserved words.
- props += " [%s] attribute DOMString _%s;\n" % (
- ", ".join(extendedAttrs),
- name)
+ props += generateLine("_" + name, extendedAttrs)
+
idlFile = open(sys.argv[1], "r")
idlTemplate = idlFile.read()
diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp
index 2d1989def2d..5bb46165e19 100644
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1304,8 +1304,7 @@ WebGLContext::ClearScreen()
const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
if (changeDrawBuffers) {
- const GLenum back = LOCAL_GL_BACK;
- gl->fDrawBuffers(1, &back);
+ gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
}
GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
@@ -1317,7 +1316,7 @@ WebGLContext::ClearScreen()
ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha);
if (changeDrawBuffers) {
- gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0);
+ gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0);
}
}
diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h
index a7eeba956f2..dafbe702306 100644
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -827,7 +827,8 @@ protected:
public:
void Disable(GLenum cap);
void Enable(GLenum cap);
- bool GetStencilBits(GLint* out_stencilBits);
+ bool GetStencilBits(GLint* const out_stencilBits);
+ bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val);
virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
void GetParameter(JSContext* cx, GLenum pname,
diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp
index ef3716142ae..34543116fea 100644
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -994,6 +994,10 @@ WebGLContext::Hint(GLenum target, GLenum mode)
switch (target) {
case LOCAL_GL_GENERATE_MIPMAP_HINT:
+ // Deprecated and removed in desktop GL Core profiles.
+ if (gl->IsCoreProfile())
+ return;
+
isValid = true;
break;
diff --git a/dom/canvas/WebGLContextState.cpp b/dom/canvas/WebGLContextState.cpp
index 8f3563a0dcf..ea818e4004f 100644
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -73,7 +73,7 @@ StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
}
bool
-WebGLContext::GetStencilBits(GLint* out_stencilBits)
+WebGLContext::GetStencilBits(GLint* const out_stencilBits)
{
*out_stencilBits = 0;
if (mBoundDrawFramebuffer) {
@@ -97,9 +97,107 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits)
return true;
}
+bool
+WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val)
+{
+ if (mBoundDrawFramebuffer) {
+ if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
+ return false;
+ }
+
+ if (!mBoundDrawFramebuffer) {
+ switch (pname) {
+ case LOCAL_GL_RED_BITS:
+ case LOCAL_GL_GREEN_BITS:
+ case LOCAL_GL_BLUE_BITS:
+ *out_val = 8;
+ break;
+
+ case LOCAL_GL_ALPHA_BITS:
+ *out_val = (mOptions.alpha ? 8 : 0);
+ break;
+
+ case LOCAL_GL_DEPTH_BITS:
+ if (mOptions.depth) {
+ const auto& glFormats = gl->GetGLFormats();
+
+ GLenum depthFormat = glFormats.depth;
+ if (mOptions.stencil && glFormats.depthStencil) {
+ depthFormat = glFormats.depthStencil;
+ }
+
+ if (depthFormat == LOCAL_GL_DEPTH_COMPONENT16) {
+ *out_val = 16;
+ } else {
+ *out_val = 24;
+ }
+ } else {
+ *out_val = 0;
+ }
+ break;
+
+ case LOCAL_GL_STENCIL_BITS:
+ *out_val = (mOptions.stencil ? 8 : 0);
+ break;
+
+ default:
+ MOZ_CRASH("bad pname");
+ }
+ return true;
+ }
+
+ if (!gl->IsCoreProfile()) {
+ gl->fGetIntegerv(pname, out_val);
+ return true;
+ }
+
+ GLenum fbAttachment = 0;
+ GLenum fbPName = 0;
+ switch (pname) {
+ case LOCAL_GL_RED_BITS:
+ fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
+ break;
+
+ case LOCAL_GL_GREEN_BITS:
+ fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
+ break;
+
+ case LOCAL_GL_BLUE_BITS:
+ fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
+ break;
+
+ case LOCAL_GL_ALPHA_BITS:
+ fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
+ break;
+
+ case LOCAL_GL_DEPTH_BITS:
+ fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
+ break;
+
+ case LOCAL_GL_STENCIL_BITS:
+ fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT;
+ fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
+ break;
+
+ default:
+ MOZ_CRASH("bad pname");
+ }
+
+ gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment,
+ fbPName, out_val);
+ return true;
+}
+
JS::Value
WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
{
+ const char funcName[] = "getParameter";
+
if (IsContextLost())
return JS::NullValue();
@@ -356,11 +454,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::Int32Value(refValue & stencilMask);
}
- case LOCAL_GL_STENCIL_BITS: {
- GLint stencilBits = 0;
- GetStencilBits(&stencilBits);
- return JS::Int32Value(stencilBits);
- }
+
case LOCAL_GL_STENCIL_CLEAR_VALUE:
case LOCAL_GL_UNPACK_ALIGNMENT:
case LOCAL_GL_PACK_ALIGNMENT:
@@ -370,28 +464,26 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
case LOCAL_GL_MAX_VERTEX_ATTRIBS:
case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
- case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
- case LOCAL_GL_RED_BITS:
- case LOCAL_GL_GREEN_BITS:
- case LOCAL_GL_BLUE_BITS: {
+ case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
return JS::Int32Value(i);
}
- case LOCAL_GL_DEPTH_BITS: {
- GLint i = 0;
- if (!mNeedsFakeNoDepth) {
- gl->fGetIntegerv(pname, &i);
- }
- return JS::Int32Value(i);
- }
- case LOCAL_GL_ALPHA_BITS: {
- GLint i = 0;
- if (!mNeedsFakeNoAlpha) {
- gl->fGetIntegerv(pname, &i);
- }
- return JS::Int32Value(i);
+
+ case LOCAL_GL_RED_BITS:
+ case LOCAL_GL_GREEN_BITS:
+ case LOCAL_GL_BLUE_BITS:
+ case LOCAL_GL_ALPHA_BITS:
+ case LOCAL_GL_DEPTH_BITS:
+ case LOCAL_GL_STENCIL_BITS: {
+ // Deprecated and removed in GL Core profiles, so special handling required.
+ GLint val;
+ if (!GetChannelBits(funcName, pname, &val))
+ return JS::NullValue();
+
+ return JS::Int32Value(val);
}
+
case LOCAL_GL_MAX_TEXTURE_SIZE:
return JS::Int32Value(mImplMaxTextureSize);
diff --git a/dom/canvas/WebGLExtensionTextureFloat.cpp b/dom/canvas/WebGLExtensionTextureFloat.cpp
index a7a58939ad1..4568e994ee9 100644
--- a/dom/canvas/WebGLExtensionTextureFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureFloat.cpp
@@ -32,15 +32,17 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
fua->AllowUnsizedTexFormat(pi, usage);
};
- const bool needSizedInternal = !gl->IsGLES();
- MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
+ const bool needsSwizzle = gl->IsCoreProfile();
+ MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
+
+ const bool needsSizedFormat = !gl->IsGLES();
////////////////
pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSizedFormat) {
dui.internalFormat = LOCAL_GL_RGBA32F;
}
fnAdd(webgl::EffectiveFormat::RGBA32F);
@@ -50,7 +52,7 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSizedFormat) {
dui.internalFormat = LOCAL_GL_RGB32F;
}
fnAdd(webgl::EffectiveFormat::RGB32F);
@@ -60,9 +62,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
}
fnAdd(webgl::EffectiveFormat::Luminance32F);
@@ -71,9 +75,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_ALPHA32F_ARB;
}
fnAdd(webgl::EffectiveFormat::Alpha32F);
@@ -82,9 +88,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
}
fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
}
@@ -101,10 +109,9 @@ WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl)
if (!gl->IsSupported(gl::GLFeature::texture_float))
return false;
- const bool needSizedInternal = !gl->IsGLES();
+ const bool needsSwizzle = gl->IsCoreProfile();
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
-
- if (needSizedInternal && !hasSwizzle)
+ if (needsSwizzle && !hasSwizzle)
return false;
return true;
diff --git a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
index a5770999d67..e59f9b232ee 100644
--- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
@@ -30,8 +30,10 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
fua->AllowUnsizedTexFormat(pi, usage);
};
- const bool needSizedInternal = !gl->IsGLES();
- MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
+ const bool needsSwizzle = gl->IsCoreProfile();
+ MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
+
+ const bool needsSizedFormat = !gl->IsGLES();
GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
@@ -44,7 +46,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSizedFormat) {
dui.internalFormat = LOCAL_GL_RGBA16F;
}
fnAdd(webgl::EffectiveFormat::RGBA16F);
@@ -54,7 +56,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSizedFormat) {
dui.internalFormat = LOCAL_GL_RGB16F;
}
fnAdd(webgl::EffectiveFormat::RGB16F);
@@ -64,9 +66,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
}
fnAdd(webgl::EffectiveFormat::Luminance16F);
@@ -75,9 +79,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_ALPHA16F_ARB;
}
fnAdd(webgl::EffectiveFormat::Alpha16F);
@@ -86,9 +92,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
- if (needSizedInternal) {
+ if (needsSwizzle) {
dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
+ } else if (needsSizedFormat) {
+ dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
}
fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
}
@@ -108,10 +116,9 @@ WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl)
return false;
}
- const bool needSizedInternal = !gl->IsGLES();
+ const bool needsSwizzle = gl->IsCoreProfile();
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
-
- if (needSizedInternal && !hasSwizzle)
+ if (needsSwizzle && !hasSwizzle)
return false;
return true;
diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build
index ffa942025ce..a157e9d91c8 100644
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -7,7 +7,7 @@
TEST_DIRS += ['compiledtest']
# Number changes to this file to avoid bug 1081323 (clobber after changing a manifest):
-# 3
+# 5
MOCHITEST_MANIFESTS += [
'test/crossorigin/mochitest.ini',
diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini
index d6cd17dd6b4..138ee94d696 100644
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -3,10 +3,51 @@ subsuite = webgl
skip-if = ((os == 'linux') && (buildapp == 'b2g'))
support-files =
+ webgl-mochitest/ensure-exts/ensure-ext.js
webgl-mochitest/driver-info.js
webgl-mochitest/es3-data.js
webgl-mochitest/webgl-util.js
+[webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html]
+fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
+[webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html]
+fail-if = (os == 'android')
+[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
+fail-if = (os == 'android')
+[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
+[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
+fail-if = (os == 'android')
+[webgl-mochitest/ensure-exts/test_EXT_sRGB.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac' && os_version == '10.6') || (os == 'win')
+[webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
+[webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html]
+fail-if = (os == 'android') || (os == 'linux')
+[webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html]
+fail-if = (os == 'android')
+[webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html]
+fail-if = (os == 'android')
+[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
+[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
+[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html]
+# Win7 is 6.1
+fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html]
+fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
+[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html]
+fail-if = (os == 'android') || (os == 'linux')
+[webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html]
+fail-if = (os == 'mac' && os_version == '10.6')
+[webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html]
+# Win7 is 6.1
+fail-if = (os == 'android') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+
+[webgl-mochitest/ensure-exts/test_common.html]
+
+
[webgl-mochitest/test_backbuffer_channels.html]
fail-if = (os == 'b2g')
[webgl-mochitest/test_depth_readpixels.html]
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js
new file mode 100644
index 00000000000..798067d5e42
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js
@@ -0,0 +1,32 @@
+'use strict';
+
+function EnsureExt(name, shouldBe = true) {
+ var c = document.createElement('canvas');
+ var gl = c.getContext('experimental-webgl');
+
+ if (shouldBe) {
+ ok(gl.getExtension(name), 'Should have extension ' + name + '.');
+ } else {
+ ok(!gl.getExtension(name), 'Should not have extension ' + name + '.');
+ }
+}
+
+function EnsureDraftExt(name, shouldBe = true) {
+ SimpleTest.waitForExplicitFinish();
+
+ var fnEnsure = function() {
+ EnsureExt(name, shouldBe);
+ SimpleTest.finish();
+ };
+
+ if ('SpecialPowers' in window) {
+ var prefStateList = [
+ ['webgl.enable-draft-extensions', true],
+ ];
+ var prefEnv = {'set': prefStateList};
+ SpecialPowers.pushPrefEnv(prefEnv, fnEnsure);
+ } else {
+ console.log('Couldn\'t use SpecialPowers to enable draft extensions.');
+ fnEnsure();
+ }
+}
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html
new file mode 100644
index 00000000000..04b24d90c10
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html
new file mode 100644
index 00000000000..903269e6b66
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html
new file mode 100644
index 00000000000..3ac21299c68
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html
new file mode 100644
index 00000000000..e0b90adbbb5
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html
new file mode 100644
index 00000000000..3c7f3867917
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html
new file mode 100644
index 00000000000..da5aa0a3fbf
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html
new file mode 100644
index 00000000000..e64ff94848c
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html
new file mode 100644
index 00000000000..877c4440bf3
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html
new file mode 100644
index 00000000000..3e7b7a39622
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html
new file mode 100644
index 00000000000..aeb8f271ea0
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html
new file mode 100644
index 00000000000..6d68f0b4e2b
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html
new file mode 100644
index 00000000000..21c824ad854
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html
new file mode 100644
index 00000000000..327625c0184
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html
new file mode 100644
index 00000000000..c9548139842
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html
new file mode 100644
index 00000000000..6ad80011064
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html
new file mode 100644
index 00000000000..957171c160e
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html
new file mode 100644
index 00000000000..18774d0d68a
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html
new file mode 100644
index 00000000000..3b5907a8a88
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py
index bac482c3d73..919ba232804 100644
--- a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py
+++ b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py
@@ -28,7 +28,8 @@ def ReadLocalFile(include):
return data
-kSimpleTestReplacement = '''\n
+kSimpleTestReplacement = '''
+
-\n'''
+
+'''
fin = open(mochiPath, 'rb')
fout = open(testPath, 'wb')
diff --git a/dom/devicestorage/test/mochitest.ini b/dom/devicestorage/test/mochitest.ini
index cee91b441da..a2367739f9c 100644
--- a/dom/devicestorage/test/mochitest.ini
+++ b/dom/devicestorage/test/mochitest.ini
@@ -10,7 +10,6 @@ support-files = devicestorage_common.js
[test_available.html]
[test_basic.html]
[test_dirs.html]
-skip-if = e10s # Bug 1063569.
# [test_diskSpace.html]
# Possible race between the time we write a file, and the
# time it takes to be reflected by statfs(). Bug # 791287
diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp
index 7b1d1c25f7d..a9410f5d8cf 100644
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -1017,7 +1017,7 @@ HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
do_QueryInterface(inst));
if (formSubmitObserver) {
rv = formSubmitObserver->Notify(this,
- window->GetCurrentInnerWindow(),
+ window ? window->GetCurrentInnerWindow() : nullptr,
aActionURL,
aCancelSubmit);
NS_ENSURE_SUCCESS(rv, rv);
diff --git a/dom/locales/en-US/chrome/layout/layout_errors.properties b/dom/locales/en-US/chrome/layout/layout_errors.properties
index b276ea27a7f..11acea9ebbb 100644
--- a/dom/locales/en-US/chrome/layout/layout_errors.properties
+++ b/dom/locales/en-US/chrome/layout/layout_errors.properties
@@ -9,4 +9,4 @@ ImageMapPolyWrongNumberOfCoords=The "coords" attribute of the tag is missing the last "y" coordinate (the correct format is "x1,y1,x2,y2 …").
TablePartRelPosWarning=Relative positioning of table rows and row groups is now supported. This site may need to be updated because it may depend on this feature having no effect.
-ScrollLinkedEffectFound=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developers.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!
+ScrollLinkedEffectFound2=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!
diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp
index 20f42b1e0c9..a83e5e8059b 100644
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -936,6 +936,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
mVideoTracks.mDemuxer = mInputDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
MOZ_ASSERT(mVideoTracks.mDemuxer);
info.mVideo = *mVideoTracks.mDemuxer->GetInfo()->GetAsVideoInfo();
+ info.mVideo.mTrackId = 2;
}
uint32_t numAudios = mInputDemuxer->GetNumberTracks(TrackInfo::kAudioTrack);
@@ -944,6 +945,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
mAudioTracks.mDemuxer = mInputDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
MOZ_ASSERT(mAudioTracks.mDemuxer);
info.mAudio = *mAudioTracks.mDemuxer->GetInfo()->GetAsAudioInfo();
+ info.mAudio.mTrackId = 1;
}
int64_t videoDuration = numVideos ? info.mVideo.mDuration : 0;
diff --git a/dom/permission/tests/test_permissions_api.html b/dom/permission/tests/test_permissions_api.html
index c936b46e91a..5cced3597af 100644
--- a/dom/permission/tests/test_permissions_api.html
+++ b/dom/permission/tests/test_permissions_api.html
@@ -31,14 +31,6 @@ const UNSUPPORTED_PERMISSIONS = [
'midi'
];
-function setup() {
- return new Promise((resolve, reject) => {
- SpecialPowers.pushPrefEnv({'set': [
- ['dom.permissions.enabled', true],
- ]}, resolve);
- });
-}
-
function setPermissions(action) {
let permissions = PERMISSIONS.map(x => {
return { 'type': x.perm, 'allow': action, 'context': document };
@@ -111,8 +103,7 @@ function testInvalidQuery() {
}
function runTests() {
- setup()
- .then(checkUnsupportedPermissions)
+ checkUnsupportedPermissions()
.then(checkUserVisiblePushPermission)
.then(() => setPermissions(UNKNOWN_ACTION))
.then(() => checkPermissions('prompt'))
diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
index aad18ebbe43..904c02b3d2e 100644
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1850,7 +1850,8 @@ nsPluginHost::GetSpecialType(const nsACString & aMIMEType)
}
if (aMIMEType.LowerCaseEqualsASCII("application/x-shockwave-flash") ||
- aMIMEType.LowerCaseEqualsASCII("application/futuresplash")) {
+ aMIMEType.LowerCaseEqualsASCII("application/futuresplash") ||
+ aMIMEType.LowerCaseEqualsASCII("application/x-shockwave-flash-test")) {
return eSpecialType_Flash;
}
diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp
index 4ee3198bc4f..1db10e3fc66 100755
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -673,6 +673,7 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit)
, mNPPIface(nullptr)
, mPlugin(nullptr)
, mTaskFactory(this)
+ , mSandboxLevel(0)
, mIsFlashPlugin(false)
, mIsStartingAsync(false)
, mNPInitialized(false)
@@ -736,7 +737,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
, mHangUIParent(nullptr)
, mHangUIEnabled(true)
, mIsTimerReset(true)
- , mSandboxLevel(aSandboxLevel)
#ifdef MOZ_CRASHREPORTER
, mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
, mCrashReporter(nullptr)
@@ -754,6 +754,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
{
NS_ASSERTION(mSubprocess, "Out of memory!");
sInstantiated = true;
+ mSandboxLevel = aSandboxLevel;
mRunID = GeckoChildProcessHost::GetUniqueID();
#ifdef MOZ_ENABLE_PROFILER_SPS
@@ -2669,6 +2670,23 @@ PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
if (mIsFlashPlugin) {
parentInstance->InitMetadata(strPluginType, srcAttribute);
+#ifdef XP_WIN
+ // Force windowless mode (bug 1201904) when sandbox level >= 2
+ if (mSandboxLevel >= 2) {
+ NS_NAMED_LITERAL_CSTRING(wmodeAttributeName, "wmode");
+ NS_NAMED_LITERAL_CSTRING(opaqueAttributeValue, "opaque");
+ auto wmodeAttributeIndex =
+ names.IndexOf(wmodeAttributeName, 0, comparator);
+ if (wmodeAttributeIndex != names.NoIndex) {
+ if (!values[wmodeAttributeIndex].EqualsLiteral("transparent")) {
+ values[wmodeAttributeIndex].Assign(opaqueAttributeValue);
+ }
+ } else {
+ names.AppendElement(wmodeAttributeName);
+ values.AppendElement(opaqueAttributeValue);
+ }
+ }
+#endif
}
// Release the surrogate reference that was in pdata
diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h
index d60def64662..f4784b6f1fc 100644
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -325,6 +325,7 @@ protected:
TimeDuration mTimeBlocked;
nsCString mPluginName;
nsCString mPluginVersion;
+ int32_t mSandboxLevel;
bool mIsFlashPlugin;
#ifdef MOZ_X11
@@ -548,7 +549,6 @@ private:
PluginHangUIParent *mHangUIParent;
bool mHangUIEnabled;
bool mIsTimerReset;
- int32_t mSandboxLevel;
#ifdef MOZ_CRASHREPORTER
/**
* This mutex protects the crash reporter when the Plugin Hang UI event
diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini
index dffa7d8f428..b4f6c49acc2 100644
--- a/dom/plugins/test/mochitest/mochitest.ini
+++ b/dom/plugins/test/mochitest/mochitest.ini
@@ -120,6 +120,8 @@ skip-if = toolkit != "cocoa"
[test_twostreams.html]
[test_windowed_invalidate.html]
skip-if = os != "win"
+[test_windowless_flash.html]
+skip-if = !(os == "win" && processor == "x86_64")
[test_windowless_ime.html]
skip-if = os != "win" || e10s
[test_visibility.html]
diff --git a/dom/plugins/test/mochitest/test_windowless_flash.html b/dom/plugins/test/mochitest/test_windowless_flash.html
new file mode 100644
index 00000000000..8274a78aeb7
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_windowless_flash.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/storage/DOMStorageCache.cpp b/dom/storage/DOMStorageCache.cpp
index c2f049569b2..4c84ac0dcbb 100644
--- a/dom/storage/DOMStorageCache.cpp
+++ b/dom/storage/DOMStorageCache.cpp
@@ -564,9 +564,16 @@ DOMStorageCache::Clear(const DOMStorage* aStorage)
void
DOMStorageCache::CloneFrom(const DOMStorageCache* aThat)
{
- mLoaded = aThat->mLoaded;
+ // This will never be called on anything else than SessionStorage.
+ // This means mData will never be touched on any other thread than
+ // the main thread and it never went through the loading process.
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mPersistent);
+ MOZ_ASSERT(!(bool)aThat->mLoaded);
+
+ mLoaded = false;
mInitialized = aThat->mInitialized;
- mPersistent = aThat->mPersistent;
+ mPersistent = false;
mSessionOnlyDataSetActive = aThat->mSessionOnlyDataSetActive;
for (uint32_t i = 0; i < kDataSetCount; ++i) {
diff --git a/dom/storage/DOMStorageCache.h b/dom/storage/DOMStorageCache.h
index 3ee3ce1e5c7..2bd4737f45b 100644
--- a/dom/storage/DOMStorageCache.h
+++ b/dom/storage/DOMStorageCache.h
@@ -15,6 +15,7 @@
#include "nsHashKeys.h"
#include "mozilla/Monitor.h"
#include "mozilla/Telemetry.h"
+#include "mozilla/Atomics.h"
#include "nsAutoPtr.h"
namespace mozilla {
@@ -220,8 +221,9 @@ private:
// Flag that is initially false. When the cache is about to work with
// the database (i.e. it is persistent) this flags is set to true after
// all keys and coresponding values are loaded from the database.
- // This flag never goes from true back to false.
- bool mLoaded;
+ // This flag never goes from true back to false. Since this flag is
+ // critical for mData hashtable synchronization, it's made atomic.
+ Atomic mLoaded;
// Result of load from the database. Valid after mLoaded flag has been set.
nsresult mLoadResult;
diff --git a/dom/system/gonk/SystemProperty.cpp b/dom/system/gonk/SystemProperty.cpp
index 6fd1e86666c..1f874ce908b 100644
--- a/dom/system/gonk/SystemProperty.cpp
+++ b/dom/system/gonk/SystemProperty.cpp
@@ -5,8 +5,11 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SystemProperty.h"
-#include
+#include
+#include
+
+#include "nsDebug.h"
#include "prinit.h"
namespace mozilla {
diff --git a/dom/system/gonk/VolumeCommand.h b/dom/system/gonk/VolumeCommand.h
index a2e7c69b82b..022965b5e02 100644
--- a/dom/system/gonk/VolumeCommand.h
+++ b/dom/system/gonk/VolumeCommand.h
@@ -48,13 +48,13 @@ public:
// Response codes from the 200, 400, and 500 series all indicated that
// the command has completed.
- return (mResponseCode >= ResponseCode::CommandOkay)
- && (mResponseCode < ResponseCode::UnsolicitedInformational);
+ return (mResponseCode >= ::ResponseCode::CommandOkay)
+ && (mResponseCode < ::ResponseCode::UnsolicitedInformational);
}
bool WasSuccessful() const
{
- return mResponseCode == ResponseCode::CommandOkay;
+ return mResponseCode == ::ResponseCode::CommandOkay;
}
bool IsPending() const { return mPending; }
@@ -79,7 +79,7 @@ private:
#else
mResponseStr = aResponseStr;
#endif
- if (mResponseCode >= ResponseCode::CommandOkay) {
+ if (mResponseCode >= ::ResponseCode::CommandOkay) {
// This is a final response.
mPending = false;
}
diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl
index cb08be68149..74ee74909e5 100644
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -100,7 +100,7 @@ interface NavigatorFeatures {
};
partial interface Navigator {
- [Throws, Pref="dom.permissions.enabled"]
+ [Throws]
readonly attribute Permissions permissions;
};
diff --git a/dom/webidl/PermissionStatus.webidl b/dom/webidl/PermissionStatus.webidl
index 27ae490c391..3abfd66f407 100644
--- a/dom/webidl/PermissionStatus.webidl
+++ b/dom/webidl/PermissionStatus.webidl
@@ -13,8 +13,7 @@ enum PermissionState {
"prompt"
};
-[Exposed=(Window),
- Pref="dom.permissions.enabled"]
+[Exposed=(Window)]
interface PermissionStatus : EventTarget {
readonly attribute PermissionState state;
attribute EventHandler onchange;
diff --git a/dom/webidl/Permissions.webidl b/dom/webidl/Permissions.webidl
index 776a22ff843..17574c75e59 100644
--- a/dom/webidl/Permissions.webidl
+++ b/dom/webidl/Permissions.webidl
@@ -22,8 +22,7 @@ dictionary PushPermissionDescriptor : PermissionDescriptor {
boolean userVisible = false;
};
-[Exposed=(Window),
- Pref="dom.permissions.enabled"]
+[Exposed=(Window)]
interface Permissions {
[Throws]
Promise query(object permission);
diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
index 7f4af258525..2a0d81ae540 100644
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -1242,11 +1242,6 @@ public:
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
- // "If registration's waiting worker's skip waiting flag is set"
- if (mRegistration->mWaitingWorker->SkipWaitingFlag()) {
- mRegistration->PurgeActiveWorker();
- }
-
Done(NS_OK);
// Activate() is invoked out of band of atomic.
mRegistration->TryToActivate();
diff --git a/editor/libeditor/nsEditor.cpp b/editor/libeditor/nsEditor.cpp
index bc604c141df..ba0c1fa9913 100644
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -1480,7 +1480,7 @@ nsEditor::JoinNodes(nsINode& aLeftNode, nsINode& aRightNode)
parent->AsDOMNode());
}
- nsresult result;
+ nsresult result = NS_OK;
RefPtr txn = CreateTxnForJoinNode(aLeftNode, aRightNode);
if (txn) {
result = DoTransaction(txn);
diff --git a/editor/libeditor/nsHTMLEditor.cpp b/editor/libeditor/nsHTMLEditor.cpp
index f635c16d8b2..ca5684a5aad 100644
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -547,7 +547,7 @@ nsHTMLEditor::BeginningOfDocument()
// Find first editable thingy
bool done = false;
nsCOMPtr curNode = rootElement.get(), selNode;
- int32_t curOffset = 0, selOffset;
+ int32_t curOffset = 0, selOffset = 0;
while (!done) {
nsWSRunObject wsObj(this, curNode, curOffset);
int32_t visOffset = 0;
diff --git a/editor/txtsvc/nsTextServicesDocument.cpp b/editor/txtsvc/nsTextServicesDocument.cpp
index 587b4ad9f9e..46a6eedf0ec 100644
--- a/editor/txtsvc/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/nsTextServicesDocument.cpp
@@ -2754,7 +2754,7 @@ nsTextServicesDocument::GetUncollapsedSelection(nsITextServicesDocument::TSDBloc
nsCOMPtr startParent, endParent;
int32_t startOffset, endOffset;
int32_t rangeCount, tableCount, i;
- int32_t e1s1, e1s2, e2s1, e2s2;
+ int32_t e1s1 = 0, e1s2 = 0, e2s1 = 0, e2s2 = 0;
OffsetEntry *eStart, *eEnd;
int32_t eStartOffset, eEndOffset;
diff --git a/gfx/2d/BaseMargin.h b/gfx/2d/BaseMargin.h
index 28bc648c5de..a4ef5fe2424 100644
--- a/gfx/2d/BaseMargin.h
+++ b/gfx/2d/BaseMargin.h
@@ -21,10 +21,10 @@ struct Sides final {
mBits = aSideBits;
}
bool IsEmpty() const { return mBits == 0; }
- bool Top() const { return mBits & eSideBitsTop; }
- bool Right() const { return mBits & eSideBitsRight; }
- bool Bottom() const { return mBits & eSideBitsBottom; }
- bool Left() const { return mBits & eSideBitsLeft; }
+ bool Top() const { return (mBits & eSideBitsTop) != 0; }
+ bool Right() const { return (mBits & eSideBitsRight) != 0; }
+ bool Bottom() const { return (mBits & eSideBitsBottom) != 0; }
+ bool Left() const { return (mBits & eSideBitsLeft) != 0; }
bool Contains(SideBits aSideBits) const
{
MOZ_ASSERT((aSideBits & ~eSideBitsAll) == 0, "illegal side bits");
diff --git a/gfx/2d/Matrix.h b/gfx/2d/Matrix.h
index 53203477b70..1bd826bedcc 100644
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -298,8 +298,8 @@ public:
*/
bool HasNonIntegerTranslation() const {
return HasNonTranslation() ||
- !FuzzyEqual(_31, floor(_31 + 0.5)) ||
- !FuzzyEqual(_32, floor(_32 + 0.5));
+ !FuzzyEqual(_31, floor(_31 + Float(0.5))) ||
+ !FuzzyEqual(_32, floor(_32 + Float(0.5)));
}
/**
diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp
index f67b283365b..1739afb324b 100755
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -846,7 +846,8 @@ DrawBuffer::Create(GLContext* const gl,
DrawBuffer::~DrawBuffer()
{
- mGL->MakeCurrent();
+ if (!mGL->MakeCurrent())
+ return;
GLuint fb = mFB;
GLuint rbs[] = {
@@ -923,7 +924,8 @@ ReadBuffer::Create(GLContext* gl,
ReadBuffer::~ReadBuffer()
{
- mGL->MakeCurrent();
+ if (!mGL->MakeCurrent())
+ return;
GLuint fb = mFB;
GLuint rbs[] = {
diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp
index ea23b50c0f5..c28fc904b81 100644
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -137,7 +137,7 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor,
{
APZThreadUtils::AssertOnCompositorThread();
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
@@ -1186,7 +1186,7 @@ void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
const Maybe& aConstraints)
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
RefPtr node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
@@ -1245,7 +1245,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform()
// matched APZCs is the same. It is simplest to ensure that by flushing the
// pending repaint requests, which makes all of the untransforms empty (and
// therefore equal).
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
mTreeLock.AssertCurrentThreadOwns();
ForEachNode(mRootNode.get(),
@@ -1270,7 +1270,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
void
APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
RefPtr apzc = FindRootContentOrRootApzc();
if (apzc) {
apzc->AdjustScrollForSurfaceShift(aShift);
@@ -1286,7 +1286,7 @@ APZCTreeManager::ClearTree()
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
mInputQueue.get(), &InputQueue::Clear));
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
// Collect the nodes into a list, and then destroy each one.
// We can't destroy them as we collect them, because ForEachNode()
@@ -1308,7 +1308,7 @@ APZCTreeManager::ClearTree()
RefPtr
APZCTreeManager::GetRootNode() const
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
return mRootNode;
}
@@ -1500,7 +1500,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
already_AddRefed
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
RefPtr node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
RefPtr apzc = node ? node->GetApzc() : nullptr;
@@ -1519,7 +1519,7 @@ APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
already_AddRefed
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult)
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
HitTestResult hitResult = HitNothing;
ParentLayerPoint point = ViewAs(aPoint,
PixelCastJustification::ScreenIsParentLayerForRoot);
@@ -1552,7 +1552,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr
APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics)
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
return DepthFirstSearch(mRootNode.get(),
[&aDragMetrics](HitTestingTreeNode* aNode) {
@@ -1877,7 +1877,7 @@ ScreenToParentLayerMatrix4x4
APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@@ -1918,7 +1918,7 @@ ParentLayerToScreenMatrix4x4
APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@@ -1947,7 +1947,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co
already_AddRefed
APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
- MonitorAutoLock lock(mTreeLock);
+ MutexAutoLock lock(mTreeLock);
RefPtr apzc;
// For now, we only ever want to do pinching on the root-content APZC for
// a given layers id.
diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h
index 56e70ead86a..d4dffe0fc85 100644
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -17,7 +17,7 @@
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/layers/APZUtils.h" // for HitTestResult
#include "mozilla/layers/TouchCounter.h"// for TouchCounter
-#include "mozilla/Monitor.h" // for Monitor
+#include "mozilla/Mutex.h" // for Mutex
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
#include "mozilla/Vector.h" // for mozilla::Vector
#include "nsAutoPtr.h" // for nsRefPtr
@@ -534,7 +534,7 @@ private:
* is considered part of the APZC tree management state.
* Finally, the lock needs to be held when accessing mZoomConstraints.
* IMPORTANT: See the note about lock ordering at the top of this file. */
- mutable mozilla::Monitor mTreeLock;
+ mutable mozilla::Mutex mTreeLock;
RefPtr mRootNode;
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp
index 51ae4c49be8..9bcc9473f5b 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -155,6 +155,14 @@ using mozilla::gfx::PointTyped;
* pixels would make us drop to low-res at y=490...990.\n
* This value is in layer pixels.
*
+ * \li\b apz.displayport_expiry_ms
+ * While a scrollable frame is scrolling async, we set a displayport on it
+ * to make sure it is layerized. However this takes up memory, so once the
+ * scrolling stops we want to remove the displayport. This pref controls how
+ * long after scrolling stops the displayport is removed. A value of 0 will
+ * disable the expiry behavior entirely.
+ * Units: milliseconds
+ *
* \li\b apz.enlarge_displayport_when_clipped
* Pref that enables enlarging of the displayport along one axis when the
* generated displayport's size is beyond that of the scrollable rect on the
@@ -2887,6 +2895,7 @@ AsyncPanZoomController::RequestContentRepaint(const FrameMetrics& aFrameMetrics,
aFrameMetrics.GetScrollOffset().x) < EPSILON &&
fabsf(mLastPaintRequestMetrics.GetScrollOffset().y -
aFrameMetrics.GetScrollOffset().y) < EPSILON &&
+ aFrameMetrics.GetPresShellResolution() == mLastPaintRequestMetrics.GetPresShellResolution() &&
aFrameMetrics.GetZoom() == mLastPaintRequestMetrics.GetZoom() &&
fabsf(aFrameMetrics.GetViewport().width -
mLastPaintRequestMetrics.GetViewport().width) < EPSILON &&
@@ -3315,6 +3324,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
/ mFrameMetrics.GetCumulativeResolution();
float presShellResolutionChange = aLayerMetrics.GetPresShellResolution()
/ mFrameMetrics.GetPresShellResolution();
+ if (presShellResolutionChange != 1.0f) {
+ needContentRepaint = true;
+ }
mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange);
} else {
// Take the new zoom as either device scale or composition width or
diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp
index 8b9a0cd1110..7e2e54df639 100644
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -30,6 +30,13 @@
namespace mozilla {
namespace layers {
+// When we compute the velocity we do so by taking two input events and
+// dividing the distance delta over the time delta. In some cases the time
+// delta can be really small, which can make the velocity computation very
+// volatile. To avoid this we impose a minimum time delta below which we do
+// not recompute the velocity.
+const uint32_t MIN_VELOCITY_SAMPLE_TIME_MS = 5;
+
bool FuzzyEqualsCoordinate(float aValue1, float aValue2)
{
return FuzzyEqualsAdditive(aValue1, aValue2, COORDINATE_EPSILON)
@@ -40,7 +47,8 @@ extern StaticAutoPtr gVelocityCurveFunction;
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
: mPos(0),
- mPosTimeMs(0),
+ mVelocitySampleTimeMs(0),
+ mVelocitySamplePos(0),
mVelocity(0.0f),
mAxisLocked(false),
mAsyncPanZoomController(aAsyncPanZoomController),
@@ -67,16 +75,20 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
// mVelocityQueue is controller-thread only
APZThreadUtils::AssertOnControllerThread();
- if (aTimestampMs == mPosTimeMs) {
- // This could be a duplicate event, or it could be a legitimate event
- // on some platforms that generate events really fast. As a compromise
- // update mPos so we don't run into problems like bug 1042734, even though
- // that means the velocity will be stale. Better than doing a divide-by-zero.
+ if (aTimestampMs <= mVelocitySampleTimeMs + MIN_VELOCITY_SAMPLE_TIME_MS) {
+ // See also the comment on MIN_VELOCITY_SAMPLE_TIME_MS.
+ // We still update mPos so that the positioning is correct (and we don't run
+ // into problems like bug 1042734) but the velocity will remain where it was.
+ // In particular we don't update either mVelocitySampleTimeMs or
+ // mVelocitySamplePos so that eventually when we do get an event with the
+ // required time delta we use the corresponding distance delta as well.
+ AXIS_LOG("%p|%s skipping velocity computation for small time delta %dms\n",
+ mAsyncPanZoomController, Name(), (aTimestampMs - mVelocitySampleTimeMs));
mPos = aPos;
return;
}
- float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
+ float newVelocity = mAxisLocked ? 0.0f : (float)(mVelocitySamplePos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mVelocitySampleTimeMs);
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
bool velocityIsNegative = (newVelocity < 0);
newVelocity = fabs(newVelocity);
@@ -107,7 +119,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
mAsyncPanZoomController, Name(), newVelocity);
mVelocity = newVelocity;
mPos = aPos;
- mPosTimeMs = aTimestampMs;
+ mVelocitySampleTimeMs = aTimestampMs;
+ mVelocitySamplePos = aPos;
// Limit queue size pased on pref
mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, mVelocity));
@@ -119,7 +132,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
mStartPos = aPos;
mPos = aPos;
- mPosTimeMs = aTimestampMs;
+ mVelocitySampleTimeMs = aTimestampMs;
+ mVelocitySamplePos = aPos;
mAxisLocked = false;
}
diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h
index 1da9dcf3e42..3771d45c210 100644
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -251,7 +251,14 @@ public:
protected:
ParentLayerCoord mPos;
- uint32_t mPosTimeMs;
+
+ // mVelocitySampleTimeMs and mVelocitySamplePos are the time and position
+ // used in the last velocity sampling. They get updated when a new sample is
+ // taken (which may not happen on every input event, if the time delta is too
+ // small).
+ uint32_t mVelocitySampleTimeMs;
+ ParentLayerCoord mVelocitySamplePos;
+
ParentLayerCoord mStartPos;
float mVelocity; // Units: ParentLayerCoords per millisecond
bool mAxisLocked; // Whether movement on this axis is locked.
diff --git a/gfx/layers/apz/test/mochitest/helper_subframe_style.css b/gfx/layers/apz/test/mochitest/helper_subframe_style.css
index a911bea7115..5af9640802f 100644
--- a/gfx/layers/apz/test/mochitest/helper_subframe_style.css
+++ b/gfx/layers/apz/test/mochitest/helper_subframe_style.css
@@ -3,7 +3,7 @@ body {
}
.inner-frame {
- margin-top: 25%;
+ margin-top: 50px; /* this should be at least 30px */
height: 200%;
width: 75%;
overflow: scroll;
diff --git a/gfx/layers/apz/test/mochitest/test_layerization.html b/gfx/layers/apz/test/mochitest/test_layerization.html
index 99e25edceb9..b25c6054b04 100644
--- a/gfx/layers/apz/test/mochitest/test_layerization.html
+++ b/gfx/layers/apz/test/mochitest/test_layerization.html
@@ -72,6 +72,8 @@ function scrollWheelOver(element) {
var gTestContinuation = null;
var utils;
+const DISPLAYPORT_EXPIRY = 100;
+
// Return whether the element with id |elementId| has been layerized.
// Assumes |elementId| will be present in the content description for the
// element, and not in the content descriptions of other elements.
@@ -91,6 +93,14 @@ function isLayerized(elementId) {
return false;
}
+// Helper function to pass to waitForAllPaints rather than passing driveTest
+// directly. If there are no paints pending waitForAllPaints will invoke the
+// callback synchronously, and if we did waitForAllPaints(driveTest) that might
+// cause reentrancy into driveTest which is bad.
+function callDriveTestAsync() {
+ setTimeout(driveTest, 0);
+}
+
function* runTest() {
utils = SpecialPowers.getDOMWindowUtils(window);
@@ -126,6 +136,72 @@ function* runTest() {
yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4'));
ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized");
ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized");
+
+ // Now we enable displayport expiry, and verify that things are still
+ // layerized as they were before.
+ yield SpecialPowers.pushPrefEnv({"set": [["apz.displayport_expiry_ms", DISPLAYPORT_EXPIRY]]}, driveTest);
+ ok(isLayerized('outer1'), "outer1 is still layerized after enabling expiry");
+ ok(!isLayerized('inner1'), "inner1 is still not layerized after enabling expiry");
+ ok(isLayerized('outer2'), "outer2 is still layerized after enabling expiry");
+ ok(isLayerized('inner2'), "inner2 is still layerized after enabling expiry");
+ ok(isLayerized('outer3'), "outer3 is still layerized after enabling expiry");
+ ok(!isLayerized('inner3'), "inner3 is still not layerized after enabling expiry");
+ ok(isLayerized('outer4'), "outer4 is still layerized after enabling expiry");
+ ok(isLayerized('inner4'), "inner4 is still layerized after enabling expiry");
+
+ // Now we trigger a scroll on some of the things still layerized, so that
+ // the displayport expiry gets triggered.
+
+ // Expire displayport with scrolling on outer1
+ yield scrollWheelOver(document.getElementById('outer1'));
+ yield waitForAllPaints(function() {
+ flushApzRepaints(driveTest);
+ });
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(!isLayerized('outer1'), "outer1 is no longer layerized after displayport expiry");
+ ok(!isLayerized('inner1'), "inner1 is still not layerized after displayport expiry");
+
+ // Expire displayport with scrolling on inner2
+ yield scrollWheelOver(document.getElementById('inner2'));
+ yield waitForAllPaints(function() {
+ flushApzRepaints(driveTest);
+ });
+ // Once the expiry elapses, it will trigger expiry on outer2, so we check
+ // both, one at a time.
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(!isLayerized('inner2'), "inner2 is no longer layerized after displayport expiry");
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(!isLayerized('outer2'), "outer2 got de-layerized with inner2");
+
+ // Scroll on inner3. inner3 isn't layerized, and this will cause it to
+ // get layerized, but it will also trigger displayport expiration for inner3
+ // which will eventually trigger displayport expiration on outer3.
+ yield scrollWheelOver(document.getElementById('outer3').contentDocument.getElementById('inner3'));
+ yield waitForAllPaints(function() {
+ flushApzRepaints(driveTest);
+ });
+ ok(isLayerized('inner3'), "inner3 becomes layerized after scroll");
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(!isLayerized('inner3'), "inner3 becomes unlayerized after expiry");
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(!isLayerized('outer3'), "outer3 is no longer layerized after inner3 triggered expiry");
+
+ // Scroll outer4 and wait for the expiry. It should NOT get expired because
+ // inner4 is still layerized
+ yield scrollWheelOver(document.getElementById('outer4').contentDocument.documentElement);
+ yield waitForAllPaints(function() {
+ flushApzRepaints(driveTest);
+ });
+ // Wait for the expiry to elapse
+ yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
+ yield waitForAllPaints(callDriveTestAsync);
+ ok(isLayerized('inner4'), "inner4 is still layerized because it never expired");
+ ok(isLayerized('outer4'), "outer4 is still layerized because inner4 is still layerized");
}
function driveTest() {
@@ -153,7 +229,8 @@ function startTest() {
}
SimpleTest.waitForExplicitFinish();
-SimpleTest.testInChaosMode();
+SimpleTest.requestFlakyTimeout("we are testing code that measures an actual timeout");
+SimpleTest.expectAssertions(0, 8); // we get a bunch of "ASSERTION: Bounds computation mismatch" sometimes (bug 1232856)
// Disable smooth scrolling, because it results in long-running scroll
// animations that can result in a 'scroll' event triggered by an earlier
@@ -161,6 +238,7 @@ SimpleTest.testInChaosMode();
// Also enable APZ test logging, since we use that data to determine whether
// a scroll frame was layerized.
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false],
+ ["apz.displayport_expiry_ms", 0],
["apz.test.logging_enabled", true]]},
function() {
SimpleTest.waitForFocus(startTest, window);
diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp
index d7fda20665b..1d4446d1ba5 100644
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -178,11 +178,12 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
#endif
RefPtr texture = image->GetTextureClient(this);
+ const bool hasTextureClient = !!texture;
for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
if (mBuffers[i].mImageSerial == image->GetSerial()) {
- if (texture) {
- MOZ_ASSERT(texture == mBuffers[i].mTextureClient);
+ if (hasTextureClient) {
+ MOZ_ASSERT(image->GetTextureClient(this) == mBuffers[i].mTextureClient);
} else {
texture = mBuffers[i].mTextureClient;
}
diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp
index 25f103d1a6f..03be61b016e 100644
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -339,12 +339,14 @@ DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
NS_WARNING("No D3D device to update the texture.");
return false;
}
- mSize = aSurface->GetSize();
- uint32_t bpp = 0;
+ uint32_t bpp = BytesPerPixel(aSurface->GetFormat());
+ DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
+
+ mSize = aSurface->GetSize();
+ mFormat = aSurface->GetFormat();
_D3DFORMAT format = D3DFMT_A8R8G8B8;
- mFormat = aSurface->GetFormat();
switch (mFormat) {
case SurfaceFormat::B8G8R8X8:
format = D3DFMT_X8R8G8B8;
@@ -364,18 +366,100 @@ DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
}
int32_t maxSize = mCompositor->GetMaxTextureSize();
- DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
- (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
- mTexture = DataToTexture(deviceManager,
- aSurface->GetData(), aSurface->Stride(),
- IntSize(mSize), format, bpp);
+ (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
+ mIsTiled = false;
+
+ if (mTexture) {
+ D3DSURFACE_DESC currentDesc;
+ mTexture->GetLevelDesc(0, ¤tDesc);
+
+ // Make sure there's no size mismatch, if there is, recreate.
+ if (currentDesc.Width != mSize.width || currentDesc.Height != mSize.height ||
+ currentDesc.Format != format) {
+ mTexture = nullptr;
+ // Make sure we upload the whole surface.
+ aDestRegion = nullptr;
+ }
+ }
+
if (!mTexture) {
- NS_WARNING("Could not upload texture");
+ // TODO Improve: Reallocating this texture is costly enough
+ // that it causes us to skip frames on scrolling
+ // important pages like Facebook.
+ mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_DEFAULT, this);
+ mIsTiled = false;
+ if (!mTexture) {
+ Reset();
+ return false;
+ }
+
+ if (mFlags & TextureFlags::COMPONENT_ALPHA) {
+ aDestRegion = nullptr;
+ }
+ }
+
+ DataSourceSurface::MappedSurface map;
+ if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+ gfxCriticalError() << "Failed to map surface.";
Reset();
return false;
}
- mIsTiled = false;
+
+ nsIntRegion regionToUpdate = aDestRegion ? *aDestRegion : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height));
+
+ RefPtr srcTexture;
+ RefPtr srcSurface;
+
+ if (mFormat == SurfaceFormat::A8) {
+ // A8 doesn't appear to work with CreateOffscreenPlainSurface
+ srcTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, this);
+ if (!srcTexture) {
+ aSurface->Unmap();
+ return false;
+ }
+ srcTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+ } else {
+ HRESULT hr = mCompositor->device()->CreateOffscreenPlainSurface(mSize.width, mSize.height, format, D3DPOOL_SYSTEMMEM, getter_AddRefs(srcSurface), nullptr);
+ if (FAILED(hr)) {
+ aSurface->Unmap();
+ return false;
+ }
+ }
+
+ RefPtr destSurface;
+ mTexture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
+
+ D3DLOCKED_RECT rect;
+ srcSurface->LockRect(&rect, nullptr, 0);
+
+ for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
+ const nsIntRect& iterRect = iter.Get();
+ uint8_t* src = map.mData + map.mStride * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
+ uint8_t* dest = reinterpret_cast(rect.pBits) + rect.Pitch * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
+
+ for (int y = 0; y < iterRect.height; y++) {
+ memcpy(dest + rect.Pitch * y,
+ src + map.mStride * y,
+ iterRect.width * bpp);
+ }
+ }
+
+ srcSurface->UnlockRect();
+ aSurface->Unmap();
+
+ for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
+ const nsIntRect& iterRect = iter.Get();
+
+ RECT updateRect;
+ updateRect.left = iterRect.x;
+ updateRect.top = iterRect.y;
+ updateRect.right = iterRect.XMost();
+ updateRect.bottom = iterRect.YMost();
+ POINT point = { updateRect.left, updateRect.top };
+
+ mCompositor->device()->UpdateSurface(srcSurface, &updateRect, destSurface, &point);
+ }
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
diff --git a/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp b/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp
index 6e014feded1..ad4f33f7d9e 100644
--- a/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp
+++ b/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp
@@ -51,7 +51,8 @@ bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
///////////////////////////////////////////////////////////////////////////////
static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorType dstCT,
- SkColorProfileType dstPT, const SkIRect* subset) {
+ SkAlphaType dstAT, SkColorProfileType dstPT,
+ const SkIRect* subset) {
if (nullptr == texture || kUnknown_SkColorType == dstCT) {
return nullptr;
}
@@ -75,7 +76,7 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp
srcRect = *subset;
}
desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT);
+ desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, dstAT, dstPT);
GrTexture* dst = context->textureProvider()->createTexture(desc, false, nullptr, 0);
if (nullptr == dst) {
@@ -88,8 +89,7 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp
context->copySurface(dst->asRenderTarget(), texture, srcRect, SkIPoint::Make(0,0),
GrContext::kFlushWrites_PixelOp);
- SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType,
- dstPT);
+ SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, dstAT, dstPT);
SkGrPixelRef* pixelRef = new SkGrPixelRef(info, dst);
SkSafeUnref(dst);
return pixelRef;
@@ -142,7 +142,8 @@ SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, SkColorProfileType dstPT,
// a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
// independently of that texture. Texture-backed pixel refs, on the other
// hand, own their GrTextures, and are thus self-contained.
- return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, dstPT, subset);
+ return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, this->info().alphaType(),
+ dstPT, subset);
}
static bool tryAllocBitmapPixels(SkBitmap* bitmap) {
diff --git a/gfx/src/nsFont.cpp b/gfx/src/nsFont.cpp
index 99693ccb186..777a320228d 100644
--- a/gfx/src/nsFont.cpp
+++ b/gfx/src/nsFont.cpp
@@ -52,29 +52,7 @@ nsFont::Init()
variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
}
-nsFont::nsFont(const nsFont& aOther)
- : fontlist(aOther.fontlist)
-{
- style = aOther.style;
- systemFont = aOther.systemFont;
- weight = aOther.weight;
- stretch = aOther.stretch;
- smoothing = aOther.smoothing;
- size = aOther.size;
- sizeAdjust = aOther.sizeAdjust;
- kerning = aOther.kerning;
- synthesis = aOther.synthesis;
- fontFeatureSettings = aOther.fontFeatureSettings;
- languageOverride = aOther.languageOverride;
- variantAlternates = aOther.variantAlternates;
- variantCaps = aOther.variantCaps;
- variantEastAsian = aOther.variantEastAsian;
- variantLigatures = aOther.variantLigatures;
- variantNumeric = aOther.variantNumeric;
- variantPosition = aOther.variantPosition;
- alternateValues = aOther.alternateValues;
- featureValueLookup = aOther.featureValueLookup;
-}
+nsFont::nsFont(const nsFont& aOther) = default;
nsFont::nsFont()
{
@@ -111,30 +89,7 @@ bool nsFont::Equals(const nsFont& aOther) const
return false;
}
-nsFont& nsFont::operator=(const nsFont& aOther)
-{
- fontlist = aOther.fontlist;
- style = aOther.style;
- systemFont = aOther.systemFont;
- weight = aOther.weight;
- stretch = aOther.stretch;
- smoothing = aOther.smoothing;
- size = aOther.size;
- sizeAdjust = aOther.sizeAdjust;
- kerning = aOther.kerning;
- synthesis = aOther.synthesis;
- fontFeatureSettings = aOther.fontFeatureSettings;
- languageOverride = aOther.languageOverride;
- variantAlternates = aOther.variantAlternates;
- variantCaps = aOther.variantCaps;
- variantEastAsian = aOther.variantEastAsian;
- variantLigatures = aOther.variantLigatures;
- variantNumeric = aOther.variantNumeric;
- variantPosition = aOther.variantPosition;
- alternateValues = aOther.alternateValues;
- featureValueLookup = aOther.featureValueLookup;
- return *this;
-}
+nsFont& nsFont::operator=(const nsFont& aOther) = default;
void
nsFont::CopyAlternates(const nsFont& aOther)
diff --git a/gfx/src/nsRegion.cpp b/gfx/src/nsRegion.cpp
index a46944e6807..4c4d4ae8560 100644
--- a/gfx/src/nsRegion.cpp
+++ b/gfx/src/nsRegion.cpp
@@ -950,11 +950,6 @@ namespace {
result.mSize = result.mSizeContainingRect = kVeryLargeNegativeNumber;
return result;
}
- SizePair& operator=(const SizePair& aOther) {
- mSizeContainingRect = aOther.mSizeContainingRect;
- mSize = aOther.mSize;
- return *this;
- }
bool operator<(const SizePair& aOther) const {
if (mSizeContainingRect < aOther.mSizeContainingRect)
return true;
diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h
index ad2f85f8fa8..95af19c2485 100644
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -148,6 +148,7 @@ private:
DECL_GFX_PREF(Live, "apz.content_response_timeout", APZContentResponseTimeout, int32_t, 300);
DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50);
DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100);
+ DECL_GFX_PREF(Live, "apz.displayport_expiry_ms", APZDisplayPortExpiryTime, uint32_t, 15000);
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false);
DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f);
diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp
index 302ffa8913c..a1acf253188 100644
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -178,8 +178,15 @@ public:
: mUserFontEntry(aUserFontEntry) {}
virtual ots::TableAction GetTableAction(uint32_t aTag) override {
- // preserve Graphite, color glyph and SVG tables
- if (aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
+ // Preserve Graphite, color glyph and SVG tables
+ if (
+#ifdef RELEASE_BUILD // For Beta/Release, also allow OT Layout tables through
+ // unchecked, and rely on harfbuzz to handle them safely.
+ aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
+ aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
+ aTag == TRUETYPE_TAG('G', 'S', 'U', 'B') ||
+#endif
+ aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') ||
aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') ||
aTag == TRUETYPE_TAG('G', 'l', 'a', 't') ||
diff --git a/js/src/asmjs/AsmJS.cpp b/js/src/asmjs/AsmJS.cpp
index 02964e962e6..9c27c0ba6ee 100644
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -2584,12 +2584,15 @@ SimdToExpr(SimdType type, SimdOperation op)
switch (type) {
case SimdType::Int32x4: {
ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32CASE)
+ break;
}
case SimdType::Float32x4: {
ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32CASE)
+ break;
}
case SimdType::Bool32x4: {
ENUMERATE(B32x4, FORALL_BOOL_SIMD_OP, B32CASE)
+ break;
}
default: break;
}
diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp
index d9ed9f6d875..b84a9aee4b0 100644
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -288,7 +288,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
introducerFilename = maybeScript->scriptSource()->introducerFilename();
- RootedObject enclosing(cx);
+ Rooted enclosing(cx);
if (evalType == DIRECT_EVAL)
enclosing = callerScript->innermostStaticScope(pc);
else
@@ -374,7 +374,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
introducerFilename = maybeScript->scriptSource()->introducerFilename();
- RootedObject enclosing(cx, callerScript->innermostStaticScope(pc));
+ Rooted enclosing(cx, callerScript->innermostStaticScope(pc));
Rooted staticScope(cx, StaticEvalScope::create(cx, enclosing));
if (!staticScope)
return false;
@@ -476,7 +476,8 @@ js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScri
// Unlike the non-syntactic scope chain API used by the subscript loader,
// this API creates a fresh block scope each time.
- RootedObject enclosingStaticScope(cx, script->enclosingStaticScope());
+ Rooted enclosingStaticScope(cx,
+ &script->enclosingStaticScope()->as());
scope = ClonedBlockObject::createNonSyntactic(cx, enclosingStaticScope, scope);
if (!scope)
return false;
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index f0decbf4f6a..13d6c9f7d07 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -573,7 +573,7 @@ ModuleObject::isInstance(HandleValue value)
}
/* static */ ModuleObject*
-ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope)
+ModuleObject::create(ExclusiveContext* cx, Handle enclosingStaticScope)
{
RootedObject proto(cx, cx->global()->getModulePrototype());
RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
@@ -581,7 +581,11 @@ ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope)
return nullptr;
RootedModuleObject self(cx, &obj->as());
- self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(enclosingStaticScope));
+ Rooted scope(cx, StaticModuleScope::create(cx, self,
+ enclosingStaticScope));
+ if (!scope)
+ return nullptr;
+ self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(scope));
Zone* zone = cx->zone();
IndirectBindingMap* bindings = zone->new_(zone);
@@ -729,10 +733,10 @@ ModuleObject::initialEnvironment() const
return getReservedSlot(InitialEnvironmentSlot).toObject().as();
}
-JSObject*
-ModuleObject::enclosingStaticScope() const
+StaticModuleScope*
+ModuleObject::staticScope() const
{
- return getReservedSlot(StaticScopeSlot).toObjectOrNull();
+ return &getReservedSlot(StaticScopeSlot).toObject().as();
}
/* static */ void
diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
index 1bf80aa9bad..80c3088cb4d 100644
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -21,6 +21,8 @@ namespace js {
class ModuleEnvironmentObject;
class ModuleObject;
+class StaticScope;
+class StaticModuleScope;
namespace frontend {
class ParseNode;
@@ -225,7 +227,7 @@ class ModuleObject : public NativeObject
static bool isInstance(HandleValue value);
- static ModuleObject* create(ExclusiveContext* cx, HandleObject enclosingStaticScope);
+ static ModuleObject* create(ExclusiveContext* cx, Handle enclosingStaticScope);
void init(HandleScript script);
void setInitialEnvironment(Handle initialEnvironment);
void initImportExportData(HandleArrayObject requestedModules,
@@ -235,7 +237,7 @@ class ModuleObject : public NativeObject
HandleArrayObject starExportEntries);
JSScript* script() const;
- JSObject* enclosingStaticScope() const;
+ StaticModuleScope* staticScope() const;
ModuleEnvironmentObject& initialEnvironment() const;
ModuleEnvironmentObject* environment() const;
ModuleNamespaceObject* namespace_();
diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp
index 9ba70fd5865..9413dba3cc6 100644
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -213,6 +213,8 @@ static const JSFunctionSpec SimdTypedObjectMethods[] = {
namespace js {
namespace jit {
+static_assert(uint64_t(SimdOperation::Last) <= UINT16_MAX, "SimdOperation must fit in uint16_t");
+
// See also JitInfo_* in MCallOptimize.cpp. We provide a JSJitInfo for all the
// named functions here. The default JitInfo_SimdInt32x4 etc structs represent the
// SimdOperation::Constructor.
diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h
index 6ea4d065215..85ce1bf84db 100644
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -878,7 +878,11 @@ GetBooleanSimdType(SimdType t)
//
// C++ defines keywords and/or/xor/not, so prepend Fn_ to all named functions to
// avoid clashes.
-enum class SimdOperation : uint8_t {
+//
+// Note: because of a gcc < v4.8's compiler bug, uint8_t can't be used as the
+// storage class here. See bug 1243810. See also
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64037 .
+enum class SimdOperation {
// The constructor call. No Fn_ prefix here.
Constructor,
@@ -901,6 +905,8 @@ enum class SimdOperation : uint8_t {
Fn_fromUint32x4Bits,
Fn_fromFloat32x4Bits,
Fn_fromFloat64x2Bits,
+
+ Last = Fn_fromFloat64x2Bits
};
class SimdObject : public JSObject
diff --git a/js/src/configure.in b/js/src/configure.in
index 8bb39f0276e..863748fffd4 100644
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3623,9 +3623,6 @@ AC_SUBST(MOZ_PKG_SPECIAL)
AC_SUBST(MOZILLA_OFFICIAL)
-dnl win32 options
-AC_SUBST(MOZ_BROWSE_INFO)
-
dnl Echo the CFLAGS to remove extra whitespace.
CFLAGS=`echo \
$_WARNINGS_CFLAGS \
diff --git a/js/src/doc/Debugger/Debugger.md b/js/src/doc/Debugger/Debugger.md
index 8048fcd8fd7..df275002fcd 100644
--- a/js/src/doc/Debugger/Debugger.md
+++ b/js/src/doc/Debugger/Debugger.md
@@ -536,3 +536,13 @@ other kinds of objects.
`TypeError`. Determine which global is designated by global
using the same rules as [`Debugger.prototype.addDebuggee`][add].
+## Static methods of the Debugger Object
+
+The functions described below are not called with a `this` value.
+
+isCompilableUnit(source)
+: Given a string of source code, designated by source, return false if
+ the string might become a valid JavaScript statement with the addition of
+ more lines. Otherwise return true. The intent is to support interactive
+ compilation - accumulate lines in a buffer until isCompilableUnit is true,
+ then pass it to the compiler.
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index 3ea9abe339f..2c7d10c6795 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -72,7 +72,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
bool canLazilyParse();
bool createParser();
bool createSourceAndParser();
- bool createScript(HandleObject staticScope, bool savedCallerFun = false);
+ bool createScript(Handle staticScope, bool savedCallerFun = false);
bool createEmitter(SharedContext* sharedContext, HandleScript evalCaller = nullptr,
bool insideNonGlobalEval = false);
bool isEvalCompilationUnit();
@@ -255,7 +255,7 @@ BytecodeCompiler::createSourceAndParser()
}
bool
-BytecodeCompiler::createScript(HandleObject staticScope, bool savedCallerFun)
+BytecodeCompiler::createScript(Handle staticScope, bool savedCallerFun)
{
script = JSScript::Create(cx, staticScope, savedCallerFun, options,
sourceObject, /* sourceStart = */ 0, sourceBuffer.length());
@@ -284,11 +284,8 @@ BytecodeCompiler::isEvalCompilationUnit()
bool
BytecodeCompiler::isNonGlobalEvalCompilationUnit()
{
- if (!isEvalCompilationUnit())
- return false;
- StaticEvalScope& eval = enclosingStaticScope->as();
- JSObject* enclosing = eval.enclosingScopeForStaticScopeIter();
- return !IsStaticGlobalLexicalScope(enclosing);
+ return isEvalCompilationUnit() &&
+ !IsStaticGlobalLexicalScope(enclosingStaticScope->enclosingScope());
}
bool
@@ -562,7 +559,8 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
return script;
}
-ModuleObject* BytecodeCompiler::compileModule()
+ModuleObject*
+BytecodeCompiler::compileModule()
{
if (!createSourceAndParser())
return nullptr;
@@ -571,7 +569,8 @@ ModuleObject* BytecodeCompiler::compileModule()
if (!module)
return nullptr;
- if (!createScript(module))
+ Rooted moduleScope(cx, module->staticScope());
+ if (!createScript(moduleScope))
return nullptr;
module->init(script);
@@ -651,7 +650,8 @@ BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun,
if (fn->pn_funbox->function()->isInterpreted()) {
MOZ_ASSERT(fun == fn->pn_funbox->function());
- if (!createScript(enclosingStaticScope))
+ Rooted scope(cx, fn->pn_funbox->staticScope());
+ if (!createScript(scope))
return false;
script->bindings = fn->pn_funbox->bindings;
@@ -803,11 +803,12 @@ frontend::CompileLazyFunction(JSContext* cx, Handle lazy, const cha
if (!NameFunctions(cx, pn))
return false;
- RootedObject enclosingScope(cx, lazy->enclosingScope());
+ Rooted staticScope(cx, pn->pn_funbox->staticScope());
+ MOZ_ASSERT(staticScope);
RootedScriptSource sourceObject(cx, lazy->sourceObject());
MOZ_ASSERT(sourceObject);
- Rooted script(cx, JSScript::Create(cx, enclosingScope, false, options,
+ Rooted script(cx, JSScript::Create(cx, staticScope, false, options,
sourceObject, lazy->begin(), lazy->end()));
if (!script)
return false;
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 30660c59ce6..d6f472e43cc 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -733,7 +733,7 @@ BytecodeEmitter::pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t
}
}
-JSObject*
+StaticScope*
BytecodeEmitter::innermostStaticScope() const
{
if (StmtInfoBCE* stmt = innermostScopeStmt())
@@ -1362,9 +1362,7 @@ BytecodeEmitter::atBodyLevel(StmtInfoBCE* stmt) const
if (sc->staticScope()->is()) {
bool bl = !stmt->enclosing;
MOZ_ASSERT_IF(bl, stmt->type == StmtType::BLOCK);
- MOZ_ASSERT_IF(bl, stmt->staticScope
- ->as()
- .enclosingStaticScope() == sc->staticScope());
+ MOZ_ASSERT_IF(bl, stmt->staticScope->enclosingScope() == sc->staticScope());
return bl;
}
return !stmt;
@@ -1467,8 +1465,8 @@ BytecodeEmitter::computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definitio
// object. Aliased block bindings do not need adjusting; see
// computeAliasedSlots.
uint32_t slot = dn->pn_scopecoord.slot();
- if (blockScopeOfDef(dn)->is() ||
- blockScopeOfDef(dn)->is())
+ if (blockScopeOfDef(dn)->is() ||
+ blockScopeOfDef(dn)->is())
{
MOZ_ASSERT(IsArgOp(*op) || slot < bceOfDef->script->bindings.numBodyLevelLocals());
MOZ_ALWAYS_TRUE(bceOfDef->lookupAliasedName(bceOfDef->script, dn->name(), &slot));
@@ -1569,8 +1567,11 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
// Look up for name in function and block scopes.
if (ssi.type() == StaticScopeIter::Function) {
RootedScript funScript(cx, ssi.funScript());
- if (funScript->funHasExtensibleScope() || ssi.fun().atom() == pn->pn_atom)
+ if (funScript->funHasExtensibleScope() ||
+ ssi.fun().function().atom() == pn->pn_atom)
+ {
return false;
+ }
// Skip the current function, since we're trying to convert a
// free name.
@@ -1582,7 +1583,7 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
}
}
} else if (ssi.type() == StaticScopeIter::Module) {
- RootedScript moduleScript(cx, ssi.moduleScript());
+ RootedScript moduleScript(cx, ssi.module().script());
uint32_t slot_;
if (lookupAliasedName(moduleScript, name, &slot_, pn)) {
slot = Some(slot_);
@@ -1590,7 +1591,8 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
}
// Convert module import accesses to use JSOP_GETIMPORT.
- RootedModuleEnvironmentObject env(cx, &ssi.module().initialEnvironment());
+ RootedModuleEnvironmentObject env(cx, &ssi.module().moduleObject()
+ .initialEnvironment());
RootedPropertyName propName(cx, name);
MOZ_ASSERT(env);
if (env->hasImportBinding(propName)) {
@@ -1833,12 +1835,11 @@ BytecodeEmitter::bindNameToSlotHelper(ParseNode* pn)
* Currently, the ALIASEDVAR ops do not support accessing the
* callee of a DeclEnvObject, so use NAME.
*/
- JSFunction* fun = sc->asFunctionBox()->function();
- if (blockScopeOfDef(dn) != fun)
+ if (blockScopeOfDef(dn) != sc->asFunctionBox()->staticScope())
return true;
- MOZ_ASSERT(fun->isLambda());
- MOZ_ASSERT(pn->pn_atom == fun->atom());
+ MOZ_ASSERT(sc->asFunctionBox()->function()->isLambda());
+ MOZ_ASSERT(pn->pn_atom == sc->asFunctionBox()->function()->atom());
/*
* Leave pn->isOp(JSOP_GETNAME) if this->fun needs a CallObject to
@@ -3538,9 +3539,9 @@ BytecodeEmitter::emitSetThis(ParseNode* pn)
}
static bool
-IsModuleOnScopeChain(JSObject* obj)
+IsModuleOnScopeChain(StaticScope* scope)
{
- for (StaticScopeIter ssi(obj); !ssi.done(); ssi++) {
+ for (StaticScopeIter ssi(scope); !ssi.done(); ssi++) {
if (ssi.type() == StaticScopeIter::Module)
return true;
}
@@ -6390,14 +6391,21 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
SharedContext* outersc = sc;
if (fun->isInterpretedLazy()) {
if (!fun->lazyScript()->sourceObject()) {
- JSObject* scope = innermostStaticScope();
+ // Two cases that can arise during parsing can cause the static
+ // scope chain to be incorrectly linked up: (1) the
+ // transformation of blocks from non-scopeful to scopeful when
+ // the first block-scoped declaration is found; (2) legacy
+ // comprehension expression transplantation. The
+ // setEnclosingScope call below fixes these cases.
+ Rooted enclosingScope(cx, innermostStaticScope());
+ fun->lazyScript()->staticScope()->setEnclosingScope(enclosingScope);
+
JSObject* source = script->sourceObject();
- fun->lazyScript()->setParent(scope, &source->as());
+ fun->lazyScript()->initSource(&source->as());
}
if (emittingRunOnceLambda)
fun->lazyScript()->setTreatAsRunOnce();
} else {
-
if (outersc->isFunctionBox() && outersc->asFunctionBox()->mightAliasLocals())
funbox->setMightAliasLocals(); // inherit mightAliasLocals from parent
MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
@@ -6410,9 +6418,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
const TransitiveCompileOptions& transitiveOptions = parser->options();
CompileOptions options(cx, transitiveOptions);
- Rooted enclosingScope(cx, innermostStaticScope());
+ // See comment above regarding funScope->setEnclosingScope().
+ Rooted funScope(cx, funbox->staticScope());
+ Rooted enclosingScope(cx, innermostStaticScope());
+ funScope->setEnclosingScope(enclosingScope);
+
Rooted sourceObject(cx, script->sourceObject());
- Rooted script(cx, JSScript::Create(cx, enclosingScope, false, options,
+ Rooted script(cx, JSScript::Create(cx, funScope, false, options,
sourceObject,
funbox->bufStart, funbox->bufEnd));
if (!script)
@@ -6426,8 +6438,6 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
insideNonGlobalEval, lineNum, emitterMode);
if (!bce2.init())
return false;
-
- /* We measured the max scope depth when we parsed the function. */
if (!bce2.emitFunctionScript(pn->pn_body))
return false;
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index b7cacb6249d..0d4348a21e1 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -249,9 +249,9 @@ struct BytecodeEmitter
StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); }
StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
- JSObject* innermostStaticScope() const;
- JSObject* blockScopeOfDef(Definition* dn) const {
- return parser->blockScopes[dn->pn_blockid];
+ StaticScope* innermostStaticScope() const;
+ StaticScope* blockScopeOfDef(Definition* dn) const {
+ return &parser->blockScopes[dn->pn_blockid].get()->as();
}
bool atBodyLevel(StmtInfoBCE* stmt) const;
diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp
index 30b35bd7eb7..e97278253bb 100644
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -1193,8 +1193,8 @@ FunctionBox::trace(JSTracer* trc)
{
ObjectBox::trace(trc);
bindings.trace(trc);
- if (enclosingStaticScope_)
- TraceRoot(trc, &enclosingStaticScope_, "funbox-enclosingStaticScope");
+ if (staticScope_)
+ TraceRoot(trc, &staticScope_, "funbox-staticScope");
}
void
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 984b8cf720b..93d1dccf781 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -57,9 +57,9 @@ JSFunction::AutoParseUsingFunctionBox::AutoParseUsingFunctionBox(ExclusiveContex
{
fun_->unsetEnvironment();
fun_->setFunctionBox(funbox);
- funbox->computeAllowSyntax(fun_);
- funbox->computeInWith(fun_);
- funbox->computeThisBinding(fun_);
+ funbox->computeAllowSyntax(funbox->staticScope_);
+ funbox->computeInWith(funbox->staticScope_);
+ funbox->computeThisBinding(funbox->staticScope_);
}
JSFunction::AutoParseUsingFunctionBox::~AutoParseUsingFunctionBox()
@@ -119,18 +119,18 @@ MarkUsesAsHoistedLexical(ParseNode* pn)
}
void
-SharedContext::computeAllowSyntax(JSObject* staticScope)
+SharedContext::computeAllowSyntax(StaticScope* staticScope)
{
for (StaticScopeIter it(context, staticScope); !it.done(); it++) {
- if (it.type() == StaticScopeIter::Function && !it.fun().isArrow()) {
+ if (it.type() == StaticScopeIter::Function && !it.fun().function().isArrow()) {
// Any function supports new.target.
allowNewTarget_ = true;
- allowSuperProperty_ = it.fun().allowSuperProperty();
+ allowSuperProperty_ = it.fun().function().allowSuperProperty();
if (it.maybeFunctionBox()) {
superScopeAlreadyNeedsHomeObject_ = it.maybeFunctionBox()->needsHomeObject();
allowSuperCall_ = it.maybeFunctionBox()->isDerivedClassConstructor();
} else {
- allowSuperCall_ = it.fun().isDerivedClassConstructor();
+ allowSuperCall_ = it.fun().function().isDerivedClassConstructor();
}
break;
}
@@ -138,7 +138,7 @@ SharedContext::computeAllowSyntax(JSObject* staticScope)
}
void
-SharedContext::computeThisBinding(JSObject* staticScope)
+SharedContext::computeThisBinding(StaticScope* staticScope)
{
for (StaticScopeIter it(context, staticScope); !it.done(); it++) {
if (it.type() == StaticScopeIter::Module) {
@@ -147,9 +147,10 @@ SharedContext::computeThisBinding(JSObject* staticScope)
}
if (it.type() == StaticScopeIter::Function) {
+ RootedFunction fun(context, &it.fun().function());
// Arrow functions and generator expression lambdas don't have
// their own `this` binding.
- if (it.fun().isArrow())
+ if (fun->isArrow())
continue;
bool isDerived;
if (it.maybeFunctionBox()) {
@@ -157,9 +158,9 @@ SharedContext::computeThisBinding(JSObject* staticScope)
continue;
isDerived = it.maybeFunctionBox()->isDerivedClassConstructor();
} else {
- if (it.fun().nonLazyScript()->isGeneratorExp())
+ if (fun->nonLazyScript()->isGeneratorExp())
continue;
- isDerived = it.fun().isDerivedClassConstructor();
+ isDerived = fun->isDerivedClassConstructor();
}
// Derived class constructors (including nested arrow functions and
@@ -176,7 +177,7 @@ SharedContext::computeThisBinding(JSObject* staticScope)
}
void
-SharedContext::computeInWith(JSObject* staticScope)
+SharedContext::computeInWith(StaticScope* staticScope)
{
for (StaticScopeIter it(context, staticScope); !it.done(); it++) {
if (it.type() == StaticScopeIter::With) {
@@ -195,8 +196,8 @@ SharedContext::markSuperScopeNeedsHomeObject()
return;
for (StaticScopeIter it(context, staticScope()); !it.done(); it++) {
- if (it.type() == StaticScopeIter::Function && !it.fun().isArrow()) {
- MOZ_ASSERT(it.fun().allowSuperProperty());
+ if (it.type() == StaticScopeIter::Function && !it.fun().function().isArrow()) {
+ MOZ_ASSERT(it.fun().function().allowSuperProperty());
// If we are still emitting the outer function that needs a home
// object, mark it as needing one. Otherwise, we must be emitting
// an eval script, and the outer function must already be marked
@@ -204,7 +205,7 @@ SharedContext::markSuperScopeNeedsHomeObject()
if (it.maybeFunctionBox())
it.maybeFunctionBox()->setNeedsHomeObject();
else
- MOZ_ASSERT(it.fun().nonLazyScript()->needsHomeObject());
+ MOZ_ASSERT(it.funScript()->needsHomeObject());
superScopeAlreadyNeedsHomeObject_ = true;
return;
}
@@ -754,12 +755,12 @@ Parser::newObjectBox(JSObject* obj)
template
FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
- JSObject* enclosingStaticScope, ParseContext* outerpc,
+ ParseContext* outerpc,
Directives directives, bool extraWarnings, GeneratorKind generatorKind)
: ObjectBox(fun, traceListHead),
SharedContext(cx, directives, extraWarnings),
bindings(),
- enclosingStaticScope_(enclosingStaticScope),
+ staticScope_(nullptr),
bufStart(0),
bufEnd(0),
startLine(1),
@@ -782,13 +783,21 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
MOZ_ASSERT(fun->isTenured());
}
+bool
+FunctionBox::initStaticScope(Handle enclosingScope)
+{
+ RootedFunction fun(context, function());
+ staticScope_ = StaticFunctionScope::create(context, fun, enclosingScope);
+ return staticScope_ != nullptr;
+}
+
template
FunctionBox*
Parser::newFunctionBox(Node fn, JSFunction* fun,
ParseContext* outerpc,
Directives inheritedDirectives,
GeneratorKind generatorKind,
- JSObject* enclosingStaticScope)
+ Handle enclosingStaticScope)
{
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
MOZ_ASSERT(fun);
@@ -801,15 +810,17 @@ Parser::newFunctionBox(Node fn, JSFunction* fun,
* function.
*/
FunctionBox* funbox =
- alloc.new_(context, traceListHead, fun, enclosingStaticScope, outerpc,
- inheritedDirectives, options().extraWarningsOption,
- generatorKind);
+ alloc.new_(context, traceListHead, fun, outerpc, inheritedDirectives,
+ options().extraWarningsOption, generatorKind);
if (!funbox) {
ReportOutOfMemory(context);
return nullptr;
}
-
traceListHead = funbox;
+
+ if (!funbox->initStaticScope(enclosingStaticScope))
+ return nullptr;
+
if (fn)
handler.setFunctionBox(fn, funbox);
@@ -1158,7 +1169,7 @@ Parser::standaloneFunctionBody(HandleFunction fun,
GeneratorKind generatorKind,
Directives inheritedDirectives,
Directives* newDirectives,
- HandleObject enclosingStaticScope)
+ Handle enclosingStaticScope)
{
MOZ_ASSERT(checkOptionsCalled);
@@ -2844,7 +2855,9 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox* funbo
size_t numInnerFunctions = pc->innerFunctions.length();
RootedFunction fun(context, funbox->function());
- LazyScript* lazy = LazyScript::CreateRaw(context, fun, numFreeVariables, numInnerFunctions,
+ Rooted funScope(context, funbox->staticScope());
+ LazyScript* lazy = LazyScript::CreateRaw(context, fun, funScope,
+ numFreeVariables, numInnerFunctions,
versionNumber(), funbox->bufStart, funbox->bufEnd,
funbox->startLine, funbox->startColumn);
if (!lazy)
@@ -3047,7 +3060,7 @@ Parser::standaloneLazyFunction(HandleFunction fun, bool strict
if (!tokenStream.peekTokenPos(&pn->pn_pos))
return null();
- RootedObject enclosing(context, fun->lazyScript()->enclosingScope());
+ Rooted enclosing(context, fun->lazyScript()->enclosingScope());
Directives directives(/* strict = */ strict);
FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, enclosing);
if (!funbox)
@@ -6501,8 +6514,11 @@ template <>
ParseNode*
Parser::withStatement(YieldHandling yieldHandling)
{
- // test262/ch12/12.10/12.10-0-1.js fails if we try to parse with-statements
- // in syntax-parse mode. See bug 892583.
+ // This is intentionally different from other abortIfSyntaxParser()
+ // bailouts: `with` statements rule out syntax-only parsing for the entire
+ // compilation unit. This `return null()` causes us to bail out all the way
+ // to BytecodeCompiler::compileScript(), which retries with syntax parsing
+ // disabled. See bug 892583.
if (handler.syntaxParser) {
handler.disableSyntaxParser();
abortedSyntaxParse = true;
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index f95e255497c..abfad067a28 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -290,7 +290,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
StmtInfoPC* innermostStmt() const { return stmtStack.innermost(); }
StmtInfoPC* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
StmtInfoPC* innermostNonLabelStmt() const { return stmtStack.innermostNonLabel(); }
- JSObject* innermostStaticScope() const {
+ StaticScope* innermostStaticScope() const {
if (StmtInfoPC* stmt = innermostScopeStmt())
return stmt->staticScope;
return sc->staticScope();
@@ -310,9 +310,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
if (sc->staticScope()->is()) {
bool bl = !stmt->enclosing;
MOZ_ASSERT_IF(bl, stmt->type == StmtType::BLOCK);
- MOZ_ASSERT_IF(bl, stmt->staticScope
- ->template as()
- .enclosingStaticScope() == sc->staticScope());
+ MOZ_ASSERT_IF(bl, stmt->staticScope->enclosingScope() == sc->staticScope());
return bl;
}
return !stmt;
@@ -507,11 +505,11 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
ObjectBox* newObjectBox(JSObject* obj);
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc,
Directives directives, GeneratorKind generatorKind,
- JSObject* enclosingStaticScope);
+ Handle enclosingStaticScope);
// Use when the funbox is the outermost.
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
- GeneratorKind generatorKind, HandleObject enclosingStaticScope)
+ GeneratorKind generatorKind, Handle enclosingStaticScope)
{
return newFunctionBox(fn, fun, nullptr, directives, generatorKind,
enclosingStaticScope);
@@ -521,7 +519,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext* outerpc,
Directives directives, GeneratorKind generatorKind)
{
- RootedObject enclosing(context, outerpc->innermostStaticScope());
+ Rooted enclosing(context, outerpc->innermostStaticScope());
return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing);
}
@@ -534,7 +532,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind,
HandleObject proto);
- bool generateBlockId(JSObject* staticScope, uint32_t* blockIdOut) {
+ bool generateBlockId(StaticScope* staticScope, uint32_t* blockIdOut) {
if (blockScopes.length() == StmtInfoPC::BlockIdLimit) {
tokenStream.reportError(JSMSG_NEED_DIET, "program");
return false;
@@ -600,7 +598,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node standaloneFunctionBody(HandleFunction fun, Handle formals,
GeneratorKind generatorKind,
Directives inheritedDirectives, Directives* newDirectives,
- HandleObject enclosingStaticScope);
+ Handle enclosingStaticScope);
// Parse a function, given only its arguments and body. Used for lazily
// parsed functions.
diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h
index a70fe79c80c..dd2ad6dcd9a 100644
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -229,10 +229,10 @@ class SharedContext
// GlobalSharedContexts are stack allocated and thus may use RootedObject
// for the static scope. FunctionBoxes are LifoAlloc'd and need to
// manually trace their static scope.
- virtual JSObject* staticScope() const = 0;
- void computeAllowSyntax(JSObject* staticScope);
- void computeInWith(JSObject* staticScope);
- void computeThisBinding(JSObject* staticScope);
+ virtual StaticScope* staticScope() const = 0;
+ void computeAllowSyntax(StaticScope* staticScope);
+ void computeInWith(StaticScope* staticScope);
+ void computeThisBinding(StaticScope* staticScope);
virtual ObjectBox* toObjectBox() { return nullptr; }
bool isObjectBox() { return toObjectBox() != nullptr; }
@@ -300,19 +300,19 @@ class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext
// non-function scope, so we have to compute our ThisBinding based on
// the actual callee.
if (maybeEvalCaller)
- computeThisBinding(maybeEvalCaller);
+ computeThisBinding(maybeEvalCaller->nonLazyScript()->staticScope());
else
computeThisBinding(staticScope);
}
- JSObject* staticScope() const override { return staticScope_; }
+ StaticScope* staticScope() const override { return staticScope_; }
};
class FunctionBox : public ObjectBox, public SharedContext
{
public:
Bindings bindings; /* bindings for this function */
- JSObject* enclosingStaticScope_;
+ StaticFunctionScope* staticScope_;
uint32_t bufStart;
uint32_t bufEnd;
uint32_t startLine;
@@ -335,13 +335,15 @@ class FunctionBox : public ObjectBox, public SharedContext
template
FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
- JSObject* enclosingStaticScope, ParseContext* pc,
- Directives directives, bool extraWarnings, GeneratorKind generatorKind);
+ ParseContext* pc, Directives directives, bool extraWarnings,
+ GeneratorKind generatorKind);
+
+ bool initStaticScope(Handle enclosingScope);
ObjectBox* toObjectBox() override { return this; }
JSFunction* function() const { return &object->as(); }
- JSObject* staticScope() const override { return function(); }
- JSObject* enclosingStaticScope() const { return enclosingStaticScope_; }
+ StaticFunctionScope* staticScope() const override { return staticScope_; }
+ StaticScope* enclosingStaticScope() const { return staticScope_->enclosingScope(); }
GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
bool isGenerator() const { return generatorKind() != NotGenerator; }
@@ -427,7 +429,7 @@ class ModuleBox : public ObjectBox, public SharedContext
ObjectBox* toObjectBox() override { return this; }
ModuleObject* module() const { return &object->as(); }
- JSObject* staticScope() const override { return module(); }
+ StaticModuleScope* staticScope() const override { return module()->staticScope(); }
void trace(JSTracer* trc) override;
};
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index 2700e1f01c0..c1fdf3fa885 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -955,8 +955,8 @@ LazyScript::traceChildren(JSTracer* trc)
if (sourceObject_)
TraceEdge(trc, &sourceObject_, "sourceObject");
- if (enclosingScope_)
- TraceEdge(trc, &enclosingScope_, "enclosingScope");
+ if (staticScope_)
+ TraceEdge(trc, &staticScope_, "staticScope");
// We rely on the fact that atoms are always tenured.
FreeVariable* freeVariables = this->freeVariables();
@@ -981,8 +981,8 @@ js::GCMarker::eagerlyMarkChildren(LazyScript *thing)
if (thing->sourceObject_)
traverseEdge(thing, static_cast(thing->sourceObject_));
- if (thing->enclosingScope_)
- traverseEdge(thing, static_cast(thing->enclosingScope_));
+ if (thing->staticScope_)
+ traverseEdge(thing, static_cast(thing->staticScope_));
// We rely on the fact that atoms are always tenured.
LazyScript::FreeVariable* freeVariables = thing->freeVariables();
diff --git a/js/src/gc/Policy.h b/js/src/gc/Policy.h
index 8243ae7efc7..1159d6ea835 100644
--- a/js/src/gc/Policy.h
+++ b/js/src/gc/Policy.h
@@ -100,6 +100,8 @@ class JitCode;
D(js::ScriptSourceObject*) \
D(js::Shape*) \
D(js::SharedArrayBufferObject*) \
+ D(js::StaticFunctionScope*) \
+ D(js::StaticScope*) \
D(js::StructTypeDescr*) \
D(js::UnownedBaseShape*) \
D(js::jit::JitCode*)
diff --git a/js/src/jit-test/tests/debug/Debugger-findObjects-11.js b/js/src/jit-test/tests/debug/Debugger-findObjects-11.js
new file mode 100644
index 00000000000..f0330447f0b
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debugger-findObjects-11.js
@@ -0,0 +1,7 @@
+// This shouldn't segfault.
+
+var g = newGlobal();
+g.eval(`function f() { return function() {
+ function g() {}
+}; }`);
+new Debugger(g).findObjects();
diff --git a/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js b/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js
new file mode 100644
index 00000000000..d872541c191
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js
@@ -0,0 +1,50 @@
+load(libdir + "asserts.js");
+
+const bad_types = [
+ 2112,
+ {geddy: "lee"},
+ () => 1,
+ [],
+ Array
+]
+
+// We only accept strings around here!
+for (var badType of bad_types) {
+ assertThrowsInstanceOf(() => {
+ Debugger.isCompilableUnit(badType);
+ }, TypeError);
+}
+
+const compilable_units = [
+ "wubba-lubba-dub-dub",
+ "'Get Schwifty!'",
+ "1 + 2",
+ "function f(x) {}",
+ "function x(f,) {", // statements with bad syntax are always compilable
+ "let x = 100",
+ ";;;;;;;;",
+ "",
+ " ",
+ "\n",
+ "let x",
+]
+
+const non_compilable_units = [
+ "function f(x) {",
+ "(...d) =>",
+ "{geddy:",
+ "{",
+ "[1, 2",
+ "[",
+ "1 +",
+ "let x =",
+ "3 ==",
+]
+
+for (var code of compilable_units) {
+ assertEq(Debugger.isCompilableUnit(code), true);
+}
+
+for (var code of non_compilable_units) {
+ assertEq(Debugger.isCompilableUnit(code), false);
+}
diff --git a/js/src/jit-test/tests/gc/withStatementOffThread.js b/js/src/jit-test/tests/gc/withStatementOffThread.js
new file mode 100644
index 00000000000..fa5a4edd452
--- /dev/null
+++ b/js/src/jit-test/tests/gc/withStatementOffThread.js
@@ -0,0 +1,12 @@
+if (helperThreadCount() == 0)
+ quit();
+
+var code = `
+function f() {
+ [function() { { function g() { } } },
+ function() { with ({}) { } }];
+}
+`;
+
+offThreadCompileScript(code);
+runOffThreadScript();
diff --git a/js/src/jit-test/tests/xdr/scope.js b/js/src/jit-test/tests/xdr/scope.js
index 417a402d24d..90698ceebd9 100644
--- a/js/src/jit-test/tests/xdr/scope.js
+++ b/js/src/jit-test/tests/xdr/scope.js
@@ -1,6 +1,50 @@
load(libdir + 'bytecode-cache.js');
var test = "";
+// code a nested function after calling it
+test = `
+ function f() {
+ function g() {
+ return [f, g];
+ }
+ return g();
+ }
+ f()
+`;
+evalWithCache(test, {
+ assertEqBytecode: true,
+ checkAfter(ctx) {
+ let [f, g] = ctx.global.f();
+ assertEq(f, ctx.global.f);
+ assertEq(f()[0], f);
+ assertEq(f()[1] === g, false); // second call, fresh g closure
+ assertEq(f()[1].toString(), g.toString()); // but the same source code
+ assertEq(g()[0], f);
+ assertEq(g()[1], g);
+ }
+});
+
+// code an unused function that contains an unused nested function
+test = `
+ function f() {
+ function g() {
+ return [f, g];
+ }
+ return g;
+ }
+ f
+`;
+evalWithCache(test, {
+ assertEqBytecode: true,
+ checkAfter(ctx) {
+ let f = ctx.global.f;
+ let g = f();
+ let [f1, g1] = g();
+ assertEq(f1, f);
+ assertEq(g1, g);
+ }
+});
+
// code a function which has both used and unused inner functions.
test = (function () {
function f() {
@@ -16,4 +60,4 @@ test = (function () {
return "var obj = { x : 2 };" + f.toSource() + "; f()";
})();
-evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 36ab64bde01..6fd562a0b81 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -3695,8 +3695,12 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
&inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
if (!builder.build()) {
- if (cx->isThrowingOverRecursed() || builder.abortReason() == AbortReason_Alloc)
+ if (cx->isThrowingOverRecursed() ||
+ cx->isThrowingOutOfMemory() ||
+ builder.abortReason() == AbortReason_Alloc)
+ {
return false;
+ }
MOZ_ASSERT(!cx->isExceptionPending());
return true;
}
diff --git a/js/src/jit/TypePolicy.h b/js/src/jit/TypePolicy.h
index ff31b547674..9d671bb20f4 100644
--- a/js/src/jit/TypePolicy.h
+++ b/js/src/jit/TypePolicy.h
@@ -525,14 +525,6 @@ class FilterTypeSetPolicy final : public TypePolicy
virtual bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
};
-static inline bool
-CoercesToDouble(MIRType type)
-{
- if (type == MIRType_Undefined || IsFloatingPointType(type))
- return true;
- return false;
-}
-
#undef SPECIALIZATION_DATA_
#undef INHERIT_DATA_
#undef EMPTY_DATA_
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index c33cce9ae00..65808e35f91 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3456,8 +3456,9 @@ CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
staticScopeObj.set(&globalLexical->staticBlock());
if (!scopeChain.empty()) {
- staticScopeObj.set(StaticNonSyntacticScope::create(cx, staticScopeObj));
- if (!staticScopeObj)
+ Rooted scope(cx,
+ StaticNonSyntacticScope::create(cx, staticScopeObj));
+ if (!scope)
return false;
// The XPConnect subscript loader, which may pass in its own dynamic
@@ -3478,10 +3479,11 @@ CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
// TODOshu: disallow the subscript loader from using non-distinguished
// objects as dynamic scopes.
dynamicScopeObj.set(
- cx->compartment()->getOrCreateNonSyntacticLexicalScope(cx, staticScopeObj,
- dynamicScopeObj));
+ cx->compartment()->getOrCreateNonSyntacticLexicalScope(cx, scope, dynamicScopeObj));
if (!dynamicScopeObj)
return false;
+
+ staticScopeObj.set(scope);
}
return true;
@@ -3495,7 +3497,7 @@ IsFunctionCloneable(HandleFunction fun)
// If a function was compiled to be lexically nested inside some other
// script, we cannot clone it without breaking the compiler's assumptions.
- if (JSObject* scope = fun->nonLazyScript()->enclosingStaticScope()) {
+ if (StaticScope* scope = fun->nonLazyScript()->enclosingStaticScope()) {
// If the script is directly under the global scope, we can clone it.
if (IsStaticGlobalLexicalScope(scope))
return true;
@@ -3512,7 +3514,7 @@ IsFunctionCloneable(HandleFunction fun)
if (block.needsClone())
return false;
- JSObject* enclosing = block.enclosingStaticScope();
+ StaticScope* enclosing = block.enclosingScope();
// If the script is an indirect eval that is immediately scoped
// under the global, we can clone it.
diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp
index 77fb3f6a2d3..e27a274ac49 100644
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -505,7 +505,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandle desc)
ClonedBlockObject*
JSCompartment::getOrCreateNonSyntacticLexicalScope(JSContext* cx,
- HandleObject enclosingStatic,
+ Handle enclosingStatic,
HandleObject enclosingScope)
{
if (!nonSyntacticLexicalScopes_) {
diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h
index 700d74f40f0..fb58d4b8acf 100644
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -32,6 +32,7 @@ template class ComponentFinder;
struct NativeIterator;
class ClonedBlockObject;
+class StaticNonSyntacticScope;
/*
* A single-entry cache for some base-10 double-to-string conversions. This
@@ -529,9 +530,10 @@ struct JSCompartment
explicit WrapperEnum(JSCompartment* c) : js::WrapperMap::Enum(c->crossCompartmentWrappers) {}
};
- js::ClonedBlockObject* getOrCreateNonSyntacticLexicalScope(JSContext* cx,
- js::HandleObject enclosingStatic,
- js::HandleObject enclosingScope);
+ js::ClonedBlockObject* getOrCreateNonSyntacticLexicalScope(
+ JSContext* cx,
+ js::Handle enclosingStatic,
+ js::HandleObject enclosingScope);
js::ClonedBlockObject* getNonSyntacticLexicalScope(JSObject* enclosingScope) const;
/*
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index e57dca138fd..b56346ee65a 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -405,9 +405,9 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext* cx)
return nullptr;
RootedFunction curr(cx, iter.callee(cx));
- for (StaticScopeIter i(curr); !i.done(); i++) {
+ for (StaticScopeIter i(curr->nonLazyScript()->staticScope()); !i.done(); i++) {
if (i.type() == StaticScopeIter::Function)
- curr = &i.fun();
+ curr = &i.fun().function();
}
return curr;
}
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index 1a63c781ae3..d368a092dd8 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -42,6 +42,7 @@
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
+#include "vm/ScopeObject.h"
#include "vm/Shape.h"
#include "vm/StringBuffer.h"
#include "vm/WrapperObject.h"
@@ -535,8 +536,8 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
template
bool
-js::XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
- MutableHandleFunction objp)
+js::XDRInterpretedFunction(XDRState* xdr, Handle enclosingScope,
+ HandleScript enclosingScript, MutableHandleFunction objp)
{
enum FirstWordFlag {
HasAtom = 0x1,
@@ -652,10 +653,12 @@ js::XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope, Han
}
template bool
-js::XDRInterpretedFunction(XDRState*, HandleObject, HandleScript, MutableHandleFunction);
+js::XDRInterpretedFunction(XDRState*, Handle, HandleScript,
+ MutableHandleFunction);
template bool
-js::XDRInterpretedFunction(XDRState*, HandleObject, HandleScript, MutableHandleFunction);
+js::XDRInterpretedFunction(XDRState*, Handle, HandleScript,
+ MutableHandleFunction);
/*
* [[HasInstance]] internal method for Function objects: fetch the .prototype
@@ -751,15 +754,14 @@ static JSObject*
CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
{
Rooted self(cx, cx->global());
-
RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
- /*
- * Bizarrely, |Function.prototype| must be an interpreted function, so
- * give it the guts to be one.
- */
+
+ // Bizarrely, |Function.prototype| must be an interpreted function, so
+ // give it the guts to be one.
+ Rooted globalLexicalEnv(cx, &self->lexicalScope());
JSObject* functionProto_ =
NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
- self, nullptr, objectProto, AllocKind::FUNCTION,
+ globalLexicalEnv, nullptr, objectProto, AllocKind::FUNCTION,
SingletonObject);
if (!functionProto_)
return nullptr;
@@ -787,8 +789,12 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
if (!sourceObject || !ScriptSourceObject::initFromOptions(cx, sourceObject, options))
return nullptr;
+ Rooted globalScope(cx, &globalLexicalEnv->staticBlock());
+ Rooted funScope(cx, StaticFunctionScope::create(cx, functionProto, globalScope));
+ if (!funScope)
+ return nullptr;
RootedScript script(cx, JSScript::Create(cx,
- /* enclosingScope = */ nullptr,
+ funScope,
/* savedCallerFun = */ false,
options,
sourceObject,
@@ -1445,7 +1451,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
}
if (script) {
- RootedObject enclosingScope(cx, lazy->enclosingScope());
+ Rooted enclosingScope(cx, lazy->enclosingScope());
RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, enclosingScope, fun, script));
if (!clonedScript)
return false;
@@ -2052,7 +2058,7 @@ js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject par
JSFunction*
js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
- HandleObject newStaticScope,
+ Handle newStaticScope,
gc::AllocKind allocKind /* = FUNCTION */,
HandleObject proto /* = nullptr */)
{
diff --git a/js/src/jsfun.h b/js/src/jsfun.h
index 4b4cff9740b..dc9cfafcebe 100644
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -728,7 +728,7 @@ CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
// Functions whose scripts are cloned are always given singleton types.
extern JSFunction*
CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
- HandleObject newStaticScope,
+ Handle newStaticScope,
gc::AllocKind kind = gc::AllocKind::FUNCTION,
HandleObject proto = nullptr);
@@ -789,7 +789,7 @@ JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool lambdaParen);
template
bool
-XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope,
+XDRInterpretedFunction(XDRState* xdr, Handle enclosingScope,
HandleScript enclosingScript, MutableHandleFunction objp);
/*
diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h
index b2ef7055c05..88d35534711 100644
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -92,7 +92,7 @@ CloneFunctionObjectIfNotSingleton(JSContext* cx, HandleFunction fun, HandleObjec
RootedScript script(cx, fun->getOrCreateScript(cx));
if (!script)
return nullptr;
- RootedObject staticScope(cx, script->enclosingStaticScope());
+ Rooted staticScope(cx, script->enclosingStaticScope());
return CloneFunctionAndScript(cx, fun, parent, staticScope, kind, proto);
}
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 25fa074500a..d8c26b313ca 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3410,6 +3410,7 @@ GCRuntime::sweepBackgroundThings(ZoneList& zones, LifoAlloc& freeBlocks, ThreadT
for (unsigned index = 0 ; index < BackgroundFinalizePhases[phase].length ; ++index) {
AllocKind kind = BackgroundFinalizePhases[phase].kinds[index];
ArenaHeader* arenas = zone->arenas.arenaListsToSweep[kind];
+ MOZ_RELEASE_ASSERT(uintptr_t(arenas) != uintptr_t(-1));
if (arenas)
ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas);
}
@@ -6831,7 +6832,7 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
// Get the static global lexical scope of the target compartment. Static
// scopes need to be fixed up below.
- RootedObject targetStaticGlobalLexicalScope(rt);
+ Rooted targetStaticGlobalLexicalScope(rt);
targetStaticGlobalLexicalScope = &target->maybeGlobal()->lexicalScope().staticBlock();
for (ZoneCellIter iter(source->zone(), AllocKind::SCRIPT); !iter.done(); iter.next()) {
diff --git a/js/src/jsgc.h b/js/src/jsgc.h
index 2ceaa7bbdd4..54ce98097d8 100644
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -594,7 +594,7 @@ class ArenaLists
enum BackgroundFinalizeStateEnum { BFS_DONE, BFS_RUN };
- typedef mozilla::Atomic
+ typedef mozilla::Atomic
BackgroundFinalizeState;
/* The current background finalization state, accessed atomically. */
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index 0f4598a528a..5e0c41d2a0b 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -590,9 +590,7 @@ inline bool
IsInternalFunctionObject(JSObject& funobj)
{
JSFunction& fun = funobj.as();
- MOZ_ASSERT_IF(fun.isLambda(),
- fun.isInterpreted() || fun.isAsmJSNative());
- return fun.isLambda() && fun.isInterpreted() && !fun.environment();
+ return fun.isInterpreted() && !fun.environment();
}
/*
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index e404ea4dc69..a33dba27301 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -516,7 +516,7 @@ XDRLazyFreeVariables(XDRState* xdr, MutableHandle lazy)
template
static bool
XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript script,
- HandleObject enclosingScope, MutableHandle lazy)
+ Handle funScope, MutableHandle lazy)
{
MOZ_ASSERT_IF(mode == XDR_ENCODE, script->isRelazifiable() && script->maybeLazyScript());
MOZ_ASSERT_IF(mode == XDR_ENCODE, !lazy->numInnerFunctions());
@@ -546,8 +546,8 @@ XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript scri
return false;
if (mode == XDR_DECODE) {
- lazy.set(LazyScript::Create(cx, fun, script, enclosingScope, script,
- packedFields, begin, end, lineno, column));
+ lazy.set(LazyScript::Create(cx, fun, script, funScope, script, packedFields,
+ begin, end, lineno, column));
// As opposed to XDRLazyScript, we need to restore the runtime bits
// of the script, as we are trying to match the fact this function
@@ -592,8 +592,8 @@ enum XDRClassKind {
template
bool
-js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript enclosingScript,
- HandleFunction fun, MutableHandleScript scriptp)
+js::XDRScript(XDRState* xdr, Handle enclosingScopeArg,
+ HandleScript enclosingScript, HandleFunction fun, MutableHandleScript scriptp)
{
/* NB: Keep this in sync with CopyScript. */
@@ -637,7 +637,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
JSContext* cx = xdr->cx();
RootedScript script(cx);
- RootedObject enclosingScope(cx, enclosingScopeArg);
+ Rooted enclosingScope(cx, enclosingScopeArg);
natoms = nsrcnotes = 0;
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = nyieldoffsets = 0;
@@ -849,6 +849,12 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
return false;
}
+ if (fun) {
+ enclosingScope = StaticFunctionScope::create(cx, fun, enclosingScope);
+ if (!enclosingScope)
+ return false;
+ }
+
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
options, sourceObject, 0, 0);
if (!script)
@@ -1045,28 +1051,33 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
}
if (!xdr->codeUint32(&enclosingStaticScopeIndex))
return false;
- Rooted enclosingStaticScope(cx);
+ Rooted enclosingStaticScope(cx);
if (mode == XDR_DECODE) {
if (enclosingStaticScopeIndex != UINT32_MAX) {
MOZ_ASSERT(enclosingStaticScopeIndex < i);
- enclosingStaticScope = script->objects()->vector[enclosingStaticScopeIndex];
+ enclosingStaticScope = &script->objects()->vector[enclosingStaticScopeIndex]
+ ->as();
} else {
// This is not ternary because MSVC can't typecheck the
// ternary.
if (fun)
- enclosingStaticScope = fun;
+ enclosingStaticScope = script->staticScope();
else
enclosingStaticScope = enclosingScope;
}
}
if (classk == CK_BlockObject) {
- Rooted tmp(cx, static_cast(objp->get()));
+ Rooted tmp(cx);
+ if (mode == XDR_ENCODE)
+ tmp = &(*objp)->as();
if (!XDRStaticBlockScope(xdr, enclosingStaticScope, &tmp))
return false;
*objp = tmp;
} else {
- Rooted tmp(cx, static_cast(objp->get()));
+ Rooted tmp(cx);
+ if (mode == XDR_ENCODE)
+ tmp = &(*objp)->as();
if (!XDRStaticWithScope(xdr, enclosingStaticScope, &tmp))
return false;
*objp = tmp;
@@ -1077,7 +1088,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
case CK_JSFunction: {
/* Code the nested function's enclosing scope. */
uint32_t funEnclosingScopeIndex = 0;
- RootedObject funEnclosingScope(cx);
+ Rooted funEnclosingScope(cx);
if (mode == XDR_ENCODE) {
RootedFunction function(cx, &(*objp)->as());
@@ -1124,12 +1135,13 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
// This is not ternary because MSVC can't typecheck the
// ternary.
if (fun)
- funEnclosingScope = fun;
+ funEnclosingScope = script->staticScope();
else
funEnclosingScope = enclosingScope;
} else {
MOZ_ASSERT(funEnclosingScopeIndex < i);
- funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
+ funEnclosingScope = &script->objects()->vector[funEnclosingScopeIndex]
+ .get()->as();
}
}
@@ -1206,7 +1218,10 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
if (mode == XDR_ENCODE)
lazy = script->maybeLazyScript();
- if (!XDRRelazificationInfo(xdr, fun, script, enclosingScope, &lazy))
+ Rooted lazyScope(cx, mode == XDR_DECODE
+ ? &enclosingScope->as()
+ : nullptr);
+ if (!XDRRelazificationInfo(xdr, fun, script, lazyScope, &lazy))
return false;
if (mode == XDR_DECODE)
@@ -1225,17 +1240,18 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript
}
template bool
-js::XDRScript(XDRState*, HandleObject, HandleScript, HandleFunction,
+js::XDRScript(XDRState*, Handle, HandleScript, HandleFunction,
MutableHandleScript);
template bool
-js::XDRScript(XDRState*, HandleObject, HandleScript, HandleFunction,
+js::XDRScript(XDRState*, Handle, HandleScript, HandleFunction,
MutableHandleScript);
template
bool
-js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
- HandleFunction fun, MutableHandle lazy)
+js::XDRLazyScript(XDRState* xdr, Handle enclosingScope,
+ HandleScript enclosingScript, HandleFunction fun,
+ MutableHandle lazy)
{
JSContext* cx = xdr->cx();
@@ -1268,7 +1284,11 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript
}
if (mode == XDR_DECODE) {
- lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript,
+ Rooted funScope(cx,
+ StaticFunctionScope::create(cx, fun, enclosingScope));
+ if (!funScope)
+ return false;
+ lazy.set(LazyScript::Create(cx, fun, nullptr, funScope, enclosingScript,
packedFields, begin, end, lineno, column));
if (!lazy)
return false;
@@ -1283,13 +1303,14 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript
// Code inner functions.
{
RootedFunction func(cx);
+ Rooted funScope(cx, lazy->staticScope());
HeapPtrFunction* innerFunctions = lazy->innerFunctions();
size_t numInnerFunctions = lazy->numInnerFunctions();
for (size_t i = 0; i < numInnerFunctions; i++) {
if (mode == XDR_ENCODE)
func = innerFunctions[i];
- if (!XDRInterpretedFunction(xdr, fun, enclosingScript, &func))
+ if (!XDRInterpretedFunction(xdr, funScope, enclosingScript, &func))
return false;
if (mode == XDR_DECODE)
@@ -1301,11 +1322,11 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript
}
template bool
-js::XDRLazyScript(XDRState*, HandleObject, HandleScript,
+js::XDRLazyScript(XDRState*, Handle, HandleScript,
HandleFunction, MutableHandle);
template bool
-js::XDRLazyScript(XDRState*, HandleObject, HandleScript,
+js::XDRLazyScript(XDRState*, Handle, HandleScript,
HandleFunction, MutableHandle);
void
@@ -2747,7 +2768,7 @@ JSScript::initCompartment(ExclusiveContext* cx)
}
/* static */ JSScript*
-JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCallerFun,
+JSScript::Create(ExclusiveContext* cx, Handle staticScope, bool savedCallerFun,
const ReadOnlyCompileOptions& options, HandleObject sourceObject,
uint32_t bufStart, uint32_t bufEnd)
{
@@ -2760,7 +2781,7 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
PodZero(script.get());
new (&script->bindings) Bindings;
- script->enclosingStaticScope_ = enclosingScope;
+ script->staticScope_ = staticScope;
script->savedCallerFun_ = savedCallerFun;
script->initCompartment(cx);
@@ -2768,10 +2789,12 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
script->noScriptRval_ = options.noScriptRval;
script->treatAsRunOnce_ = options.isRunOnce;
- // Compute whether this script is under a non-syntactic scope. We don't
- // need to walk the entire static scope chain if the script is nested in a
- // function. In that case, we can propagate the cached value from the
- // outer script.
+ // Compute whether this script is under a non-syntactic scope, passing
+ // staticScope->enclosingScope() in a case where staticScope itself is not
+ // a non-syntactic scope and may not be fully initialized yet.
+ Rooted enclosingScope(cx, staticScope);
+ if (staticScope && staticScope->is())
+ enclosingScope = staticScope->enclosingScope();
script->hasNonSyntacticScope_ = HasNonSyntacticStaticScopeChain(enclosingScope);
script->version = options.version;
@@ -3123,15 +3146,20 @@ JSScript::uninlinedGlobal() const
void
JSScript::fixEnclosingStaticGlobalLexicalScope()
{
- MOZ_ASSERT(IsStaticGlobalLexicalScope(enclosingStaticScope_));
- enclosingStaticScope_ = &global().lexicalScope().staticBlock();
+ if (function_) {
+ MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_->enclosingScope()));
+ staticScope_->setEnclosingScope(&global().lexicalScope().staticBlock());
+ } else {
+ MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_));
+ staticScope_ = &global().lexicalScope().staticBlock();
+ }
}
void
LazyScript::fixEnclosingStaticGlobalLexicalScope()
{
- MOZ_ASSERT(IsStaticGlobalLexicalScope(enclosingScope_));
- enclosingScope_ = &function_->global().lexicalScope().staticBlock();
+ MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_->enclosingScope()));
+ staticScope_->setEnclosingScope(&function_->global().lexicalScope().staticBlock());
}
void
@@ -3409,7 +3437,8 @@ Rebase(JSScript* dst, JSScript* src, T* srcp)
}
static JSObject*
-CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun)
+CloneInnerInterpretedFunction(JSContext* cx, Handle enclosingScope,
+ HandleFunction srcFun)
{
/* NB: Keep this in sync with XDRInterpretedFunction. */
RootedObject cloneProto(cx);
@@ -3449,7 +3478,7 @@ CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, Handle
}
bool
-js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src,
+js::detail::CopyScript(JSContext* cx, Handle scriptStaticScope, HandleScript src,
HandleScript dst)
{
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
@@ -3496,14 +3525,15 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
if (obj->is()) {
Rooted innerBlock(cx, &obj->as());
- RootedObject enclosingScope(cx);
+ Rooted enclosingScope(cx);
if (NestedStaticScope* enclosingBlock = innerBlock->enclosingNestedScope()) {
if (IsStaticGlobalLexicalScope(enclosingBlock)) {
MOZ_ASSERT(IsStaticGlobalLexicalScope(scriptStaticScope) ||
scriptStaticScope->is());
enclosingScope = scriptStaticScope;
} else {
- enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)];
+ enclosingScope = &objects[FindScopeObjectIndex(src, *enclosingBlock)]
+ .get()->as();
}
} else {
enclosingScope = scriptStaticScope;
@@ -3525,13 +3555,14 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
if (!innerFun->getOrCreateScript(cx))
return false;
}
- RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
+ Rooted staticScope(cx, innerFun->nonLazyScript()
+ ->enclosingStaticScope());
StaticScopeIter ssi(cx, staticScope);
- RootedObject enclosingScope(cx);
+ Rooted enclosingScope(cx);
if (ssi.done() || ssi.type() == StaticScopeIter::NonSyntactic) {
enclosingScope = scriptStaticScope;
} else if (ssi.type() == StaticScopeIter::Function) {
- MOZ_ASSERT(scriptStaticScope->is());
+ MOZ_ASSERT(scriptStaticScope->is());
enclosingScope = scriptStaticScope;
} else if (ssi.type() == StaticScopeIter::Block) {
if (ssi.block().isGlobal()) {
@@ -3539,10 +3570,12 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
scriptStaticScope->is());
enclosingScope = scriptStaticScope;
} else {
- enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
+ enclosingScope = &objects[FindScopeObjectIndex(src, ssi.block())]
+ .get()->as();
}
} else {
- enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
+ enclosingScope = &objects[FindScopeObjectIndex(src, ssi.staticWith())]
+ .get()->as();
}
clone = CloneInnerInterpretedFunction(cx, enclosingScope, innerFun);
@@ -3656,7 +3689,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
}
static JSScript*
-CreateEmptyScriptForClone(JSContext* cx, HandleObject enclosingScope, HandleScript src)
+CreateEmptyScriptForClone(JSContext* cx, Handle enclosingScope, HandleScript src)
{
/*
* Wrap the script source object as needed. Self-hosted scripts may be
@@ -3708,18 +3741,23 @@ js::CloneGlobalScript(JSContext* cx, Handle enclosingScope, Handle
}
JSScript*
-js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
+js::CloneScriptIntoFunction(JSContext* cx, Handle enclosingScope, HandleFunction fun,
HandleScript src)
{
MOZ_ASSERT(fun->isInterpreted());
+ Rooted funScope(cx, StaticFunctionScope::create(cx, fun,
+ enclosingScope));
+ if (!funScope)
+ return nullptr;
+
// Allocate the destination script up front and set it as the script of
// |fun|, which is to be its container.
//
// This is so that when cloning nested functions, they can walk the static
// scope chain via fun and correctly compute the presence of a
// non-syntactic global.
- RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src));
+ RootedScript dst(cx, CreateEmptyScriptForClone(cx, funScope, src));
if (!dst)
return nullptr;
@@ -3735,7 +3773,7 @@ js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFu
fun->initScript(dst);
}
- if (!detail::CopyScript(cx, fun, src, dst)) {
+ if (!detail::CopyScript(cx, funScope, src, dst)) {
if (lazy)
fun->initLazyScript(lazy);
else
@@ -3980,8 +4018,8 @@ JSScript::traceChildren(JSTracer* trc)
if (module_)
TraceEdge(trc, &module_, "module");
- if (enclosingStaticScope_)
- TraceEdge(trc, &enclosingStaticScope_, "enclosingStaticScope");
+ if (staticScope_)
+ TraceEdge(trc, &staticScope_, "staticScope");
if (maybeLazyScript())
TraceManuallyBarrieredEdge(trc, &lazyScript, "lazyScript");
@@ -4083,20 +4121,18 @@ JSScript::getStaticBlockScope(jsbytecode* pc)
return blockChain;
}
-JSObject*
+StaticScope*
JSScript::innermostStaticScopeInScript(jsbytecode* pc)
{
- if (JSObject* scope = getStaticBlockScope(pc))
+ if (NestedStaticScope* scope = getStaticBlockScope(pc))
return scope;
- if (module())
- return module();
- return functionNonDelazifying();
+ return staticScope_;
}
-JSObject*
+StaticScope*
JSScript::innermostStaticScope(jsbytecode* pc)
{
- if (JSObject* scope = innermostStaticScopeInScript(pc))
+ if (StaticScope* scope = innermostStaticScopeInScript(pc))
return scope;
return enclosingStaticScope();
}
@@ -4141,8 +4177,13 @@ js::SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame,
// Note that here and below, it is insufficient to only check for
// JS_OPTIMIZED_ARGUMENTS, as Ion could have optimized out the
// arguments slot.
- if (IsOptimizedPlaceholderMagicValue(frame.callObj().as().aliasedVar(ScopeCoordinate(pc))))
- frame.callObj().as().setAliasedVar(cx, ScopeCoordinate(pc), cx->names().arguments, ObjectValue(*argsobj));
+ if (IsOptimizedPlaceholderMagicValue(frame.callObj().as()
+ .aliasedVar(ScopeCoordinate(pc))))
+ {
+ frame.callObj().as().setAliasedVar(cx, ScopeCoordinate(pc),
+ cx->names().arguments,
+ ObjectValue(*argsobj));
+ }
} else {
if (IsOptimizedPlaceholderMagicValue(frame.unaliasedLocal(bi.frameIndex())))
frame.unaliasedLocal(bi.frameIndex()) = ObjectValue(*argsobj);
@@ -4240,10 +4281,12 @@ JSScript::formalLivesInArgumentsObject(unsigned argSlot)
return argsObjAliasesFormals() && !formalIsAliased(argSlot);
}
-LazyScript::LazyScript(JSFunction* fun, void* table, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
+LazyScript::LazyScript(JSFunction* fun, StaticFunctionScope* funScope, void* table,
+ uint64_t packedFields, uint32_t begin, uint32_t end,
+ uint32_t lineno, uint32_t column)
: script_(nullptr),
function_(fun),
- enclosingScope_(nullptr),
+ staticScope_(funScope),
sourceObject_(nullptr),
table_(table),
packedFields_(packedFields),
@@ -4271,13 +4314,10 @@ LazyScript::resetScript()
}
void
-LazyScript::setParent(JSObject* enclosingScope, ScriptSourceObject* sourceObject)
+LazyScript::initSource(ScriptSourceObject* sourceObject)
{
- MOZ_ASSERT(!sourceObject_ && !enclosingScope_);
- MOZ_ASSERT_IF(enclosingScope, function_->compartment() == enclosingScope->compartment());
+ MOZ_ASSERT(!sourceObject_);
MOZ_ASSERT(function_->compartment() == sourceObject->compartment());
-
- enclosingScope_ = enclosingScope;
sourceObject_ = sourceObject;
}
@@ -4295,6 +4335,7 @@ LazyScript::maybeForwardedScriptSource() const
/* static */ LazyScript*
LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
+ Handle funScope,
uint64_t packedFields, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column)
{
@@ -4324,11 +4365,12 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
cx->compartment()->scheduleDelazificationForDebugger();
- return new (res) LazyScript(fun, table.forget(), packed, begin, end, lineno, column);
+ return new (res) LazyScript(fun, funScope, table.forget(), packed, begin, end, lineno, column);
}
/* static */ LazyScript*
LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
+ Handle funScope,
uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
{
@@ -4349,14 +4391,15 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
p.isDerivedClassConstructor = false;
p.needsHomeObject = false;
- LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
+ LazyScript* res = LazyScript::CreateRaw(cx, fun, funScope, packedFields,
+ begin, end, lineno, column);
MOZ_ASSERT_IF(res, res->version() == version);
return res;
}
/* static */ LazyScript*
LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
- HandleScript script, HandleObject enclosingScope,
+ HandleScript script, Handle funScope,
HandleScript sourceObjectScript,
uint64_t packedFields, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column)
@@ -4368,7 +4411,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
// holding this lazy script.
HandleFunction dummyFun = fun;
- LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
+ LazyScript* res = LazyScript::CreateRaw(cx, fun, funScope, packedFields,
+ begin, end, lineno, column);
if (!res)
return nullptr;
@@ -4386,7 +4430,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
// Set the enclosing scope of the lazy function, this would later be
// used to define the environment when the function would be used.
MOZ_ASSERT(!res->sourceObject());
- res->setParent(enclosingScope, &sourceObjectScript->scriptSourceUnwrap());
+ res->initSource(&sourceObjectScript->scriptSourceUnwrap());
MOZ_ASSERT(!res->hasScript());
if (script)
@@ -4419,10 +4463,10 @@ LazyScript::hasUncompiledEnclosingScript() const
// If the enclosing scope is a function with a null script or has a script
// without code, it was not successfully compiled.
- if (!enclosingScope() || !enclosingScope()->is())
+ if (!enclosingScope() || !enclosingScope()->is())
return false;
- JSFunction& fun = enclosingScope()->as();
+ JSFunction& fun = enclosingScope()->as().function();
return !fun.hasScript() || fun.hasUncompiledScript() || !fun.nonLazyScript()->code();
}
diff --git a/js/src/jsscript.h b/js/src/jsscript.h
index b13598cbe0a..e70ec4f8171 100644
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -50,6 +50,7 @@ class LazyScript;
class ModuleObject;
class NestedStaticScope;
class StaticScope;
+class StaticFunctionScope;
class RegExpObject;
struct SourceCompressionTask;
class Shape;
@@ -66,7 +67,8 @@ namespace detail {
// Do not call this directly! It is exposed for the friend declarations in
// this file.
bool
-CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, HandleScript dst);
+CopyScript(JSContext* cx, Handle