diff --git a/CLOBBER b/CLOBBER
index 68d7e52fb0ea..f37a76e82ae7 100644
--- a/CLOBBER
+++ b/CLOBBER
@@ -18,3 +18,4 @@
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 879831 needed to clobber for the removal of jsprobes.cpp
+bug 882904: move LIBS to moz.build (logic).
diff --git a/accessible/src/generic/HyperTextAccessible.cpp b/accessible/src/generic/HyperTextAccessible.cpp
index 94d55192526e..28b0c91dd652 100644
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -2112,6 +2112,14 @@ HyperTextAccessible::ScrollSubstringToPoint(int32_t aStartIndex,
ENameValueFlag
HyperTextAccessible::NativeName(nsString& aName)
{
+ // Check @alt attribute for invalid img elements.
+ bool hasImgAlt = false;
+ if (mContent->IsHTML(nsGkAtoms::img)) {
+ hasImgAlt = mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
+ if (!aName.IsEmpty())
+ return eNameOK;
+ }
+
ENameValueFlag nameFlag = AccessibleWrap::NativeName(aName);
if (!aName.IsEmpty())
return nameFlag;
@@ -2123,7 +2131,7 @@ HyperTextAccessible::NativeName(nsString& aName)
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName))
aName.CompressWhitespace();
- return eNameOK;
+ return hasImgAlt ? eNoNameOnPurpose : eNameOK;
}
void
diff --git a/accessible/src/jsat/content-script.js b/accessible/src/jsat/content-script.js
index 92c36b40383a..f9eecbe4fc0c 100644
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -16,6 +16,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',
'resource://gre/modules/accessibility/EventManager.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'ObjectWrapper',
+ 'resource://gre/modules/ObjectWrapper.jsm');
Logger.debug('content-script.js');
@@ -182,6 +184,21 @@ function scroll(aMessage) {
while (acc) {
let elem = acc.DOMNode;
+ // This is inspired by IndieUI events. Once they are
+ // implemented, it should be easy to transition to them.
+ // https://dvcs.w3.org/hg/IndieUI/raw-file/tip/src/indie-ui-events.html#scrollrequest
+ let uiactions = elem.getAttribute ? elem.getAttribute('uiactions') : '';
+ if (uiactions && uiactions.split(' ').indexOf('scroll') >= 0) {
+ let evt = elem.ownerDocument.createEvent('CustomEvent');
+ let details = horiz ? { deltaX: page * elem.clientWidth } :
+ { deltaY: page * elem.clientHeight };
+ evt.initCustomEvent(
+ 'scrollrequest', true, true,
+ ObjectWrapper.wrap(details, elem.ownerDocument.defaultView));
+ if (!elem.dispatchEvent(evt))
+ return;
+ }
+
// We will do window scrolling next.
if (elem == content.document)
break;
@@ -202,25 +219,6 @@ function scroll(aMessage) {
return true;
}
}
-
- let controllers = acc.
- getRelationByType(
- Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
- for (let i = 0; controllers.targetsCount > i; i++) {
- let controller = controllers.getTarget(i);
- // If the section has a controlling slider, it should be considered
- // the page-turner.
- if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
- // Sliders are controlled with ctrl+right/left. I just decided :)
- let evt = content.document.createEvent('KeyboardEvent');
- evt.initKeyEvent(
- 'keypress', true, true, null,
- true, false, false, false,
- (page > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
- controller.DOMNode.dispatchEvent(evt);
- return true;
- }
- }
}
acc = acc.parent;
}
diff --git a/accessible/tests/mochitest/name/test_general.html b/accessible/tests/mochitest/name/test_general.html
index d28626ae3214..737e523bb6b7 100644
--- a/accessible/tests/mochitest/name/test_general.html
+++ b/accessible/tests/mochitest/name/test_general.html
@@ -208,6 +208,7 @@
// Test equation image
testName("img_eq", "x^2 + y^2 + z^2")
+ testName("input_img_eq", "x^2 + y^2 + z^2")
testName("txt_eq", "x^2 + y^2 + z^2")
////////////////////////////////////////////////////////////////////////
@@ -606,6 +607,7 @@
Image:
+
Text:
diff --git a/accessible/tests/mochitest/tree/Makefile.in b/accessible/tests/mochitest/tree/Makefile.in
index 9631b3db8f94..900615a966d2 100644
--- a/accessible/tests/mochitest/tree/Makefile.in
+++ b/accessible/tests/mochitest/tree/Makefile.in
@@ -34,6 +34,7 @@ MOCHITEST_A11Y_FILES =\
test_groupbox.xul \
test_iframe.html \
test_img.html \
+ test_invalid_img.xhtml \
test_invalidationlist.html \
test_list.html \
test_map.html \
diff --git a/accessible/tests/mochitest/tree/test_invalid_img.xhtml b/accessible/tests/mochitest/tree/test_invalid_img.xhtml
new file mode 100644
index 000000000000..14ada63224ea
--- /dev/null
+++ b/accessible/tests/mochitest/tree/test_invalid_img.xhtml
@@ -0,0 +1,50 @@
+
+
+ invalid html img
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mozilla Bug 852129
+
+
+
+
+
+
+
+ 1
+
+
diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in
index 0a71a0a17643..3bfbe1df17c5 100644
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -51,7 +51,6 @@ STL_FLAGS=
LIBS += $(JEMALLOC_LIBS)
LIBS += \
- $(EXTRA_DSO_LIBS) \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
diff --git a/b2g/components/Makefile.in b/b2g/components/Makefile.in
index 46c41604d1d5..da26cc6d791d 100644
--- a/b2g/components/Makefile.in
+++ b/b2g/components/Makefile.in
@@ -9,7 +9,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
ActivitiesGlue.js \
AlertsService.js \
B2GAboutRedirector.js \
@@ -36,7 +36,7 @@ EXTRA_JS_MODULES = \
$(NULL)
ifdef MOZ_UPDATER
-EXTRA_PP_COMPONENTS += UpdatePrompt.js
+DISABLED_EXTRA_PP_COMPONENTS += UpdatePrompt.js
endif
include $(topsrcdir)/config/rules.mk
diff --git a/b2g/components/moz.build b/b2g/components/moz.build
index 12242bdbdbc6..5b36cdfbada8 100644
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -12,3 +12,26 @@ XPIDL_SOURCES += [
MODULE = 'B2GComponents'
+EXTRA_PP_COMPONENTS += [
+ 'ActivitiesGlue.js',
+ 'AlertsService.js',
+ 'B2GAboutRedirector.js',
+ 'B2GComponents.manifest',
+ 'ContentHandler.js',
+ 'ContentPermissionPrompt.js',
+ 'DirectoryProvider.js',
+ 'FilePicker.js',
+ 'MailtoProtocolHandler.js',
+ 'MozKeyboard.js',
+ 'PaymentGlue.js',
+ 'ProcessGlobal.js',
+ 'RecoveryService.js',
+ 'SmsProtocolHandler.js',
+ 'TelProtocolHandler.js',
+ 'YoutubeProtocolHandler.js',
+]
+
+if CONFIG['MOZ_UPDATER']:
+ EXTRA_PP_COMPONENTS += [
+ 'UpdatePrompt.js',
+ ]
diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in
index a705fdbd4aa0..c4a5de582de0 100644
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -54,7 +54,6 @@ DEFINES += -DXPCOM_GLUE
STL_FLAGS=
LIBS += \
- $(EXTRA_DSO_LIBS) \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
diff --git a/browser/base/content/test/browser_datareporting_notification.js b/browser/base/content/test/browser_datareporting_notification.js
index 51c3bdeb7535..b892bd00922f 100644
--- a/browser/base/content/test/browser_datareporting_notification.js
+++ b/browser/base/content/test/browser_datareporting_notification.js
@@ -23,7 +23,6 @@ function sendNotifyRequest(name) {
service.healthReporter.onInit().then(function onInit() {
is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy.");
- is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for notification response.");
});
return policy;
diff --git a/browser/base/content/test/browser_urlbar_search_healthreport.js b/browser/base/content/test/browser_urlbar_search_healthreport.js
index 215aa63141bc..4315a98649ed 100644
--- a/browser/base/content/test/browser_urlbar_search_healthreport.js
+++ b/browser/base/content/test/browser_urlbar_search_healthreport.js
@@ -45,7 +45,7 @@ function test() {
gURLBar.value = "firefox health report";
gURLBar.handleCommand();
- executeSoon(function afterSearch() {
+ executeSoon(() => executeSoon(() => {
gBrowser.removeTab(tab);
m.getValues().then(function onData(data) {
@@ -58,7 +58,7 @@ function test() {
is(newCount, oldCount + 1, "Exactly one search has been recorded.");
finish();
});
- });
+ }));
});
});
}
diff --git a/browser/components/Makefile.in b/browser/components/Makefile.in
index dc685b3f9e5f..a70f997846c2 100644
--- a/browser/components/Makefile.in
+++ b/browser/components/Makefile.in
@@ -13,7 +13,7 @@ DISABLED_EXTRA_COMPONENTS = \
BrowserComponents.manifest \
$(NULL)
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
nsBrowserContentHandler.js \
nsBrowserGlue.js \
$(NULL)
diff --git a/browser/components/feeds/src/Makefile.in b/browser/components/feeds/src/Makefile.in
index 904a5d79920d..afd42cf6f0ef 100644
--- a/browser/components/feeds/src/Makefile.in
+++ b/browser/components/feeds/src/Makefile.in
@@ -25,7 +25,7 @@ DISABLED_EXTRA_COMPONENTS = \
WebContentConverter.js \
$(NULL)
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
FeedWriter.js \
$(NULL)
diff --git a/browser/components/feeds/src/moz.build b/browser/components/feeds/src/moz.build
index e97a4f0ab691..f79e0f956b33 100644
--- a/browser/components/feeds/src/moz.build
+++ b/browser/components/feeds/src/moz.build
@@ -15,3 +15,7 @@ EXTRA_COMPONENTS += [
'FeedConverter.js',
'WebContentConverter.js',
]
+
+EXTRA_PP_COMPONENTS += [
+ 'FeedWriter.js',
+]
diff --git a/browser/components/migration/src/Makefile.in b/browser/components/migration/src/Makefile.in
index 017d5f6fc8d2..ab7afa2202d6 100644
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -19,7 +19,7 @@ DISABLED_EXTRA_COMPONENTS = \
FirefoxProfileMigrator.js \
$(NULL)
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
ChromeProfileMigrator.js \
$(NULL)
@@ -27,19 +27,19 @@ ifeq ($(OS_ARCH),WINNT)
DISABLED_EXTRA_COMPONENTS += IEProfileMigrator.js \
$(NULL)
-EXTRA_PP_COMPONENTS += SafariProfileMigrator.js \
+DISABLED_EXTRA_PP_COMPONENTS += SafariProfileMigrator.js \
$(NULL)
DEFINES += -DHAS_IE_MIGRATOR -DHAS_SAFARI_MIGRATOR
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-EXTRA_PP_COMPONENTS += SafariProfileMigrator.js \
+DISABLED_EXTRA_PP_COMPONENTS += SafariProfileMigrator.js \
$(NULL)
DEFINES += -DHAS_SAFARI_MIGRATOR
endif
-EXTRA_PP_COMPONENTS += \
+DISABLED_EXTRA_PP_COMPONENTS += \
BrowserProfileMigrators.manifest \
$(NULL)
diff --git a/browser/components/migration/src/moz.build b/browser/components/migration/src/moz.build
index e98f9e082ea0..211f79e22e1e 100644
--- a/browser/components/migration/src/moz.build
+++ b/browser/components/migration/src/moz.build
@@ -20,3 +20,18 @@ if CONFIG['OS_ARCH'] == 'WINNT':
EXTRA_COMPONENTS += [
'IEProfileMigrator.js',
]
+
+EXTRA_PP_COMPONENTS += [
+ 'BrowserProfileMigrators.manifest',
+ 'ChromeProfileMigrator.js',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ EXTRA_PP_COMPONENTS += [
+ 'SafariProfileMigrator.js',
+ ]
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ EXTRA_PP_COMPONENTS += [
+ 'SafariProfileMigrator.js',
+ ]
diff --git a/browser/components/moz.build b/browser/components/moz.build
index dc73374babdb..1e2aa74ac939 100644
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -39,3 +39,7 @@ MODULE = 'browsercomps'
EXTRA_COMPONENTS += [
'BrowserComponents.manifest',
]
+EXTRA_PP_COMPONENTS += [
+ 'nsBrowserContentHandler.js',
+ 'nsBrowserGlue.js',
+]
diff --git a/browser/components/search/test/browser_healthreport.js b/browser/components/search/test/browser_healthreport.js
index d70191560df0..58dc9d881ab5 100644
--- a/browser/components/search/test/browser_healthreport.js
+++ b/browser/components/search/test/browser_healthreport.js
@@ -66,7 +66,7 @@ function test() {
}
EventUtils.synthesizeKey("VK_RETURN", {});
- executeSoon(afterSearch);
+ executeSoon(() => executeSoon(afterSearch));
});
});
}
diff --git a/browser/devtools/styleeditor/StyleEditorPanel.jsm b/browser/devtools/styleeditor/StyleEditorPanel.jsm
index 0cfa54b4e360..783dfe84d9e9 100644
--- a/browser/devtools/styleeditor/StyleEditorPanel.jsm
+++ b/browser/devtools/styleeditor/StyleEditorPanel.jsm
@@ -91,16 +91,16 @@ StyleEditorPanel.prototype = {
* @param {string} href
* Url of stylesheet to find and select in editor
* @param {number} line
- * Line number to jump to after selecting
+ * Line number to jump to after selecting. One-indexed
* @param {number} col
- * Column number to jump to after selecting
+ * Column number to jump to after selecting. One-indexed
*/
selectStyleSheet: function(href, line, col) {
if (!this._debuggee || !this.UI) {
return;
}
let stylesheet = this._debuggee.styleSheetFromHref(href);
- this.UI.selectStyleSheet(href, line, col);
+ this.UI.selectStyleSheet(href, line - 1, col - 1);
},
/**
diff --git a/browser/devtools/styleeditor/StyleEditorUI.jsm b/browser/devtools/styleeditor/StyleEditorUI.jsm
index d89e3c6e7668..3ddca7022cd7 100644
--- a/browser/devtools/styleeditor/StyleEditorUI.jsm
+++ b/browser/devtools/styleeditor/StyleEditorUI.jsm
@@ -48,7 +48,7 @@ function StyleEditorUI(debuggee, panelDoc) {
this._root = this._panelDoc.getElementById("style-editor-chrome");
this.editors = [];
- this.selectedStyleSheetIndex = -1;
+ this.selectedEditor = null;
this._onStyleSheetCreated = this._onStyleSheetCreated.bind(this);
this._onStyleSheetsCleared = this._onStyleSheetsCleared.bind(this);
@@ -84,6 +84,14 @@ StyleEditorUI.prototype = {
this._markedDirty = value;
},
+ /*
+ * Index of selected stylesheet in document.styleSheets
+ */
+ get selectedStyleSheetIndex() {
+ return this.selectedEditor ?
+ this.selectedEditor.styleSheet.styleSheetIndex : -1;
+ },
+
/**
* Build the initial UI and wire buttons with event handlers.
*/
@@ -140,10 +148,17 @@ StyleEditorUI.prototype = {
* Handler for debuggee's 'stylesheets-cleared' event. Remove all editors.
*/
_onStyleSheetsCleared: function() {
- this._clearStyleSheetEditors();
+ // remember selected sheet and line number for next load
+ if (this.selectedEditor) {
+ let href = this.selectedEditor.styleSheet.href;
+ let {line, col} = this.selectedEditor.sourceEditor.getCaretPosition();
+ this.selectStyleSheet(href, line, col);
+ }
+ this._clearStyleSheetEditors();
this._view.removeAll();
- this.selectedStyleSheetIndex = -1;
+
+ this.selectedEditor = null;
this._root.classList.add("loading");
},
@@ -166,11 +181,22 @@ StyleEditorUI.prototype = {
* StyleSheet object for new sheet
*/
_onDocumentLoad: function(event, styleSheets) {
+ if (this._styleSheetToSelect) {
+ // if selected stylesheet from previous load isn't here,
+ // just set first stylesheet to be selected instead
+ let selectedExists = styleSheets.some((sheet) => {
+ return this._styleSheetToSelect.href == sheet.href;
+ })
+ if (!selectedExists) {
+ this._styleSheetToSelect = null;
+ }
+ }
for (let sheet of styleSheets) {
this._addStyleSheetEditor(sheet);
}
- // this might be the first stylesheet, so remove loading indicator
+
this._root.classList.remove("loading");
+
this.emit("document-load");
},
@@ -295,13 +321,18 @@ StyleEditorUI.prototype = {
onShow: function(summary, details, data) {
let editor = data.editor;
+ this.selectedEditor = editor;
+ this._styleSheetToSelect = null;
+
if (!editor.sourceEditor) {
// only initialize source editor when we switch to this view
let inputElement = details.querySelector(".stylesheet-editor-input");
editor.load(inputElement);
}
editor.onShow();
- }
+
+ this.emit("editor-selected", editor);
+ }.bind(this)
});
},
@@ -314,7 +345,6 @@ StyleEditorUI.prototype = {
for each (let editor in this.editors) {
if (editor.styleSheet.href == sheet.href) {
this._selectEditor(editor, sheet.line, sheet.col);
- this._styleSheetToSelect = null;
break;
}
}
@@ -331,18 +361,14 @@ StyleEditorUI.prototype = {
* Column number to jump to
*/
_selectEditor: function(editor, line, col) {
- line = line || 1;
- col = col || 1;
-
- this.selectedStyleSheetIndex = editor.styleSheet.styleSheetIndex;
+ line = line || 0;
+ col = col || 0;
editor.getSourceEditor().then(() => {
- editor.sourceEditor.setCaretPosition(line - 1, col - 1);
+ editor.sourceEditor.setCaretPosition(line, col);
});
this._view.activeSummary = editor.summary;
-
- this.emit("editor-selected", editor);
},
/**
@@ -354,9 +380,9 @@ StyleEditorUI.prototype = {
* a stylesheet is not passed and the editor is initialized we ignore
* the call.
* @param {Number} [line]
- * Line to which the caret should be moved (one-indexed).
+ * Line to which the caret should be moved (zero-indexed).
* @param {Number} [col]
- * Column to which the caret should be moved (one-indexed).
+ * Column to which the caret should be moved (zero-indexed).
*/
selectStyleSheet: function(href, line, col)
{
diff --git a/browser/devtools/styleeditor/test/Makefile.in b/browser/devtools/styleeditor/test/Makefile.in
index f80625eadb43..c43c941e6409 100644
--- a/browser/devtools/styleeditor/test/Makefile.in
+++ b/browser/devtools/styleeditor/test/Makefile.in
@@ -28,6 +28,7 @@ _BROWSER_TEST_FILES = \
browser_styleeditor_bug_740541_iframes.js \
browser_styleeditor_bug_851132_middle_click.js \
browser_styleeditor_nostyle.js \
+ browser_styleeditor_reload.js \
head.js \
four.html \
head.js \
diff --git a/browser/devtools/styleeditor/test/browser_styleeditor_reload.js b/browser/devtools/styleeditor/test/browser_styleeditor_reload.js
new file mode 100644
index 000000000000..267fbcffeb08
--- /dev/null
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_reload.js
@@ -0,0 +1,99 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
+const NEW_URI = TEST_BASE_HTTPS + "media.html";
+
+const LINE_NO = 5;
+const COL_NO = 3;
+
+let gContentWin;
+let gUI;
+
+function test()
+{
+ waitForExplicitFinish();
+
+ addTabAndOpenStyleEditor(function(panel) {
+ gContentWin = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
+ gUI = panel.UI;
+
+ let count = 0;
+ gUI.on("editor-added", function editorAdded(event, editor) {
+ if (++count == 2) {
+ gUI.off("editor-added", editorAdded);
+ gUI.editors[0].getSourceEditor().then(runTests);
+ }
+ })
+ });
+
+ content.location = TESTCASE_URI;
+}
+
+function runTests()
+{
+ let count = 0;
+ gUI.once("editor-selected", (event, editor) => {
+ editor.getSourceEditor().then(() => {
+ info("selected second editor, about to reload page");
+ reloadPage();
+
+ gUI.on("editor-added", function editorAdded(event, editor) {
+ if (++count == 2) {
+ gUI.off("editor-added", editorAdded);
+ gUI.editors[1].getSourceEditor().then(testRemembered);
+ }
+ })
+ });
+ });
+ gUI.selectStyleSheet(gUI.editors[1].styleSheet.href, LINE_NO, COL_NO);
+}
+
+function testRemembered()
+{
+ is(gUI.selectedEditor, gUI.editors[1], "second editor is selected");
+
+ let {line, col} = gUI.selectedEditor.sourceEditor.getCaretPosition();
+ is(line, LINE_NO, "correct line selected");
+ is(col, COL_NO, "correct column selected");
+
+ testNewPage();
+}
+
+function testNewPage()
+{
+ let count = 0;
+ gUI.on("editor-added", function editorAdded(event, editor) {
+ info("editor added here")
+ if (++count == 2) {
+ gUI.off("editor-added", editorAdded);
+ gUI.editors[0].getSourceEditor().then(testNotRemembered);
+ }
+ })
+
+ info("navigating to a different page");
+ navigatePage();
+}
+
+function testNotRemembered()
+{
+ is(gUI.selectedEditor, gUI.editors[0], "first editor is selected");
+
+ let {line, col} = gUI.selectedEditor.sourceEditor.getCaretPosition();
+ is(line, 0, "first line is selected");
+ is(col, 0, "first column is selected");
+
+ gUI = null;
+ finish();
+}
+
+function reloadPage()
+{
+ gContentWin.location.reload();
+}
+
+function navigatePage()
+{
+ gContentWin.location = NEW_URI;
+}
\ No newline at end of file
diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js
index 42524a7c1909..893401be63a3 100644
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js
@@ -8,7 +8,7 @@
// Tests that the Web Console CSP messages are displayed
const TEST_VIOLATION = "https://example.com/browser/browser/devtools/webconsole/test/test_bug_770099_violation.html";
-const CSP_VIOLATION_MSG = "CSP WARN: Directive default-src https://example.com:443 violated by http://some.example.com/test.png"
+const CSP_VIOLATION_MSG = "Content Security Policy: Directive default-src https://example.com:443 violated by http://some.example.com/test.png"
let hud = undefined;
diff --git a/browser/fuel/src/Makefile.in b/browser/fuel/src/Makefile.in
index 8166aedd9f31..79b5c91a1e7f 100644
--- a/browser/fuel/src/Makefile.in
+++ b/browser/fuel/src/Makefile.in
@@ -10,6 +10,6 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DISABLED_EXTRA_COMPONENTS = fuelApplication.manifest
-EXTRA_PP_COMPONENTS = fuelApplication.js
+DISABLED_EXTRA_PP_COMPONENTS = fuelApplication.js
include $(topsrcdir)/config/rules.mk
diff --git a/browser/fuel/src/moz.build b/browser/fuel/src/moz.build
index d7f2cd6af472..1fc5a0135ddc 100644
--- a/browser/fuel/src/moz.build
+++ b/browser/fuel/src/moz.build
@@ -9,3 +9,7 @@ MODULE = 'fuel'
EXTRA_COMPONENTS += [
'fuelApplication.manifest',
]
+
+EXTRA_PP_COMPONENTS += [
+ 'fuelApplication.js',
+]
diff --git a/browser/metro/base/content/contenthandlers/Content.js b/browser/metro/base/content/contenthandlers/Content.js
index e7948ba921c2..53c63d184379 100644
--- a/browser/metro/base/content/contenthandlers/Content.js
+++ b/browser/metro/base/content/contenthandlers/Content.js
@@ -143,7 +143,7 @@ let Content = {
// pages have any privilege themselves.
addEventListener("click", this, false);
- docShell.QueryInterface(Ci.nsIDocShellHistory).useGlobalHistory = true;
+ docShell.useGlobalHistory = true;
},
/*******************************************
diff --git a/browser/metro/components/Makefile.in b/browser/metro/components/Makefile.in
index 4e89f862bdf1..667adf897778 100644
--- a/browser/metro/components/Makefile.in
+++ b/browser/metro/components/Makefile.in
@@ -11,7 +11,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/config.mk
# metro/components.manifest
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
components.manifest \
AboutRedirector.js \
BrowserCLH.js \
diff --git a/browser/metro/components/moz.build b/browser/metro/components/moz.build
index 26492f18f30a..f83a3d104da4 100644
--- a/browser/metro/components/moz.build
+++ b/browser/metro/components/moz.build
@@ -10,3 +10,14 @@ XPIDL_SOURCES += [
MODULE = 'components'
+# metro/components.manifest
+EXTRA_PP_COMPONENTS += [
+ 'AboutRedirector.js',
+ 'BrowserCLH.js',
+ 'BrowserStartup.js',
+ 'DirectoryProvider.js',
+ 'HelperAppDialog.js',
+ 'SessionStore.js',
+ 'Sidebar.js',
+ 'components.manifest',
+]
diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp
index 92a7f03c8737..9e7d704cf472 100644
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2090,7 +2090,7 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JS::Handle aObj,
// Note: jsClass is set before this loop, and also at the
// *end* of this loop.
- if (IS_WRAPPER_CLASS(jsClass)) {
+ if (IS_WN_CLASS(jsClass)) {
result = nsXPConnect::XPConnect()->GetPrincipal(obj,
aAllowShortCircuit);
if (result) {
diff --git a/config/makefiles/debugmake.mk b/config/makefiles/debugmake.mk
index dd21734003e7..6e193947e4da 100644
--- a/config/makefiles/debugmake.mk
+++ b/config/makefiles/debugmake.mk
@@ -50,7 +50,6 @@ ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $
@echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
@echo "STATIC_LIBS = $(STATIC_LIBS)"
@echo "SHARED_LIBS = $(SHARED_LIBS)"
- @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)"
@echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)"
@echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)"
@echo --------------------------------------------------------------------------------
diff --git a/config/rules.mk b/config/rules.mk
index 42ecc25f2ee7..ec293c3cc8fc 100644
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -110,10 +110,6 @@ endif # ifndef .PYMAKE
_VPATH_SRCS = $(abspath $<)
-ifdef EXTRA_DSO_LIBS
-EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
-endif
-
################################################################################
# Testing frameworks support
################################################################################
diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
index 710c0ba465ec..3b130e2ffb60 100644
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -766,7 +766,9 @@ public:
* Get this document's inline style sheet. May return null if there
* isn't one
*/
- virtual nsHTMLCSSStyleSheet* GetInlineStyleSheet() const = 0;
+ nsHTMLCSSStyleSheet* GetInlineStyleSheet() const {
+ return mStyleAttrStyleSheet;
+ }
/**
* Get/set the object from which a document can get a script context
@@ -2178,6 +2180,7 @@ protected:
nsRefPtr mCSSLoader;
nsRefPtr mStyleImageLoader;
nsRefPtr mAttrStyleSheet;
+ nsRefPtr mStyleAttrStyleSheet;
// The set of all object, embed, applet, video and audio elements for
// which this is the owner document. (They might not be in the document.)
diff --git a/content/base/src/CSPUtils.jsm b/content/base/src/CSPUtils.jsm
index dcc3afb5c112..9d17d5de7bdb 100644
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -13,6 +13,9 @@
const Cu = Components.utils;
const Ci = Components.interfaces;
+const WARN_FLAG = Ci.nsIScriptError.warningFlag;
+const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG;
+
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@@ -842,7 +845,7 @@ CSPRep.prototype = {
// However, our original CSP implementation required a default src
// or an allow directive.
if (!defaultSrcDir && !this._specCompliant) {
- this.warn(CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
+ this.log(WARN_FLAG, CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
return false;
}
@@ -888,7 +891,9 @@ CSPRep.prototype = {
},
/**
- * Sends a warning message to the error console and web developer console.
+ * Sends a message to the error console and web developer console.
+ * @param aFlag
+ * The nsIScriptError flag constant indicating severity
* @param aMsg
* The message to send
* @param aSource (optional)
@@ -898,50 +903,25 @@ CSPRep.prototype = {
* @param aLineNum (optional)
* The number of the line where the error occurred
*/
- warn:
- function cspd_warn(aMsg, aSource, aScriptLine, aLineNum) {
- var textMessage = 'CSP WARN: ' + aMsg + "\n";
-
+ log:
+ function cspd_log(aFlag, aMsg, aSource, aScriptLine, aLineNum) {
+ var textMessage = "Content Security Policy: " + aMsg;
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
.createInstance(Ci.nsIScriptError);
if (this._innerWindowID) {
consoleMsg.initWithWindowID(textMessage, aSource, aScriptLine, aLineNum,
- 0, Ci.nsIScriptError.warningFlag,
- "Content Security Policy",
+ 0, aFlag,
+ "CSP",
this._innerWindowID);
} else {
consoleMsg.init(textMessage, aSource, aScriptLine, aLineNum, 0,
- Ci.nsIScriptError.warningFlag,
- "Content Security Policy");
+ aFlag,
+ "CSP");
}
Components.classes["@mozilla.org/consoleservice;1"]
.getService(Ci.nsIConsoleService).logMessage(consoleMsg);
},
- /**
- * Sends an error message to the error console and web developer console.
- * @param aMsg
- * The message to send
- */
- error:
- function cspsd_error(aMsg) {
- var textMessage = 'CSP ERROR: ' + aMsg + "\n";
-
- var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
- .createInstance(Ci.nsIScriptError);
- if (this._innerWindowID) {
- consoleMsg.initWithWindowID(textMessage, null, null, 0, 0,
- Ci.nsIScriptError.errorFlag,
- "Content Security Policy",
- this._innerWindowID);
- }
- else {
- consoleMsg.init(textMessage, null, null, 0, 0,
- Ci.nsIScriptError.errorFlag, "Content Security Policy");
- }
- Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Ci.nsIConsoleService).logMessage(consoleMsg);
- },
};
//////////////////////////////////////////////////////////////////////
@@ -1967,17 +1947,17 @@ function innerWindowFromRequest(docRequest) {
function cspError(aCSPRep, aMessage) {
if (aCSPRep) {
- aCSPRep.error(aMessage);
+ aCSPRep.log(ERROR_FLAG, aMessage);
} else {
- (new CSPRep()).error(aMessage);
+ (new CSPRep()).log(ERROR_FLAG, aMessage);
}
}
function cspWarn(aCSPRep, aMessage) {
if (aCSPRep) {
- aCSPRep.warn(aMessage);
+ aCSPRep.log(WARN_FLAG, aMessage);
} else {
- (new CSPRep()).warn(aMessage);
+ (new CSPRep()).log(WARN_FLAG, aMessage);
}
}
diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in
index eb061b5b48e2..7ddedb42f8ce 100644
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -34,7 +34,7 @@ EXTRA_COMPONENTS = \
messageWakeupService.manifest \
$(NULL)
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
contentSecurityPolicy.js \
$(NULL)
diff --git a/content/base/src/contentSecurityPolicy.js b/content/base/src/contentSecurityPolicy.js
index f3054742edc1..400d408aeabc 100644
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -25,6 +25,9 @@ const CSP_VIOLATION_TOPIC = "csp-on-violate-policy";
const CSP_TYPE_XMLHTTPREQUEST_SPEC_COMPLIANT = "csp_type_xmlhttprequest_spec_compliant";
const CSP_TYPE_WEBSOCKET_SPEC_COMPLIANT = "csp_type_websocket_spec_compliant";
+const WARN_FLAG = Ci.nsIScriptError.warningFlag;
+const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG;
+
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/CSPUtils.jsm");
@@ -180,13 +183,13 @@ ContentSecurityPolicy.prototype = {
break;
case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT:
if (!this._policy.allowsInlineScripts)
- this._asyncReportViolation('self',null,'inline script base restriction',
+ this._asyncReportViolation('self', null, 'inline script base restriction',
'violated base restriction: Inline Scripts will not execute',
aSourceFile, aScriptSample, aLineNum);
break;
case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL:
if (!this._policy.allowsEvalInScripts)
- this._asyncReportViolation('self',null,'eval script base restriction',
+ this._asyncReportViolation('self', null, 'eval script base restriction',
'violated base restriction: Code will not be created from strings',
aSourceFile, aScriptSample, aLineNum);
break;
@@ -360,7 +363,7 @@ ContentSecurityPolicy.prototype = {
} else {
violationMessage = CSPLocalizer.getFormatStr("directiveViolated", [violatedDirective]);
}
- this._policy.warn(violationMessage,
+ this._policy.log(WARN_FLAG, violationMessage,
(aSourceFile) ? aSourceFile : null,
(aScriptSample) ? decodeURIComponent(aScriptSample) : null,
(aLineNum) ? aLineNum : null);
@@ -425,8 +428,8 @@ ContentSecurityPolicy.prototype = {
} catch(e) {
// it's possible that the URI was invalid, just log a
// warning and skip over that.
- this._policy.warn(CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]]));
- this._policy.warn(CSPLocalizer.getFormatStr("errorWas", [e.toString()]));
+ this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]]));
+ this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("errorWas", [e.toString()]));
}
}
}
@@ -663,7 +666,7 @@ CSPReportRedirectSink.prototype = {
// nsIChannelEventSink
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
flags, callback) {
- this._policy.warn(CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec]));
+ this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec]));
// cancel the old channel so XHR failure callback happens
oldChannel.cancel(Cr.NS_ERROR_ABORT);
diff --git a/content/base/src/moz.build b/content/base/src/moz.build
index 383955bcde61..277a6e2203d8 100644
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -153,3 +153,6 @@ CPP_SOURCES += [
'nsXMLNameSpaceMap.cpp',
]
+EXTRA_PP_COMPONENTS += [
+ 'contentSecurityPolicy.js',
+]
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
index 4184ba13ba47..713bd60cbaa5 100644
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1478,8 +1478,6 @@ nsDocument::~nsDocument()
if (mAttrStyleSheet) {
mAttrStyleSheet->SetOwningDocument(nullptr);
}
- if (mStyleAttrStyleSheet)
- mStyleAttrStyleSheet->SetOwningDocument(nullptr);
if (mListenerManager) {
mListenerManager->Disconnect();
@@ -1539,7 +1537,6 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers)
- NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocumentRegister)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
NS_INTERFACE_TABLE_END
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
@@ -2234,37 +2231,16 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
// Now reset our inline style and attribute sheets.
if (mAttrStyleSheet) {
- // Remove this sheet from all style sets
- nsCOMPtr shell = GetShell();
- if (shell) {
- shell->StyleSet()->RemoveStyleSheet(nsStyleSet::ePresHintSheet,
- mAttrStyleSheet);
- }
- mAttrStyleSheet->Reset(aURI);
+ mAttrStyleSheet->Reset();
+ mAttrStyleSheet->SetOwningDocument(this);
} else {
- mAttrStyleSheet = new nsHTMLStyleSheet(aURI, this);
+ mAttrStyleSheet = new nsHTMLStyleSheet(this);
}
- // Don't use AddStyleSheet, since it'll put the sheet into style
- // sets in the document level, which is not desirable here.
- mAttrStyleSheet->SetOwningDocument(this);
-
- if (mStyleAttrStyleSheet) {
- // Remove this sheet from all style sets
- nsCOMPtr shell = GetShell();
- if (shell) {
- shell->StyleSet()->
- RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet);
- }
- mStyleAttrStyleSheet->Reset(aURI);
- } else {
- mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet(aURI, this);
+ if (!mStyleAttrStyleSheet) {
+ mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet();
}
- // The loop over style sets below will handle putting this sheet
- // into style sets as needed.
- mStyleAttrStyleSheet->SetOwningDocument(this);
-
// Now set up our style sets
nsCOMPtr shell = GetShell();
if (shell) {
@@ -2295,19 +2271,13 @@ void
nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
{
NS_PRECONDITION(aStyleSet, "Must have a style set");
- NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::ePresHintSheet) == 0,
- "Style set already has a preshint sheet?");
NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eDocSheet) == 0,
"Style set already has document sheets?");
- NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eStyleAttrSheet) == 0,
- "Style set already has style attr sheets?");
- NS_PRECONDITION(mStyleAttrStyleSheet, "No style attr stylesheet?");
- NS_PRECONDITION(mAttrStyleSheet, "No attr stylesheet?");
- aStyleSet->AppendStyleSheet(nsStyleSet::ePresHintSheet, mAttrStyleSheet);
-
- aStyleSet->AppendStyleSheet(nsStyleSet::eStyleAttrSheet,
- mStyleAttrStyleSheet);
+ // We could consider moving this to nsStyleSet::Init, to match its
+ // handling of the eAnimationSheet and eTransitionSheet levels.
+ aStyleSet->DirtyRuleProcessors(nsStyleSet::ePresHintSheet);
+ aStyleSet->DirtyRuleProcessors(nsStyleSet::eStyleAttrSheet);
int32_t i;
for (i = mStyleSheets.Count() - 1; i >= 0; --i) {
@@ -5104,32 +5074,6 @@ nsDocument::RegisterEnabled()
return sPrefValue;
}
-NS_IMETHODIMP
-nsDocument::Register(const nsAString& aName, const JS::Value& aOptions,
- JSContext* aCx, uint8_t aOptionalArgc,
- jsval* aConstructor /* out param */)
-{
- RootedDictionary options(aCx);
- if (aOptionalArgc > 0) {
- JSAutoCompartment ac(aCx, GetWrapper());
- JS::Rooted opts(aCx, aOptions);
- NS_ENSURE_TRUE(JS_WrapValue(aCx, opts.address()),
- NS_ERROR_UNEXPECTED);
- NS_ENSURE_TRUE(options.Init(aCx, opts),
- NS_ERROR_UNEXPECTED);
- }
-
- ErrorResult rv;
- JSObject* object = Register(aCx, aName, options, rv);
- if (rv.Failed()) {
- return rv.ErrorCode();
- }
- NS_ENSURE_TRUE(object, NS_ERROR_UNEXPECTED);
-
- *aConstructor = OBJECT_TO_JSVAL(object);
- return NS_OK;
-}
-
JSObject*
nsDocument::Register(JSContext* aCx, const nsAString& aName,
const ElementRegistrationOptions& aOptions,
diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h
index b7e36e35eab2..293abb01254a 100644
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -60,7 +60,6 @@
#include "nsIProgressEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsIChannelEventSink.h"
-#include "nsIDocumentRegister.h"
#include "imgIRequest.h"
#include "mozilla/dom/DOMImplementation.h"
#include "nsIDOMTouchEvent.h"
@@ -505,7 +504,6 @@ class nsDocument : public nsIDocument,
public nsStubMutationObserver,
public nsIDOMDocumentTouch,
public nsIInlineEventHandlers,
- public nsIDocumentRegister,
public nsIObserver
{
public:
@@ -641,14 +639,6 @@ public:
return mChannel;
}
- /**
- * Get this document's inline style sheet. May return null if there
- * isn't one
- */
- virtual nsHTMLCSSStyleSheet* GetInlineStyleSheet() const MOZ_OVERRIDE {
- return mStyleAttrStyleSheet;
- }
-
/**
* Set the object from which a document can get a script context.
* This is the context within which all scripts (during document
@@ -804,9 +794,6 @@ public:
// nsIInlineEventHandlers
NS_DECL_NSIINLINEEVENTHANDLERS
- // nsIDocumentRegister
- NS_DECL_NSIDOCUMENTREGISTER
-
// nsIObserver
NS_DECL_NSIOBSERVER
@@ -1308,7 +1295,6 @@ protected:
// The channel that got passed to StartDocumentLoad(), if any
nsCOMPtr mChannel;
- nsRefPtr mStyleAttrStyleSheet;
// A document "without a browsing context" that owns the content of
// HTMLTemplateElement.
diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp
index ba7bcd514406..15d926a034d4 100644
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -401,13 +401,6 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
AutoJSContext cx;
nsresult rv;
- JS::RootedObject wrapper(cx);
- bool isDOMBinding;
- if (aReparentScope && (wrapper = aNode->GetWrapper()) &&
- !(isDOMBinding = IsDOMObject(wrapper))) {
- rv = xpc_MorphSlimWrapper(cx, aNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager;
@@ -523,19 +516,22 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
elem->RecompileScriptEventListeners();
}
- if (aReparentScope && wrapper) {
- if (isDOMBinding) {
- rv = ReparentWrapper(cx, wrapper);
- } else {
- nsIXPConnect *xpc = nsContentUtils::XPConnect();
- if (xpc) {
- rv = xpc->ReparentWrappedNativeIfFound(cx, wrapper, aReparentScope, aNode);
+ if (aReparentScope) {
+ JS::Rooted wrapper(cx);
+ if ((wrapper = aNode->GetWrapper())) {
+ if (IsDOMObject(wrapper)) {
+ rv = ReparentWrapper(cx, wrapper);
+ } else {
+ nsIXPConnect *xpc = nsContentUtils::XPConnect();
+ if (xpc) {
+ rv = xpc->ReparentWrappedNativeIfFound(cx, wrapper, aReparentScope, aNode);
+ }
}
- }
- if (NS_FAILED(rv)) {
- aNode->mNodeInfo.swap(nodeInfo);
+ if (NS_FAILED(rv)) {
+ aNode->mNodeInfo.swap(nodeInfo);
- return rv;
+ return rv;
+ }
}
}
}
diff --git a/content/events/public/nsIEventListenerService.idl b/content/events/public/nsIEventListenerService.idl
index 744f509040c8..f9277b030aa6 100644
--- a/content/events/public/nsIEventListenerService.idl
+++ b/content/events/public/nsIEventListenerService.idl
@@ -16,6 +16,7 @@ interface nsIEventListenerInfo : nsISupports
{
/**
* The type of the event for which the listener was added.
+ * Null if the listener is for all the events.
*/
readonly attribute AString type;
readonly attribute boolean capturing;
diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp
index 06b7febebd92..b0dbfa13ec60 100644
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -1167,8 +1167,12 @@ nsEventListenerManager::GetListenerInfo(nsCOMArray* aList)
CompileEventHandlerInternal(const_cast(&ls),
true, nullptr);
}
- const nsDependentSubstring& eventType =
- Substring(nsDependentAtomString(ls.mTypeAtom), 2);
+ nsAutoString eventType;
+ if (ls.mAllEvents) {
+ eventType.SetIsVoid(true);
+ } else {
+ eventType.Assign(Substring(nsDependentAtomString(ls.mTypeAtom), 2));
+ }
// EventListenerInfo is defined in XPCOM, so we have to go ahead
// and convert to an XPCOM callback here...
nsRefPtr info =
diff --git a/content/events/test/test_bug448602.html b/content/events/test/test_bug448602.html
index 2878a92a8c88..9b4e2560782c 100644
--- a/content/events/test/test_bug448602.html
+++ b/content/events/test/test_bug448602.html
@@ -184,6 +184,15 @@ function testAllListener() {
}
els.addListenerForAllEvents(root, allListener, false, true);
+ var infos = els.getListenerInfoFor(root);
+ var nullTypes = 0;
+ for (var i = 0; i < infos.length; ++i) {
+ if (infos[i].type == null) {
+ ++nullTypes;
+ }
+ }
+ is(nullTypes, 1, "Should have one all-event-listener!");
+
els.addListenerForAllEvents(root, allListener, false, true, true);
els.addListenerForAllEvents(root, allListenerTrustedOnly, false, false, true);
l3.dispatchEvent(new Event("testevent", { bubbles: true }));
diff --git a/content/html/content/src/HTMLTrackElement.cpp b/content/html/content/src/HTMLTrackElement.cpp
index f848ae4e75ed..580b36f82ad5 100644
--- a/content/html/content/src/HTMLTrackElement.cpp
+++ b/content/html/content/src/HTMLTrackElement.cpp
@@ -94,7 +94,8 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_4(HTMLTrackElement, nsGenericHTMLElement,
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTrackElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement)
-NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
+ NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+NS_ELEMENT_INTERFACE_MAP_END
void
HTMLTrackElement::OnChannelRedirect(nsIChannel* aChannel,
diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h
index 364e4173db43..f88b6a5e8e49 100644
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -44,7 +44,7 @@ public:
~nsHTMLDocument();
virtual nsresult Init() MOZ_OVERRIDE;
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsHTMLDocument,
nsDocument)
diff --git a/content/media/AudioSegment.cpp b/content/media/AudioSegment.cpp
index 7ccce0d8138d..03e6d5691b5e 100644
--- a/content/media/AudioSegment.cpp
+++ b/content/media/AudioSegment.cpp
@@ -171,7 +171,7 @@ AudioSegment::WriteTo(AudioStream* aOutput)
if (channelData.Length() > outputChannels) {
// Down-mix.
DownmixAndInterleave(channelData, c.mBufferFormat, duration,
- c.mVolume, channelData.Length(), buf.Elements());
+ c.mVolume, outputChannels, buf.Elements());
} else {
InterleaveAndConvertBuffer(channelData.Elements(), c.mBufferFormat,
duration, c.mVolume,
diff --git a/content/media/AudioSegment.h b/content/media/AudioSegment.h
index 3ff5b70f326c..7000dc82f2bb 100644
--- a/content/media/AudioSegment.h
+++ b/content/media/AudioSegment.h
@@ -30,9 +30,11 @@ void InterleaveAndConvertBuffer(const void** aSourceChannels,
int32_t aLength, float aVolume,
int32_t aChannels,
AudioDataValue* aOutput);
+
/**
- * Down-mix audio channels, and interleave the channel data. A total of
- * aOutputChannels*aDuration interleaved samples will be stored into aOutput.
+ * Given an array of input channels (aChannelData), downmix to aOutputChannels,
+ * interleave the channel data. A total of aOutputChannels*aDuration
+ * interleaved samples will be copied to a channel buffer in aOutput.
*/
void DownmixAndInterleave(const nsTArray& aChannelData,
AudioSampleFormat aSourceFormat, int32_t aDuration,
diff --git a/content/media/WebVTTLoadListener.cpp b/content/media/WebVTTLoadListener.cpp
index 7d652092b88e..a754b1b079a1 100644
--- a/content/media/WebVTTLoadListener.cpp
+++ b/content/media/WebVTTLoadListener.cpp
@@ -73,6 +73,7 @@ WebVTTLoadListener::LoadResource()
mParser.own(parser);
NS_ENSURE_TRUE(mParser != nullptr, NS_ERROR_FAILURE);
+ mElement->mReadyState = HTMLTrackElement::LOADING;
return NS_OK;
}
@@ -89,6 +90,9 @@ WebVTTLoadListener::OnStopRequest(nsIRequest* aRequest,
nsresult aStatus)
{
webvtt_finish_parsing(mParser);
+ if(mElement->mReadyState != HTMLTrackElement::ERROR) {
+ mElement->mReadyState = HTMLTrackElement::LOADED;
+ }
return NS_OK;
}
@@ -227,6 +231,11 @@ WebVTTLoadListener::OnReportError(uint32_t aLine, uint32_t aCol,
#endif
switch(aError) {
+ // Non-recoverable errors require us to abort parsing:
+ case WEBVTT_MALFORMED_TAG:
+ mElement->mReadyState = HTMLTrackElement::ERROR;
+ return -1;
+
// Errors which should result in dropped cues
// if the return value is negative:
case WEBVTT_MALFORMED_TIMESTAMP:
diff --git a/content/media/test/crashtests/882956.html b/content/media/test/crashtests/882956.html
new file mode 100644
index 000000000000..ae7b441f9993
--- /dev/null
+++ b/content/media/test/crashtests/882956.html
@@ -0,0 +1,15 @@
+
diff --git a/content/media/test/crashtests/crashtests.list b/content/media/test/crashtests/crashtests.list
index 95a9a9350263..3ea3632778c4 100644
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -46,3 +46,4 @@ load 880384.html
load 880404.html
load 880724.html
load 881775.html
+load 882956.html
diff --git a/dom/apps/src/Makefile.in b/dom/apps/src/Makefile.in
index 39932ebd73c6..7f2b9d5f2a12 100644
--- a/dom/apps/src/Makefile.in
+++ b/dom/apps/src/Makefile.in
@@ -15,7 +15,7 @@ DISABLED_EXTRA_COMPONENTS = \
Webapps.manifest \
$(NULL)
-EXTRA_PP_COMPONENTS = \
+DISABLED_EXTRA_PP_COMPONENTS = \
Webapps.js \
$(NULL)
diff --git a/dom/apps/src/moz.build b/dom/apps/src/moz.build
index 735d90b1705f..c8b90539372e 100644
--- a/dom/apps/src/moz.build
+++ b/dom/apps/src/moz.build
@@ -10,6 +10,10 @@ EXTRA_COMPONENTS += [
'Webapps.manifest',
]
+EXTRA_PP_COMPONENTS += [
+ 'Webapps.js',
+]
+
EXTRA_JS_MODULES += [
'AppDownloadManager.jsm',
'AppsServiceChild.jsm',
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index dca001c3c7f3..d6cc34708dd5 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -4259,7 +4259,7 @@ LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
{
// This function duplicates some of the logic in XPC_WN_HelperSetProperty
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
- if (!IS_WN_WRAPPER(obj))
+ if (!IS_WN_REFLECTOR(obj))
return NS_ERROR_XPC_BAD_CONVERT_JS;
XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
@@ -5099,8 +5099,7 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *aGlobalObj,
nsresult rv = WrapNativeParent(cx, globalObj, native_parent, parentObj);
NS_ENSURE_SUCCESS(rv, rv);
- return node->ChromeOnlyAccess() ?
- NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
+ return node->ChromeOnlyAccess() ? NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
}
NS_IMETHODIMP
@@ -5261,8 +5260,7 @@ nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
if (element->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) &&
doc->BindingManager()->GetBinding(element)) {
- // Don't allow slim wrappers.
- return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv;
+ return rv;
}
mozilla::css::URLValue *bindingURL;
@@ -5276,7 +5274,7 @@ nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
element->SetFlags(NODE_ATTACH_BINDING_ON_POSTCREATE);
- return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv;
+ return rv;
}
NS_IMETHODIMP
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 25fa820284ef..aab790d2a780 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -535,29 +535,24 @@ MaybeWrapValue(JSContext* cx, JS::MutableHandle rval)
return true;
}
- if (rval.isObject()) {
- JSObject* obj = &rval.toObject();
- if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
- return JS_WrapValue(cx, rval.address());
- }
-
- // We're same-compartment, but even then we might need to wrap
- // objects specially. Check for that.
- if (GetSameCompartmentWrapperForDOMBinding(obj)) {
- // We're a new-binding object, and "obj" now points to the right thing
- rval.set(JS::ObjectValue(*obj));
- return true;
- }
-
- if (!IS_SLIM_WRAPPER(obj)) {
- // We might need a SOW
- return JS_WrapValue(cx, rval.address());
- }
-
- // Fall through to returning true
+ if (!rval.isObject()) {
+ return true;
}
- return true;
+ JSObject* obj = &rval.toObject();
+ if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
+ return JS_WrapValue(cx, rval.address());
+ }
+
+ // We're same-compartment, but even then we might need to wrap
+ // objects specially. Check for that.
+ if (GetSameCompartmentWrapperForDOMBinding(obj)) {
+ // We're a new-binding object, and "obj" now points to the right thing
+ rval.set(JS::ObjectValue(*obj));
+ return true;
+ }
+
+ return JS_WrapValue(cx, rval.address());
}
static inline void
@@ -642,7 +637,7 @@ WrapNewBindingObject(JSContext* cx, JS::Handle scope, T* value,
}
rval.set(JS::ObjectValue(*obj));
- return (sameCompartment && IS_SLIM_WRAPPER(obj)) || JS_WrapValue(cx, rval.address());
+ return JS_WrapValue(cx, rval.address());
}
// Create a JSObject wrapping "value", for cases when "value" is a
diff --git a/dom/interfaces/core/moz.build b/dom/interfaces/core/moz.build
index 1c185e57de13..10f6ed014322 100644
--- a/dom/interfaces/core/moz.build
+++ b/dom/interfaces/core/moz.build
@@ -25,7 +25,6 @@ XPIDL_SOURCES += [
'nsIDOMText.idl',
'nsIDOMUserDataHandler.idl',
'nsIDOMXMLDocument.idl',
- 'nsIDocumentRegister.idl',
'nsIInlineEventHandlers.idl',
]
diff --git a/dom/interfaces/core/nsIDocumentRegister.idl b/dom/interfaces/core/nsIDocumentRegister.idl
deleted file mode 100644
index 701eb9936ba5..000000000000
--- a/dom/interfaces/core/nsIDocumentRegister.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(e35935bd-ebae-4e0d-93bf-efa93ab14c05)]
-interface nsIDocumentRegister : nsISupports
-{
- [optional_argc,
- implicit_jscontext] jsval register(in DOMString name,
- [optional] in jsval options)
- raises(DOMException);
-};
-
diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp
index 6baf9d331860..da3d31c9a897 100644
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -348,11 +348,10 @@ TabChild::Observe(nsISupports *aSubject,
// the top-left of the page.
mLastMetrics.mZoom = gfxSize(1.0, 1.0);
mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
- // I don't know what units mInnerSize is in, hence FromUnknownRect
- mLastMetrics.mCompositionBounds = LayerIntRect::FromUnknownRect(
- gfx::IntRect(0, 0, mInnerSize.width, mInnerSize.height));
- mLastMetrics.mResolution =
+ mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
+ CSSToScreenScale resolution =
AsyncPanZoomController::CalculateResolution(mLastMetrics);
+ mLastMetrics.mResolution = gfxSize(resolution.scale, resolution.scale);
mLastMetrics.mScrollOffset = CSSPoint(0, 0);
utils->SetResolution(mLastMetrics.mResolution.width,
mLastMetrics.mResolution.height);
@@ -590,9 +589,7 @@ TabChild::HandlePossibleViewportChange()
FrameMetrics metrics(mLastMetrics);
metrics.mViewport = CSSRect(CSSPoint(), viewport);
metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
- // I don't know what units mInnerSize is in, hence FromUnknownRect
- metrics.mCompositionBounds = LayerIntRect::FromUnknownRect(
- gfx::IntRect(0, 0, mInnerSize.width, mInnerSize.height));
+ metrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
// Changing the zoom when we're not doing a first paint will get ignored
// by AsyncPanZoomController and causes a blurry flash.
@@ -623,14 +620,13 @@ TabChild::HandlePossibleViewportChange()
// new CSS viewport, so we know that there's no velocity, acceleration, and
// we have no idea how long painting will take.
metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0);
- gfxSize resolution = AsyncPanZoomController::CalculateResolution(metrics);
+ CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(metrics);
// XXX is this actually hysteresis? This calculation is not well
// understood. It's taken from the previous JS implementation.
gfxFloat hysteresis/*?*/ =
gfxFloat(oldBrowserWidth) / gfxFloat(oldScreenWidth);
- resolution.width *= hysteresis;
- resolution.height *= hysteresis;
- metrics.mResolution = resolution;
+ metrics.mResolution = gfxSize(resolution.scale * hysteresis,
+ resolution.scale * hysteresis);
utils->SetResolution(metrics.mResolution.width, metrics.mResolution.height);
// Force a repaint with these metrics. This, among other things, sets the
@@ -1413,7 +1409,8 @@ TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const
mOuterRect.height = rect.height;
mOrientation = orientation;
- mInnerSize = size;
+ mInnerSize = ScreenIntSize::FromUnknownSize(
+ gfx::IntSize(size.width, size.height));
mWidget->Resize(0, 0, size.width, size.height,
true);
@@ -1530,9 +1527,9 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
utils->SetScrollPositionClampingScrollPortSize(
cssCompositedRect.width, cssCompositedRect.height);
ScrollWindowTo(window, aFrameMetrics.mScrollOffset);
- gfxSize resolution = AsyncPanZoomController::CalculateResolution(
+ CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(
aFrameMetrics);
- utils->SetResolution(resolution.width, resolution.height);
+ utils->SetResolution(resolution.scale, resolution.scale);
nsCOMPtr domDoc;
nsCOMPtr docElement;
diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h
index 6f300e5429cb..5b50a5fdc7b1 100644
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -441,7 +441,7 @@ private:
nsRefPtr mTabChildGlobal;
uint32_t mChromeFlags;
nsIntRect mOuterRect;
- nsIntSize mInnerSize;
+ ScreenIntSize mInnerSize;
// When we're tracking a possible tap gesture, this is the "down"
// point of the touchstart.
nsIntPoint mGestureDownPoint;
diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp
index c36e7f22ee89..d9e6dc992bee 100644
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -464,7 +464,8 @@ TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
if (RenderFrameParent* rfp = GetRenderFrame()) {
- rfp->NotifyDimensionsChanged(mDimensions.width, mDimensions.height);
+ rfp->NotifyDimensionsChanged(ScreenIntSize::FromUnknownSize(
+ gfx::IntSize(mDimensions.width, mDimensions.height)));
}
}
}
@@ -1464,7 +1465,8 @@ TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor,
{
RenderFrameParent* rfp = GetRenderFrame();
if (mDimensions != nsIntSize() && rfp) {
- rfp->NotifyDimensionsChanged(mDimensions.width, mDimensions.height);
+ rfp->NotifyDimensionsChanged(ScreenIntSize::FromUnknownSize(
+ gfx::IntSize(mDimensions.width, mDimensions.height)));
}
return true;
diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.cpp b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
index daf0237b381a..ba83a2fa99bc 100644
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1976,18 +1976,23 @@ NS_IMPL_ISUPPORTS1(UpdateCurrentDictionaryCallback, nsIEditorSpellCheckCallback)
NS_IMETHODIMP mozInlineSpellChecker::UpdateCurrentDictionary()
{
- if (!mSpellCheck) {
+ // mSpellCheck is null and mPendingSpellCheck is nonnull while the spell
+ // checker is being initialized. Calling UpdateCurrentDictionary on
+ // mPendingSpellCheck simply queues the dictionary update after the init.
+ nsCOMPtr spellCheck = mSpellCheck ? mSpellCheck :
+ mPendingSpellCheck;
+ if (!spellCheck) {
return NS_OK;
}
- if (NS_FAILED(mSpellCheck->GetCurrentDictionary(mPreviousDictionary))) {
+ if (NS_FAILED(spellCheck->GetCurrentDictionary(mPreviousDictionary))) {
mPreviousDictionary.Truncate();
}
nsRefPtr cb =
new UpdateCurrentDictionaryCallback(this, mDisabledAsyncToken);
NS_ENSURE_STATE(cb);
- nsresult rv = mSpellCheck->UpdateCurrentDictionary(cb);
+ nsresult rv = spellCheck->UpdateCurrentDictionary(cb);
if (NS_FAILED(rv)) {
cb = nullptr;
NS_ENSURE_SUCCESS(rv, rv);
diff --git a/gfx/2d/Point.h b/gfx/2d/Point.h
index ed7f6be5963e..026b44604c49 100644
--- a/gfx/2d/Point.h
+++ b/gfx/2d/Point.h
@@ -61,6 +61,12 @@ struct PointTyped :
};
typedef PointTyped Point;
+template
+IntPointTyped RoundedToInt(const PointTyped& aPoint) {
+ return IntPointTyped(NS_lround(aPoint.x),
+ NS_lround(aPoint.y));
+}
+
template
struct IntSizeTyped :
public BaseSize< int32_t, IntSizeTyped >,
diff --git a/gfx/2d/Rect.h b/gfx/2d/Rect.h
index eb1b01c1219d..2084b394e546 100644
--- a/gfx/2d/Rect.h
+++ b/gfx/2d/Rect.h
@@ -100,6 +100,26 @@ struct RectTyped :
};
typedef RectTyped Rect;
+template
+IntRectTyped RoundedToInt(const RectTyped& aRect)
+{
+ return IntRectTyped(NS_lround(aRect.x),
+ NS_lround(aRect.y),
+ NS_lround(aRect.width),
+ NS_lround(aRect.height));
+}
+
+template
+IntRectTyped RoundedIn(const RectTyped& aRect)
+{
+ RectTyped copy(aRect);
+ copy.RoundIn();
+ return IntRectTyped(int32_t(copy.x),
+ int32_t(copy.y),
+ int32_t(copy.width),
+ int32_t(copy.height));
+}
+
}
}
diff --git a/gfx/2d/ScaleFactor.h b/gfx/2d/ScaleFactor.h
new file mode 100644
index 000000000000..ceef86f51d05
--- /dev/null
+++ b/gfx/2d/ScaleFactor.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_SCALEFACTOR_H_
+#define MOZILLA_GFX_SCALEFACTOR_H_
+
+#include "gfxPoint.h"
+
+namespace mozilla {
+namespace gfx {
+
+/*
+ * This class represents a scaling factor between two different pixel unit
+ * systems. This is effectively a type-safe float, intended to be used in
+ * combination with the known-type instances of gfx::Point, gfx::Rect, etc.
+ *
+ * Note that some parts of the code that pre-date this class used separate
+ * scaling factors for the x and y axes. However, at runtime these values
+ * were always expected to be the same, so this class uses only one scale
+ * factor for both axes. The two constructors that take two-axis scaling
+ * factors check to ensure that this assertion holds.
+ */
+template
+struct ScaleFactor {
+ float scale;
+
+ ScaleFactor() : scale(1.0) {}
+ ScaleFactor(const ScaleFactor& aCopy) : scale(aCopy.scale) {}
+ explicit ScaleFactor(float aScale) : scale(aScale) {}
+
+ explicit ScaleFactor(float aX, float aY) : scale(aX) {
+ MOZ_ASSERT(fabs(aX - aY) < 1e-6);
+ }
+
+ explicit ScaleFactor(gfxSize aScale) : scale(aScale.width) {
+ MOZ_ASSERT(fabs(aScale.width - aScale.height) < 1e-6);
+ }
+
+ ScaleFactor Inverse() {
+ return ScaleFactor(1 / scale);
+ }
+
+ bool operator==(const ScaleFactor& aOther) const {
+ return scale == aOther.scale;
+ }
+
+ bool operator!=(const ScaleFactor& aOther) const {
+ return !(*this == aOther);
+ }
+
+ template
+ ScaleFactor operator/(const ScaleFactor& aOther) const {
+ return ScaleFactor(scale / aOther.scale);
+ }
+
+ template
+ ScaleFactor operator*(const ScaleFactor& aOther) const {
+ return ScaleFactor(scale * aOther.scale);
+ }
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SCALEFACTOR_H_ */
diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build
index 619b738f90fd..35c43ca3774e 100644
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -20,6 +20,7 @@ EXPORTS.mozilla.gfx += [
'Point.h',
'Rect.h',
'Scale.h',
+ 'ScaleFactor.h',
'Tools.h',
'Types.h',
'UserData.h',
diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla
index 525ba23ab56b..33b1ceee35be 100644
--- a/gfx/graphite2/README.mozilla
+++ b/gfx/graphite2/README.mozilla
@@ -1,6 +1,6 @@
This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev
-Current version derived from upstream changeset 09707dd22634
+Current version derived from upstream changeset 6b8ddb7d599f
See gfx/graphite2/moz-gr-update.sh for update procedure.
diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h
index 4c9451eb2679..85ee73d91264 100644
--- a/gfx/graphite2/include/graphite2/Font.h
+++ b/gfx/graphite2/include/graphite2/Font.h
@@ -30,7 +30,7 @@
#define GR2_VERSION_MAJOR 1
#define GR2_VERSION_MINOR 2
-#define GR2_VERSION_BUGFIX 2
+#define GR2_VERSION_BUGFIX 3
#ifdef __cplusplus
extern "C"
diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp
index 743e260d6111..4c139e64f6a5 100644
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -199,7 +199,8 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
return false;
ac_begin = ac_data + be::peek(--o_action);
- rc_begin = *--o_constraint ? rc_data + be::peek(o_constraint) : rc_end;
+ --o_constraint;
+ rc_begin = be::peek(o_constraint) ? rc_data + be::peek(o_constraint) : rc_end;
if (ac_begin > ac_end || ac_begin > ac_data_end || ac_end > ac_data_end
|| rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end)
diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp
index 21618f7e7df3..c6fc2b5679a0 100644
--- a/gfx/graphite2/src/Slot.cpp
+++ b/gfx/graphite2/src/Slot.cpp
@@ -147,7 +147,7 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R
int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
{
Position base;
- Rect bbox = seg->theGlyphBBoxTemporary(gid());
+ Rect bbox = seg->theGlyphBBoxTemporary(glyph());
float clusterMin = 0.;
Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin);
@@ -389,12 +389,13 @@ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
}
}
m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()];
+ const GlyphFace *aGlyph = theGlyph;
if (m_realglyphid)
{
- const GlyphFace *aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid);
- if (aGlyph) theGlyph = aGlyph;
+ aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid);
+ if (!aGlyph) aGlyph = theGlyph;
}
- m_advance = Position(theGlyph->theAdvance().x, 0.);
+ m_advance = Position(aGlyph->theAdvance().x, 0.);
if (seg->silf()->aPassBits())
seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
}
diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp
index 9ede99e91455..ba26946dcc10 100644
--- a/gfx/graphite2/src/TtfUtil.cpp
+++ b/gfx/graphite2/src/TtfUtil.cpp
@@ -954,11 +954,11 @@ gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId,
return (uint16)(idDelta + nUnicodeId); // must use modulus 2^16
// Look up value in glyphIdArray
- size_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) +
- (reinterpret_cast(pMid) - reinterpret_cast(pTable));
- if (offset * 2 >= pTable->length)
+ const ptrdiff_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) +
+ (pMid - reinterpret_cast(pTable));
+ if (offset * 2 >= be::swap(pTable->length))
return 0;
- gid16 nGlyphId = be::peek(pMid + (nUnicodeId - chStart) + (idRangeOffset >> 1));
+ gid16 nGlyphId = be::peek(reinterpret_cast(pTable)+offset);
// If this value is 0, return 0. Else add the idDelta
return nGlyphId ? nGlyphId + idDelta : 0;
}
diff --git a/gfx/graphite2/src/inc/Sparse.h b/gfx/graphite2/src/inc/Sparse.h
index bbe6bcfb95ca..cd685bdcba7b 100644
--- a/gfx/graphite2/src/inc/Sparse.h
+++ b/gfx/graphite2/src/inc/Sparse.h
@@ -106,9 +106,9 @@ sparse::sparse(I attr, const I last)
}
if (m_nchunks == 0) return;
- m_array.values = grzeroalloc((m_nchunks*sizeof(chunk) + sizeof(mapped_type)/2)
+ m_array.values = grzeroalloc((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
/ sizeof(mapped_type)
- + n_values*sizeof(mapped_type));
+ + n_values);
if (m_array.values == 0)
{
diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h
index cb7342ad85b1..24b9e5e6b71c 100644
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -89,9 +89,9 @@ public:
return mResolution * mDevPixelsPerCSSPixel;
}
- gfxPoint GetScrollOffsetInLayerPixels() const
+ gfx::Point GetScrollOffsetInLayerPixels() const
{
- return gfxPoint(
+ return gfx::Point(
static_cast(
mScrollOffset.x * LayersPixelsPerCSSPixel().width),
static_cast(
@@ -118,7 +118,7 @@ public:
//
// This is only valid on the root layer. Nested iframes do not need this
// metric as they do not have a displayport set. See bug 775452.
- LayerIntRect mCompositionBounds;
+ ScreenIntRect mCompositionBounds;
// ---------------------------------------------------------------------------
// The following metrics are all in CSS pixels. They are not in any uniform
diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp
index 1986033c1cca..0ceb44f9d14c 100644
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -395,16 +395,15 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
// This is derived from the code in
// gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
- float devPixelRatioX = 1 / rootTransform.GetXScale();
- float devPixelRatioY = 1 / rootTransform.GetYScale();
+ CSSToLayerScale paintScale = LayerToCSSScale(rootTransform.GetXScale(),
+ rootTransform.GetYScale()).Inverse();
const CSSRect& metricsDisplayPort =
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
- LayerRect displayPort = LayerRect::FromCSSRect(metricsDisplayPort + metrics.mScrollOffset,
- devPixelRatioX, devPixelRatioY);
+ LayerRect displayPort = (metricsDisplayPort + metrics.mScrollOffset) * paintScale;
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
- aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
+ aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical,
aViewport, aScaleX, aScaleY);
}
#endif
diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp
index a74af05b66d6..a85bab189d78 100644
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -342,7 +342,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
LayerComposite* layerComposite = aLayer->AsLayerComposite();
ViewTransform treeTransform;
- gfx::Point scrollOffset;
+ ScreenPoint scrollOffset;
*aWantNextFrame |=
controller->SampleContentTransformForFrame(aCurrentFrame,
container,
@@ -355,7 +355,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
metrics.mDisplayPort : metrics.mCriticalDisplayPort);
gfx::Margin fixedLayerMargins(0, 0, 0, 0);
ScreenPoint offset(0, 0);
- SyncFrameMetrics(scrollOffset, treeTransform.mScale.width, metrics.mScrollableRect,
+ SyncFrameMetrics(scrollOffset, treeTransform.mScale.scale, metrics.mScrollableRect,
mLayersUpdated, displayPort, 1 / rootTransform.GetXScale(),
mIsFirstPaint, fixedLayerMargins, offset);
@@ -381,8 +381,8 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
TransformFixedLayers(
aLayer,
- -treeTransform.mTranslation / treeTransform.mScale,
- treeTransform.mScale,
+ gfxPoint(-treeTransform.mTranslation.x, -treeTransform.mTranslation.y),
+ gfxSize(treeTransform.mScale.scale, treeTransform.mScale.scale),
fixedLayerMargins);
appliedTransform = true;
@@ -404,16 +404,15 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr
gfx3DMatrix treeTransform;
- float layerPixelRatioX = 1 / aRootTransform.GetXScale(),
- layerPixelRatioY = 1 / aRootTransform.GetYScale();
+ CSSToLayerScale geckoZoom = LayerToCSSScale(aRootTransform.GetXScale(),
+ aRootTransform.GetYScale()).Inverse();
- LayerIntPoint scrollOffsetLayerPixels = LayerIntPoint::FromCSSPointRounded(
- metrics.mScrollOffset, layerPixelRatioX, layerPixelRatioY);
+ LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.mScrollOffset * geckoZoom);
if (mIsFirstPaint) {
mContentRect = metrics.mScrollableRect;
SetFirstPaintViewport(scrollOffsetLayerPixels,
- layerPixelRatioX,
+ geckoZoom.scale,
mContentRect);
mIsFirstPaint = false;
} else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) {
@@ -424,20 +423,19 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr
// We synchronise the viewport information with Java after sending the above
// notifications, so that Java can take these into account in its response.
// Calculate the absolute display port to send to Java
- LayerIntRect displayPort =
- LayerIntRect::FromCSSRectRounded(metrics.mCriticalDisplayPort.IsEmpty()
- ? metrics.mDisplayPort
- : metrics.mCriticalDisplayPort,
- layerPixelRatioX, layerPixelRatioY);
+ LayerIntRect displayPort = RoundedToInt(
+ (metrics.mCriticalDisplayPort.IsEmpty()
+ ? metrics.mDisplayPort
+ : metrics.mCriticalDisplayPort
+ ) * geckoZoom);
displayPort += scrollOffsetLayerPixels;
gfx::Margin fixedLayerMargins(0, 0, 0, 0);
ScreenPoint offset(0, 0);
- ScreenPoint scrollOffset(0, 0);
- float scaleX = 1.0,
- scaleY = 1.0;
- SyncViewportInfo(displayPort, layerPixelRatioX, mLayersUpdated,
- scrollOffset, scaleX, scaleY, fixedLayerMargins,
+ ScreenPoint userScroll(0, 0);
+ CSSToScreenScale userZoom;
+ SyncViewportInfo(displayPort, geckoZoom.scale, mLayersUpdated,
+ userScroll, userZoom.scale, userZoom.scale, fixedLayerMargins,
offset);
mLayersUpdated = false;
@@ -447,50 +445,44 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr
// Handle transformations for asynchronous panning and zooming. We determine the
// zoom used by Gecko from the transformation set on the root layer, and we
// determine the scroll offset used by Gecko from the frame metrics of the
- // primary scrollable layer. We compare this to the desired zoom and scroll
+ // primary scrollable layer. We compare this to the user zoom and scroll
// offset in the view transform we obtained from Java in order to compute the
// transformation we need to apply.
- float tempScaleDiffX = aRootTransform.GetXScale() * scaleX;
- float tempScaleDiffY = aRootTransform.GetYScale() * scaleY;
+ LayerToScreenScale zoomAdjust = userZoom / geckoZoom;
- LayerIntPoint metricsScrollOffset(0, 0);
+ LayerIntPoint geckoScroll(0, 0);
if (metrics.IsScrollable()) {
- metricsScrollOffset = scrollOffsetLayerPixels;
+ geckoScroll = scrollOffsetLayerPixels;
}
- nsIntPoint scrollCompensation(
- (scrollOffset.x / tempScaleDiffX - metricsScrollOffset.x) * scaleX,
- (scrollOffset.y / tempScaleDiffY - metricsScrollOffset.y) * scaleY);
- treeTransform = gfx3DMatrix(ViewTransform(-scrollCompensation,
- gfxSize(scaleX, scaleY)));
+ LayerPoint translation = (userScroll / zoomAdjust) - geckoScroll;
+ treeTransform = gfx3DMatrix(ViewTransform(-translation, userZoom));
// Translate fixed position layers so that they stay in the correct position
- // when scrollOffset and metricsScrollOffset differ.
+ // when userScroll and geckoScroll differ.
gfxPoint fixedOffset;
gfxSize scaleDiff;
- LayerRect content = LayerRect::FromCSSRect(mContentRect,
- 1 / aRootTransform.GetXScale(),
- 1 / aRootTransform.GetYScale());
+ LayerRect content = mContentRect * geckoZoom;
// If the contents can fit entirely within the widget area on a particular
// dimension, we need to translate and scale so that the fixed layers remain
// within the page boundaries.
- if (mContentRect.width * scaleX < metrics.mCompositionBounds.width) {
- fixedOffset.x = -metricsScrollOffset.x;
+ if (mContentRect.width * userZoom.scale < metrics.mCompositionBounds.width) {
+ fixedOffset.x = -geckoScroll.x;
scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / content.width);
} else {
- fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, content.x,
- content.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) - metricsScrollOffset.x;
- scaleDiff.width = tempScaleDiffX;
+ fixedOffset.x = clamped(userScroll.x / zoomAdjust.scale, content.x,
+ content.XMost() - metrics.mCompositionBounds.width / zoomAdjust.scale) - geckoScroll.x;
+ scaleDiff.width = zoomAdjust.scale;
}
- if (mContentRect.height * scaleY < metrics.mCompositionBounds.height) {
- fixedOffset.y = -metricsScrollOffset.y;
+ if (mContentRect.height * userZoom.scale < metrics.mCompositionBounds.height) {
+ fixedOffset.y = -geckoScroll.y;
scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / content.height);
} else {
- fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, content.y,
- content.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) - metricsScrollOffset.y;
- scaleDiff.height = tempScaleDiffY;
+ fixedOffset.y = clamped(userScroll.y / zoomAdjust.scale, content.y,
+ content.YMost() - metrics.mCompositionBounds.height / zoomAdjust.scale) - geckoScroll.y;
+ scaleDiff.height = zoomAdjust.scale;
}
// The transform already takes the resolution scale into account. Since we
@@ -588,7 +580,7 @@ AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort,
}
void
-AsyncCompositionManager::SyncFrameMetrics(const gfx::Point& aScrollOffset,
+AsyncCompositionManager::SyncFrameMetrics(const ScreenPoint& aScrollOffset,
float aZoom,
const CSSRect& aCssPageRect,
bool aLayersUpdated,
diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h
index 38889bacc79b..99ec81989a4f 100644
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -27,8 +27,8 @@ class AutoResolveRefLayers;
// Represents (affine) transforms that are calculated from a content view.
struct ViewTransform {
- ViewTransform(gfxPoint aTranslation = gfxPoint(),
- gfxSize aScale = gfxSize(1, 1))
+ ViewTransform(LayerPoint aTranslation = LayerPoint(),
+ CSSToScreenScale aScale = CSSToScreenScale())
: mTranslation(aTranslation)
, mScale(aScale)
{}
@@ -36,12 +36,12 @@ struct ViewTransform {
operator gfx3DMatrix() const
{
return
- gfx3DMatrix::ScalingMatrix(mScale.width, mScale.height, 1) *
- gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0);
+ gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0) *
+ gfx3DMatrix::ScalingMatrix(mScale.scale, mScale.scale, 1);
}
- gfxPoint mTranslation;
- gfxSize mScale;
+ LayerPoint mTranslation;
+ CSSToScreenScale mScale;
};
/**
@@ -125,7 +125,7 @@ private:
float& aScaleX, float& aScaleY,
gfx::Margin& aFixedLayerMargins,
ScreenPoint& aOffset);
- void SyncFrameMetrics(const gfx::Point& aScrollOffset,
+ void SyncFrameMetrics(const ScreenPoint& aScrollOffset,
float aZoom,
const CSSRect& aCssPageRect,
bool aLayersUpdated,
diff --git a/gfx/layers/composite/ThebesLayerComposite.cpp b/gfx/layers/composite/ThebesLayerComposite.cpp
index 2c46046510ef..f91861933b66 100644
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -246,17 +246,15 @@ ThebesLayerComposite::GetCompositionBounds()
// the content resolution.
Layer* rootLayer = Manager()->GetRoot();
const gfx3DMatrix& rootTransform = rootLayer->GetTransform();
- float scaleX = rootTransform.GetXScale();
- float scaleY = rootTransform.GetYScale();
+ LayerToCSSScale scale(rootTransform.GetXScale(),
+ rootTransform.GetYScale());
// Get the content document bounds, in screen-space.
const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
- const LayerIntRect content = LayerIntRect::FromCSSRectRounded(metrics.mScrollableRect,
- 1 / scaleX,
- 1 / scaleY);
+ const LayerIntRect content = RoundedToInt(metrics.mScrollableRect / scale);
gfx::Point scrollOffset =
- gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
- (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
+ gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scale.scale,
+ (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scale.scale);
const nsIntPoint contentOrigin(
content.x - NS_lround(scrollOffset.x),
content.y - NS_lround(scrollOffset.y));
diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp
index 8b8ae99c0e6b..78082d383739 100644
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -208,37 +208,29 @@ AsyncPanZoomController::GetTouchStartTolerance()
return gTouchStartTolerance;
}
-static gfx::Point
-WidgetSpaceToCompensatedViewportSpace(const gfx::Point& aPoint,
- gfxFloat aCurrentZoom)
+static CSSPoint
+WidgetSpaceToCompensatedViewportSpace(const ScreenPoint& aPoint,
+ const CSSToScreenScale& aCurrentZoom)
{
// Transform the input point from local widget space to the content document
// space that the user is seeing, from last composite.
- gfx::Point pt(aPoint);
- pt = pt / aCurrentZoom;
-
// FIXME/bug 775451: this doesn't attempt to compensate for content transforms
// in effect on the compositor. The problem is that it's very hard for us to
// know what content CSS pixel is at widget point 0,0 based on information
// available here. So we use this hacky implementation for now, which works
// in quiescent states.
- return pt;
+ return aPoint / aCurrentZoom;
}
nsEventStatus
AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent,
nsInputEvent* aOutEvent)
{
- gfxFloat currentResolution;
- gfx::Point currentScrollOffset, lastScrollOffset;
+ CSSToScreenScale currentResolution;
{
MonitorAutoLock monitor(mMonitor);
- currentResolution = CalculateResolution(mFrameMetrics).width;
- currentScrollOffset = gfx::Point(mFrameMetrics.mScrollOffset.x,
- mFrameMetrics.mScrollOffset.y);
- lastScrollOffset = gfx::Point(mLastContentPaintMetrics.mScrollOffset.x,
- mLastContentPaintMetrics.mScrollOffset.y);
+ currentResolution = CalculateResolution(mFrameMetrics);
}
nsEventStatus status;
@@ -265,8 +257,9 @@ AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent,
for (uint32_t i = 0; i < touches.Length(); ++i) {
nsIDOMTouch* touch = touches[i];
if (touch) {
- gfx::Point refPoint = WidgetSpaceToCompensatedViewportSpace(
- gfx::Point(touch->mRefPoint.x, touch->mRefPoint.y),
+ CSSPoint refPoint = WidgetSpaceToCompensatedViewportSpace(
+ ScreenPoint::FromUnknownPoint(gfx::Point(
+ touch->mRefPoint.x, touch->mRefPoint.y)),
currentResolution);
touch->mRefPoint = nsIntPoint(refPoint.x, refPoint.y);
}
@@ -274,8 +267,9 @@ AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent,
break;
}
default: {
- gfx::Point refPoint = WidgetSpaceToCompensatedViewportSpace(
- gfx::Point(aOutEvent->refPoint.x, aOutEvent->refPoint.y),
+ CSSPoint refPoint = WidgetSpaceToCompensatedViewportSpace(
+ ScreenPoint::FromUnknownPoint(gfx::Point(
+ aOutEvent->refPoint.x, aOutEvent->refPoint.y)),
currentResolution);
aOutEvent->refPoint = nsIntPoint(refPoint.x, refPoint.y);
break;
@@ -550,13 +544,11 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
{
MonitorAutoLock monitor(mMonitor);
- gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
gfxFloat userZoom = mFrameMetrics.mZoom.width;
ScreenPoint focusPoint = aEvent.mFocusPoint;
- CSSPoint focusChange = ScreenPoint::ToCSSPoint(mLastZoomFocus - focusPoint,
- 1.0 / resolution,
- 1.0 / resolution);
+ CSSPoint focusChange = (mLastZoomFocus - focusPoint) / resolution;
// If displacing by the change in focus point will take us off page bounds,
// then reduce the displacement such that it doesn't.
if (mX.DisplacementWillOverscroll(focusChange.x) != Axis::OVERSCROLL_NONE) {
@@ -653,12 +645,12 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
if (mGeckoContentController) {
MonitorAutoLock monitor(mMonitor);
- gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
- CSSPoint point = CSSPoint::FromUnknownPoint(
- WidgetSpaceToCompensatedViewportSpace(
- gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y),
- resolution));
- mGeckoContentController->HandleLongTap(CSSIntPoint::RoundToInt(point));
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
+ CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
+ ScreenPoint::FromUnknownPoint(gfx::Point(
+ aEvent.mPoint.x, aEvent.mPoint.y)),
+ resolution);
+ mGeckoContentController->HandleLongTap(gfx::RoundedToInt(point));
return nsEventStatus_eConsumeNoDefault;
}
return nsEventStatus_eIgnore;
@@ -672,12 +664,12 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput
if (mGeckoContentController) {
MonitorAutoLock monitor(mMonitor);
- gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
- CSSPoint point = CSSPoint::FromUnknownPoint(
- WidgetSpaceToCompensatedViewportSpace(
- gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y),
- resolution));
- mGeckoContentController->HandleSingleTap(CSSIntPoint::RoundToInt(point));
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
+ CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
+ ScreenPoint::FromUnknownPoint(gfx::Point(
+ aEvent.mPoint.x, aEvent.mPoint.y)),
+ resolution);
+ mGeckoContentController->HandleSingleTap(gfx::RoundedToInt(point));
return nsEventStatus_eConsumeNoDefault;
}
return nsEventStatus_eIgnore;
@@ -688,12 +680,12 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
MonitorAutoLock monitor(mMonitor);
if (mAllowZoom) {
- gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
- CSSPoint point = CSSPoint::FromUnknownPoint(
- WidgetSpaceToCompensatedViewportSpace(
- gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y),
- resolution));
- mGeckoContentController->HandleDoubleTap(CSSIntPoint::RoundToInt(point));
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
+ CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
+ ScreenPoint::FromUnknownPoint(gfx::Point(
+ aEvent.mPoint.x, aEvent.mPoint.y)),
+ resolution);
+ mGeckoContentController->HandleDoubleTap(gfx::RoundedToInt(point));
}
return nsEventStatus_eConsumeNoDefault;
@@ -758,11 +750,11 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
// We want to inversely scale it because when you're zoomed further in, a
// larger swipe should move you a shorter distance.
- gfxFloat inverseResolution = 1 / CalculateResolution(mFrameMetrics).width;
+ ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse();
- gfx::Point displacement(mX.GetDisplacementForDuration(inverseResolution,
+ gfx::Point displacement(mX.GetDisplacementForDuration(inverseResolution.scale,
timeDelta),
- mY.GetDisplacementForDuration(inverseResolution,
+ mY.GetDisplacementForDuration(inverseResolution.scale,
timeDelta));
if (fabs(displacement.x) <= EPSILON && fabs(displacement.y) <= EPSILON) {
return;
@@ -802,11 +794,11 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) {
// We want to inversely scale it because when you're zoomed further in, a
// larger swipe should move you a shorter distance.
- gfxFloat inverseResolution = 1 / CalculateResolution(mFrameMetrics).width;
+ ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse();
ScrollBy(CSSPoint::FromUnknownPoint(gfx::Point(
- mX.GetDisplacementForDuration(inverseResolution, aDelta),
- mY.GetDisplacementForDuration(inverseResolution, aDelta)
+ mX.GetDisplacementForDuration(inverseResolution.scale, aDelta),
+ mY.GetDisplacementForDuration(inverseResolution.scale, aDelta)
)));
TimeDuration timePaintDelta = TimeStamp::Now() - mPreviousPaintStartTime;
if (timePaintDelta.ToMilliseconds() > gFlingRepaintInterval) {
@@ -834,17 +826,17 @@ void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) {
void AsyncPanZoomController::ScaleWithFocus(float aZoom,
const ScreenPoint& aFocus) {
float zoomFactor = aZoom / mFrameMetrics.mZoom.width;
- gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
SetZoomAndResolution(aZoom);
// If the new scale is very small, we risk multiplying in huge rounding
// errors, so don't bother adjusting the scroll offset.
- if (resolution >= 0.01f) {
+ if (resolution.scale >= 0.01f) {
mFrameMetrics.mScrollOffset.x +=
- aFocus.x * (zoomFactor - 1.0) / resolution;
+ aFocus.x * (zoomFactor - 1.0) / resolution.scale;
mFrameMetrics.mScrollOffset.y +=
- aFocus.y * (zoomFactor - 1.0) / resolution;
+ aFocus.y * (zoomFactor - 1.0) / resolution.scale;
}
}
@@ -896,9 +888,8 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort(
double estimatedPaintDuration =
aEstimatedPaintDuration > EPSILON ? aEstimatedPaintDuration : 1.0;
- gfxSize resolution = CalculateResolution(aFrameMetrics);
- CSSIntRect compositionBounds = LayerIntRect::ToCSSIntRectRoundIn(
- aFrameMetrics.mCompositionBounds, resolution.width, resolution.height);
+ CSSToScreenScale resolution = CalculateResolution(aFrameMetrics);
+ CSSIntRect compositionBounds = gfx::RoundedIn(aFrameMetrics.mCompositionBounds / resolution);
CSSRect scrollableRect = aFrameMetrics.mScrollableRect;
// Ensure the scrollableRect is at least as big as the compositionBounds
@@ -975,21 +966,20 @@ AsyncPanZoomController::CalculateIntrinsicScale(const FrameMetrics& aMetrics)
return gfxSize(intrinsicScale, intrinsicScale);
}
-/*static*/ gfxSize
+/*static*/ CSSToScreenScale
AsyncPanZoomController::CalculateResolution(const FrameMetrics& aMetrics)
{
gfxSize intrinsicScale = CalculateIntrinsicScale(aMetrics);
gfxSize userZoom = aMetrics.mZoom;
- return gfxSize(intrinsicScale.width * userZoom.width,
- intrinsicScale.height * userZoom.height);
+ return CSSToScreenScale(intrinsicScale.width * userZoom.width,
+ intrinsicScale.height * userZoom.height);
}
/*static*/ CSSRect
AsyncPanZoomController::CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics)
{
- gfxSize resolution = CalculateResolution(aMetrics);
- CSSIntRect rect = LayerIntRect::ToCSSIntRectRoundIn(
- aMetrics.mCompositionBounds, resolution.width, resolution.height);
+ CSSToScreenScale resolution = CalculateResolution(aMetrics);
+ CSSIntRect rect = gfx::RoundedIn(aMetrics.mCompositionBounds / resolution);
return CSSRect(rect);
}
@@ -1087,7 +1077,7 @@ AsyncPanZoomController::FireAsyncScrollOnTimeout()
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
ContainerLayer* aLayer,
ViewTransform* aNewTransform,
- gfx::Point& aScrollOffset) {
+ ScreenPoint& aScrollOffset) {
// The eventual return value of this function. The compositor needs to know
// whether or not to advance by a frame as soon as it can. For example, if a
// fling is happening, it has to keep compositing so that the animation is
@@ -1098,12 +1088,12 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
const gfx3DMatrix& currentTransform = aLayer->GetTransform();
// Scales on the root layer, on what's currently painted.
- gfxSize rootScale(currentTransform.GetXScale(),
- currentTransform.GetYScale());
+ LayerToCSSScale rootScale(currentTransform.GetXScale(),
+ currentTransform.GetYScale());
- gfxPoint metricsScrollOffset(0, 0);
- gfxPoint scrollOffset;
- gfxSize localScale;
+ LayerPoint metricsScrollOffset;
+ CSSPoint scrollOffset;
+ CSSToScreenScale localScale;
const FrameMetrics& frame = aLayer->GetFrameMetrics();
{
MonitorAutoLock mon(mMonitor);
@@ -1159,10 +1149,11 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
localScale = CalculateResolution(mFrameMetrics);
if (frame.IsScrollable()) {
- metricsScrollOffset = frame.GetScrollOffsetInLayerPixels();
+ metricsScrollOffset = LayerPoint::FromUnknownPoint(
+ frame.GetScrollOffsetInLayerPixels());
}
- scrollOffset = gfxPoint(mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y);
+ scrollOffset = mFrameMetrics.mScrollOffset;
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
}
@@ -1193,11 +1184,9 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
mAsyncScrollTimeout);
}
- gfxPoint scrollCompensation(
- (scrollOffset / rootScale - metricsScrollOffset) * localScale);
- *aNewTransform = ViewTransform(-scrollCompensation, localScale);
- aScrollOffset.x = scrollOffset.x * localScale.width;
- aScrollOffset.y = scrollOffset.y * localScale.height;
+ LayerPoint translation = (scrollOffset / rootScale) - metricsScrollOffset;
+ *aNewTransform = ViewTransform(-translation, localScale);
+ aScrollOffset = scrollOffset * localScale;
mLastSampleTime = aSampleTime;
@@ -1245,9 +1234,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
// Remote content has sync'd up to the composition geometry
// change, so we can accept the viewport it's calculated.
- gfxSize previousResolution = CalculateResolution(mFrameMetrics);
+ CSSToScreenScale previousResolution = CalculateResolution(mFrameMetrics);
mFrameMetrics.mViewport = aViewportFrame.mViewport;
- gfxSize newResolution = CalculateResolution(mFrameMetrics);
+ CSSToScreenScale newResolution = CalculateResolution(mFrameMetrics);
needContentRepaint |= (previousResolution != newResolution);
}
@@ -1274,10 +1263,10 @@ const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() {
return mFrameMetrics;
}
-void AsyncPanZoomController::UpdateCompositionBounds(const LayerIntRect& aCompositionBounds) {
+void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds) {
MonitorAutoLock mon(mMonitor);
- LayerIntRect oldCompositionBounds = mFrameMetrics.mCompositionBounds;
+ ScreenIntRect oldCompositionBounds = mFrameMetrics.mCompositionBounds;
mFrameMetrics.mCompositionBounds = aCompositionBounds;
// If the window had 0 dimensions before, or does now, we don't want to
@@ -1312,10 +1301,10 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
{
MonitorAutoLock mon(mMonitor);
- LayerIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
+ ScreenIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
CSSRect cssPageRect = mFrameMetrics.mScrollableRect;
CSSPoint scrollOffset = mFrameMetrics.mScrollOffset;
- gfxSize resolution = CalculateResolution(mFrameMetrics);
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
gfxSize currentZoom = mFrameMetrics.mZoom;
float targetZoom;
gfxFloat targetResolution;
@@ -1338,7 +1327,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
targetResolution =
std::min(compositionBounds.width / zoomToRect.width,
compositionBounds.height / zoomToRect.height);
- targetZoom = float(targetResolution / resolution.width) * currentZoom.width;
+ targetZoom = float(targetResolution / resolution.scale) * currentZoom.width;
}
// 1. If the rect is empty, request received from browserElementScrolling.js
// 2. currentZoom is equal to mMaxZoom and user still double-tapping it
@@ -1347,8 +1336,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
if (zoomToRect.IsEmpty() ||
(currentZoom.width == mMaxZoom && targetZoom >= mMaxZoom) ||
(currentZoom.width == localMinZoom && targetZoom <= localMinZoom)) {
- CSSIntRect cssCompositionBounds = LayerIntRect::ToCSSIntRectRoundIn(
- compositionBounds, resolution.width, resolution.height);
+ CSSIntRect cssCompositionBounds = gfx::RoundedIn(compositionBounds / resolution);
float y = scrollOffset.y;
float newHeight =
@@ -1363,7 +1351,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
targetResolution =
std::min(compositionBounds.width / zoomToRect.width,
compositionBounds.height / zoomToRect.height);
- targetZoom = float(targetResolution / resolution.width) * currentZoom.width;
+ targetZoom = float(targetResolution / resolution.scale) * currentZoom.width;
}
targetZoom = clamped(targetZoom, localMinZoom, mMaxZoom);
@@ -1453,7 +1441,8 @@ void AsyncPanZoomController::TimeoutTouchListeners() {
void AsyncPanZoomController::SetZoomAndResolution(float aZoom) {
mMonitor.AssertCurrentThreadOwns();
mFrameMetrics.mZoom = gfxSize(aZoom, aZoom);
- mFrameMetrics.mResolution = CalculateResolution(mFrameMetrics);
+ CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
+ mFrameMetrics.mResolution = gfxSize(resolution.scale, resolution.scale);
}
void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h
index 615efba2c58a..246a7037d0e6 100644
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -111,7 +111,7 @@ public:
* { x = 0, y = 0, width = surface.width, height = surface.height }, however
* there is no hard requirement for this.
*/
- void UpdateCompositionBounds(const LayerIntRect& aCompositionBounds);
+ void UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds);
/**
* We are scrolling a subframe, so disable our machinery until we hit
@@ -178,7 +178,7 @@ public:
bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
ContainerLayer* aLayer,
ViewTransform* aNewTransform,
- gfx::Point& aScrollOffset);
+ ScreenPoint& aScrollOffset);
/**
* A shadow layer update has arrived. |aViewportFrame| is the new FrameMetrics
@@ -235,7 +235,7 @@ public:
* factor, etc. (The mResolution member of aFrameMetrics is
* ignored.)
*/
- static gfxSize CalculateResolution(const FrameMetrics& aMetrics);
+ static CSSToScreenScale CalculateResolution(const FrameMetrics& aMetrics);
static CSSRect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics);
diff --git a/gfx/layers/ipc/Axis.cpp b/gfx/layers/ipc/Axis.cpp
index 1134681bda5a..4e8686e8ef27 100644
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -318,9 +318,8 @@ bool Axis::ScaleWillOverscrollBothSides(float aScale) {
CSSRect cssContentRect = metrics.mScrollableRect;
- float scale = metrics.mZoom.width * aScale;
- CSSIntRect cssCompositionBounds = LayerIntRect::ToCSSIntRectRoundIn(
- metrics.mCompositionBounds, scale, scale);
+ CSSToScreenScale scale(metrics.mZoom.width * aScale);
+ CSSIntRect cssCompositionBounds = RoundedIn(metrics.mCompositionBounds / scale);
return GetRectLength(cssContentRect) < GetRectLength(CSSRect(cssCompositionBounds));
}
diff --git a/gfx/tests/gtest/TestTiledLayerBuffer.cpp b/gfx/tests/gtest/TestTiledLayerBuffer.cpp
index 2909fd7d3724..339558c7dddc 100644
--- a/gfx/tests/gtest/TestTiledLayerBuffer.cpp
+++ b/gfx/tests/gtest/TestTiledLayerBuffer.cpp
@@ -68,7 +68,6 @@ TEST(TiledLayerBuffer, TileStart) {
TEST(TiledLayerBuffer, EmptyUpdate) {
TestTiledLayerBuffer buffer;
- nsRegion::InitStatic();
nsIntRegion validRegion(nsIntRect(0, 0, 10, 10));
buffer.TestUpdate(validRegion, validRegion);
diff --git a/image/decoders/icon/qt/Makefile.in b/image/decoders/icon/qt/Makefile.in
index 9868c78f94ea..b76677b183d3 100644
--- a/image/decoders/icon/qt/Makefile.in
+++ b/image/decoders/icon/qt/Makefile.in
@@ -19,7 +19,7 @@ LOCAL_INCLUDES += $(MOZ_QT_CFLAGS)
FORCE_STATIC_LIB = 1
EXTRA_COMPONENTS = gtkqticonsconverter.manifest
-EXTRA_PP_COMPONENTS = gtkqticonsconverter.js
+DISABLED_EXTRA_PP_COMPONENTS = gtkqticonsconverter.js
include $(topsrcdir)/config/rules.mk
diff --git a/image/decoders/icon/qt/moz.build b/image/decoders/icon/qt/moz.build
index efbd2f3da73d..b9ef4a0e3581 100644
--- a/image/decoders/icon/qt/moz.build
+++ b/image/decoders/icon/qt/moz.build
@@ -12,3 +12,6 @@ CPP_SOURCES += [
'nsIconChannel.cpp',
]
+EXTRA_PP_COMPONENTS += [
+ 'gtkqticonsconverter.js',
+]
diff --git a/js/src/builtin/Iterator-inl.h b/js/src/builtin/Iterator-inl.h
index e6c838cdeb98..bb1d7e74c632 100644
--- a/js/src/builtin/Iterator-inl.h
+++ b/js/src/builtin/Iterator-inl.h
@@ -8,7 +8,6 @@
#define Iterator_inl_h_
#include "jsiter.h"
-#include "jsobjinlines.h"
inline bool
JSObject::isPropertyIterator() const
diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp
index 09159b560dd8..d26a0f24b58a 100644
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -13,10 +13,13 @@
#include "gc/Marking.h"
#include "js/Utility.h"
#include "vm/GlobalObject.h"
+#include "vm/Interpreter.h"
#include "vm/Stack.h"
#include "jsobjinlines.h"
+#include "gc/Barrier-inl.h"
+
using namespace js;
using mozilla::DoubleIsInt32;
diff --git a/js/src/builtin/Module.cpp b/js/src/builtin/Module.cpp
index 0897cd459298..f5386d705970 100644
--- a/js/src/builtin/Module.cpp
+++ b/js/src/builtin/Module.cpp
@@ -4,9 +4,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "jsobjinlines.h"
#include "builtin/Module.h"
+#include "jsobjinlines.h"
+
using namespace js;
Class js::ModuleClass = {
diff --git a/js/src/builtin/ParallelArray.cpp b/js/src/builtin/ParallelArray.cpp
index ae7d4d1dea24..fb0dab4b58f8 100644
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -15,8 +15,6 @@
#include "vm/String.h"
#include "vm/ThreadPool.h"
-#include "jsobjinlines.h"
-
#include "vm/Interpreter-inl.h"
using namespace js;
diff --git a/js/src/builtin/ParallelArray.js b/js/src/builtin/ParallelArray.js
index 98213378053a..0a2db707446f 100644
--- a/js/src/builtin/ParallelArray.js
+++ b/js/src/builtin/ParallelArray.js
@@ -377,7 +377,7 @@ function ParallelArrayMap(func, mode) {
// FIXME(bug 844887): Check |IsCallable(func)|
var self = this;
- var length = self.shape[0];
+ var length = UnsafeGetImmutableElement(self.shape, 0);
var buffer = NewDenseArray(length);
parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc
@@ -432,7 +432,7 @@ function ParallelArrayReduce(func, mode) {
// FIXME(bug 844887): Check |IsCallable(func)|
var self = this;
- var length = self.shape[0];
+ var length = UnsafeGetImmutableElement(self.shape, 0);
if (length === 0)
ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY);
@@ -519,7 +519,7 @@ function ParallelArrayScan(func, mode) {
// FIXME(bug 844887): Check |IsCallable(func)|
var self = this;
- var length = self.shape[0];
+ var length = UnsafeGetImmutableElement(self.shape, 0);
if (length === 0)
ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY);
@@ -726,7 +726,7 @@ function ParallelArrayScatter(targets, defaultValue, conflictFunc, length, mode)
var self = this;
if (length === undefined)
- length = self.shape[0];
+ length = UnsafeGetImmutableElement(self.shape, 0);
// The Divide-Scatter-Vector strategy:
// 1. Slice |targets| array of indices ("scatter-vector") into N
@@ -977,7 +977,7 @@ function ParallelArrayFilter(func, mode) {
// FIXME(bug 844887): Check |IsCallable(func)|
var self = this;
- var length = self.shape[0];
+ var length = UnsafeGetImmutableElement(self.shape, 0);
parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc
if (ShouldForceSequential())
@@ -1151,6 +1151,11 @@ function ParallelArrayFlatten() {
function ParallelArrayGet1(i) {
if (i === undefined)
return undefined;
+
+ // We could use UnsafeGetImmutableElement here, but I am not doing
+ // so (for the moment) since using the default path enables
+ // bounds-check hoisting, which is (currently) not possible
+ // otherwise.
return this.buffer[this.offset + i];
}
@@ -1158,27 +1163,25 @@ function ParallelArrayGet1(i) {
* Specialized variant of get() for two-dimensional case
*/
function ParallelArrayGet2(x, y) {
- var xDimension = this.shape[0];
- var yDimension = this.shape[1];
- if (x === undefined)
- return undefined;
- if (x >= xDimension)
+ var xDimension = UnsafeGetImmutableElement(this.shape, 0);
+ var yDimension = UnsafeGetImmutableElement(this.shape, 1);
+ if (x === undefined || TO_INT32(x) !== x || x >= xDimension)
return undefined;
if (y === undefined)
return NewParallelArray(ParallelArrayView, [yDimension], this.buffer, this.offset + x * yDimension);
- if (y >= yDimension)
+ if (TO_INT32(y) !== y || y >= yDimension)
return undefined;
var offset = y + x * yDimension;
- return this.buffer[this.offset + offset];
+ return UnsafeGetImmutableElement(this.buffer, this.offset + offset);
}
/**
* Specialized variant of get() for three-dimensional case
*/
function ParallelArrayGet3(x, y, z) {
- var xDimension = this.shape[0];
- var yDimension = this.shape[1];
- var zDimension = this.shape[2];
+ var xDimension = UnsafeGetImmutableElement(this.shape, 0);
+ var yDimension = UnsafeGetImmutableElement(this.shape, 1);
+ var zDimension = UnsafeGetImmutableElement(this.shape, 2);
if (x === undefined)
return undefined;
if (x >= xDimension)
@@ -1194,7 +1197,7 @@ function ParallelArrayGet3(x, y, z) {
if (z >= zDimension)
return undefined;
var offset = z + y*zDimension + x * yDimension * zDimension;
- return this.buffer[this.offset + offset];
+ return UnsafeGetImmutableElement(this.buffer, this.offset + offset);
}
/**
@@ -1228,7 +1231,7 @@ function ParallelArrayGetN(...coords) {
/** The length property yields the outermost dimension */
function ParallelArrayLength() {
- return this.shape[0];
+ return UnsafeGetImmutableElement(this.shape, 0);
}
function ParallelArrayToString() {
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
index 335666be8845..28b32290fb98 100644
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -10,6 +10,8 @@
#include "builtin/RegExp.h"
+#include "jsobjinlines.h"
+
#include "vm/RegExpObject-inl.h"
#include "vm/RegExpStatics-inl.h"
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index 1d28985f7a2f..1dbd5eef2292 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -11,13 +11,14 @@
#include "jsfriendapi.h"
#include "jsgc.h"
#include "jsobj.h"
-#include "jsobjinlines.h"
#include "jsprf.h"
#include "jswrapper.h"
#include "builtin/TestingFunctions.h"
#include "vm/ForkJoin.h"
+#include "jsobjinlines.h"
+
#include "vm/Stack-inl.h"
using namespace js;
diff --git a/js/src/config/makefiles/debugmake.mk b/js/src/config/makefiles/debugmake.mk
index dd21734003e7..6e193947e4da 100644
--- a/js/src/config/makefiles/debugmake.mk
+++ b/js/src/config/makefiles/debugmake.mk
@@ -50,7 +50,6 @@ ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $
@echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
@echo "STATIC_LIBS = $(STATIC_LIBS)"
@echo "SHARED_LIBS = $(SHARED_LIBS)"
- @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)"
@echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)"
@echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)"
@echo --------------------------------------------------------------------------------
diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk
index 42ecc25f2ee7..ec293c3cc8fc 100644
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -110,10 +110,6 @@ endif # ifndef .PYMAKE
_VPATH_SRCS = $(abspath $<)
-ifdef EXTRA_DSO_LIBS
-EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
-endif
-
################################################################################
# Testing frameworks support
################################################################################
diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp
index 6032d3944244..57b6823449a3 100644
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -4,16 +4,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "ctypes/CTypes.h"
+
#include "mozilla/FloatingPoint.h"
+#include "mozilla/StandardInteger.h"
-#include "CTypes.h"
-#include "Library.h"
-#include "jsnum.h"
-#include "jscompartment.h"
-#include "jsobjinlines.h"
#include
-
#include
+
#if defined(XP_WIN) || defined(XP_OS2)
#include
#endif
@@ -32,7 +30,12 @@
#include
#endif
-#include "mozilla/StandardInteger.h"
+#include "jscompartment.h"
+#include "jsnum.h"
+#include "jsprf.h"
+#include "jstypedarray.h"
+
+#include "ctypes/Library.h"
using namespace std;
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index 862fb8f8a7d3..9a3789d4b1fc 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -14,6 +14,8 @@
#include "vm/GlobalObject.h"
#include "jsinferinlines.h"
+#include "jsobjinlines.h"
+
#include "frontend/ParseMaps-inl.h"
#include "frontend/ParseNode-inl.h"
#include "frontend/Parser-inl.h"
@@ -74,6 +76,15 @@ CheckArgumentsWithinEval(JSContext *cx, Parser &parser, Handle
return true;
}
+inline bool
+CanLazilyParse(JSContext *cx, const CompileOptions &options)
+{
+ return options.canLazilyParse &&
+ options.compileAndGo &&
+ options.sourcePolicy == CompileOptions::SAVE_SOURCE &&
+ !cx->compartment()->debugMode();
+}
+
JSScript *
frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
HandleScript evalCaller,
@@ -102,7 +113,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
return NULL;
if (options.filename && !ss->setFilename(cx, options.filename))
return NULL;
-
+
JS::RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, ss));
if (!sourceObject)
return NULL;
@@ -120,28 +131,21 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
break;
}
+ bool canLazilyParse = CanLazilyParse(cx, options);
+
Maybe > syntaxParser;
- if (options.canLazilyParse) {
+ if (canLazilyParse) {
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
(Parser *) NULL,
(LazyScript *) NULL);
}
Parser parser(cx, options, chars, length, /* foldConstants = */ true,
- options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
+ canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
parser.sct = sct;
GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx));
- // Syntax parsing may cause us to restart processing of top level
- // statements in the script. Use Maybe<> so that the parse context can be
- // reset when this occurs.
- Maybe > pc;
-
- pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0);
- if (!pc.ref().init())
- return NULL;
-
bool savedCallerFun =
options.compileAndGo &&
evalCaller &&
@@ -169,6 +173,15 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
if (!bce.init())
return NULL;
+ // Syntax parsing may cause us to restart processing of top level
+ // statements in the script. Use Maybe<> so that the parse context can be
+ // reset when this occurs.
+ Maybe > pc;
+
+ pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0);
+ if (!pc.ref().init())
+ return NULL;
+
/* If this is a direct call to eval, inherit the caller's strictness. */
if (evalCaller && evalCaller->strict)
globalsc.strict = true;
@@ -313,32 +326,34 @@ bool
frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *lazy,
const jschar *chars, size_t length)
{
- CompileOptions options(cx);
+ JS_ASSERT(cx->compartment() == fun->compartment());
+
+ CompileOptions options(cx, lazy->version());
options.setPrincipals(cx->compartment()->principals)
- .setOriginPrincipals(lazy->parent()->originPrincipals)
- .setVersion(lazy->parent()->getVersion())
- .setFileAndLine(lazy->parent()->filename(), lazy->lineno())
+ .setOriginPrincipals(lazy->originPrincipals())
+ .setFileAndLine(lazy->source()->filename(), lazy->lineno())
.setColumn(lazy->column())
- .setCompileAndGo(lazy->parent()->compileAndGo)
+ .setCompileAndGo(true)
.setNoScriptRval(false)
.setSelfHostingMode(false);
Parser parser(cx, options, chars, length,
/* foldConstants = */ true, NULL, lazy);
- RootedObject enclosingScope(cx, lazy->parent()->function());
+ RootedObject enclosingScope(cx, lazy->parentFunction());
- ParseNode *pn = parser.standaloneLazyFunction(fun, lazy->parent()->staticLevel + 1,
- lazy->strict());
+ ParseNode *pn = parser.standaloneLazyFunction(fun, lazy->staticLevel(), lazy->strict());
if (!pn)
return false;
- JS::RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, lazy->source()));
- if (!sourceObject)
+ if (!NameFunctions(cx, pn))
return false;
+ JS::RootedScriptSource sourceObject(cx, lazy->sourceObject());
+ JS_ASSERT(sourceObject);
+
Rooted script(cx, JSScript::Create(cx, enclosingScope, false,
- options, lazy->parent()->staticLevel + 1,
+ options, lazy->staticLevel(),
sourceObject, lazy->begin(), lazy->end()));
if (!script)
return false;
@@ -347,11 +362,11 @@ frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *laz
if (lazy->directlyInsideEval())
script->directlyInsideEval = true;
-
- bool hasGlobalScope = lazy->parent()->compileAndGo;
+ if (lazy->usesArgumentsAndApply())
+ script->usesArgumentsAndApply = true;
BytecodeEmitter bce(/* parent = */ NULL, &parser, pn->pn_funbox, script, options.forEval,
- /* evalCaller = */ NullPtr(), hasGlobalScope,
+ /* evalCaller = */ NullPtr(), /* hasGlobalScope = */ true,
options.lineno, BytecodeEmitter::LazyFunction);
if (!bce.init())
return false;
@@ -385,8 +400,10 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
return false;
}
+ bool canLazilyParse = CanLazilyParse(cx, options);
+
Maybe > syntaxParser;
- if (options.canLazilyParse) {
+ if (canLazilyParse) {
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
(Parser *) NULL,
(LazyScript *) NULL);
@@ -395,7 +412,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
JS_ASSERT(!options.forEval);
Parser parser(cx, options, chars, length, /* foldConstants = */ true,
- options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
+ canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
parser.sct = &sct;
JS_ASSERT(fun);
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 5a07cd3e21b8..8d6fbb7be16b 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -41,6 +41,7 @@
#include "vm/Shape.h"
#include "jsatominlines.h"
+#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "frontend/ParseMaps-inl.h"
@@ -1128,11 +1129,22 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
* resolving upvar accesses within the inner function.
*/
if (bce->emitterMode == BytecodeEmitter::LazyFunction) {
+ // The only statements within a lazy function which can push lexical
+ // scopes are try/catch blocks. Use generic ops in this case.
+ for (StmtInfoBCE *stmt = bce->topStmt; stmt; stmt = stmt->down) {
+ switch (stmt->type) {
+ case STMT_TRY:
+ case STMT_FINALLY:
+ return true;
+ default:;
+ }
+ }
+
size_t hops = 0;
FunctionBox *funbox = bce->sc->asFunctionBox();
if (funbox->hasExtensibleScope())
return false;
- if (funbox->function()->atom() == pn->pn_atom)
+ if (funbox->function()->isNamedLambda() && funbox->function()->atom() == pn->pn_atom)
return false;
if (funbox->function()->isHeavyweight()) {
hops++;
@@ -2676,7 +2688,7 @@ EmitDestructuringDecls(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, Parse
if (pn->isKind(PNK_ARRAY)) {
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
- if (pn2->isKind(PNK_COMMA))
+ if (pn2->isKind(PNK_ELISION))
continue;
emitter = (pn2->isKind(PNK_NAME))
? EmitDestructuringDecl
@@ -2896,8 +2908,8 @@ EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn,
JS_ASSERT(bce->stackDepth >= stackDepth + 1);
}
- /* Nullary comma node makes a hole in the array destructurer. */
- if (pn3->isKind(PNK_COMMA) && pn3->isArity(PN_NULLARY)) {
+ /* Elision node makes a hole in the array destructurer. */
+ if (pn3->isKind(PNK_ELISION)) {
JS_ASSERT(pn->isKind(PNK_ARRAY));
JS_ASSERT(pn2 == pn3);
if (Emit1(cx, bce, JSOP_POP) < 0)
@@ -2972,7 +2984,7 @@ EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp,
}
/* MaybeEmitGroupAssignment won't call us if rhs is holey. */
- JS_ASSERT(!(pn->isKind(PNK_COMMA) && pn->isArity(PN_NULLARY)));
+ JS_ASSERT(!pn->isKind(PNK_ELISION));
if (!EmitTree(cx, bce, pn))
return false;
++limit;
@@ -2989,7 +3001,7 @@ EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp,
if (!EmitUnaliasedVarOp(cx, JSOP_GETLOCAL, slot, bce))
return false;
- if (pn->isKind(PNK_COMMA) && pn->isArity(PN_NULLARY)) {
+ if (pn->isKind(PNK_ELISION)) {
if (Emit1(cx, bce, JSOP_POP) < 0)
return false;
} else {
@@ -4491,8 +4503,10 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
if (fun->isInterpretedLazy()) {
- if (!fun->lazyScript()->parent())
- fun->lazyScript()->initParent(bce->script);
+ if (!fun->lazyScript()->sourceObject()) {
+ JSFunction *parent = bce->sc->isFunctionBox() ? bce->sc->asFunctionBox()->function() : NULL;
+ fun->lazyScript()->setParent(parent, bce->script->sourceObject(), bce->script->originPrincipals);
+ }
} else {
SharedContext *outersc = bce->sc;
@@ -4557,6 +4571,9 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/* We measured the max scope depth when we parsed the function. */
if (!EmitFunctionScript(cx, &bce2, pn->pn_body))
return false;
+
+ if (funbox->usesArguments && funbox->usesApply)
+ script->usesArgumentsAndApply = true;
}
}
@@ -5264,16 +5281,14 @@ EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* the comment on EmitSwitch.
*/
MOZ_NEVER_INLINE static bool
-EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+EmitLabeledStatement(JSContext *cx, BytecodeEmitter *bce, const LabeledStatement *pn)
{
/*
* Emit a JSOP_LABEL instruction. The argument is the offset to the statement
* following the labeled statement.
*/
- JSAtom *atom = pn->pn_atom;
-
jsatomid index;
- if (!bce->makeAtomIndex(atom, &index))
+ if (!bce->makeAtomIndex(pn->label(), &index))
return false;
ptrdiff_t top = EmitJump(cx, bce, JSOP_LABEL, 0);
@@ -5283,8 +5298,8 @@ EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/* Emit code for the labeled statement. */
StmtInfoBCE stmtInfo(cx);
PushStatementBCE(bce, &stmtInfo, STMT_LABEL, bce->offset());
- stmtInfo.label = atom;
- if (!EmitTree(cx, bce, pn->expr()))
+ stmtInfo.label = pn->label();
+ if (!EmitTree(cx, bce, pn->statement()))
return false;
if (!PopStatementBCE(cx, bce))
return false;
@@ -5527,7 +5542,7 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (nspread && !EmitNumberOp(cx, 0, bce))
return false;
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
- if (pn2->isKind(PNK_COMMA) && pn2->isArity(PN_NULLARY)) {
+ if (pn2->isKind(PNK_ELISION)) {
if (Emit1(cx, bce, JSOP_HOLE) < 0)
return false;
} else {
@@ -5816,8 +5831,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ok = EmitStatement(cx, bce, pn);
break;
- case PNK_COLON:
- ok = EmitLabel(cx, bce, pn);
+ case PNK_LABEL:
+ ok = EmitLabeledStatement(cx, bce, &pn->as());
break;
case PNK_COMMA:
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
index 6588bd3e1997..d4f5c34b0e46 100644
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -49,6 +49,10 @@ class FullParseHandler
LazyScript * const lazyOuterFunction_;
size_t lazyInnerFunctionIndex;
+ const TokenPos &pos() {
+ return tokenStream.currentToken().pos;
+ }
+
public:
/*
@@ -100,7 +104,7 @@ class FullParseHandler
return dn;
}
ParseNode *newAtom(ParseNodeKind kind, JSAtom *atom, JSOp op = JSOP_NOP) {
- ParseNode *pn = NullaryNode::create(kind, this);
+ ParseNode *pn = new_(kind, pos());
if (!pn)
return NULL;
pn->setOp(op);
@@ -108,7 +112,7 @@ class FullParseHandler
return pn;
}
ParseNode *newNumber(double value, DecimalPoint decimalPoint = NoDecimal) {
- ParseNode *pn = NullaryNode::create(PNK_NUMBER, this);
+ ParseNode *pn = new_(PNK_NUMBER, pos());
if (!pn)
return NULL;
pn->initNumber(value, decimalPoint);
@@ -130,8 +134,8 @@ class FullParseHandler
return new_(cond, thenExpr, elseExpr);
}
- ParseNode *newNullary(ParseNodeKind kind) {
- return NullaryNode::create(kind, this);
+ ParseNode *newElision() {
+ return new_(PNK_ELISION, pos());
}
ParseNode *newUnary(ParseNodeKind kind, ParseNode *kid, JSOp op = JSOP_NOP) {
@@ -162,11 +166,6 @@ class FullParseHandler
ParseContext *pc, JSOp op = JSOP_NOP) {
return ParseNode::newBinaryOrAppend(kind, op, left, right, this, pc, foldConstants);
}
- void setBinaryRHS(ParseNode *pn, ParseNode *rhs) {
- JS_ASSERT(pn->isArity(PN_BINARY));
- pn->pn_right = rhs;
- pn->pn_pos.end = rhs->pn_pos.end;
- }
ParseNode *newTernary(ParseNodeKind kind,
ParseNode *first, ParseNode *second, ParseNode *third,
@@ -174,12 +173,22 @@ class FullParseHandler
return new_(kind, op, first, second, third);
}
+ ParseNode *newLabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) {
+ return new_(label, stmt, begin);
+ }
+
+ ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) {
+ TokenPos pos = TokenPos::make(begin, body->pn_pos.end);
+ return new_(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);
+ }
+
ParseNode *newBreak(PropertyName *label, uint32_t begin, uint32_t end) {
return new_(label, begin, end);
}
ParseNode *newContinue(PropertyName *label, uint32_t begin, uint32_t end) {
return new_(label, begin, end);
}
+
ParseNode *newDebuggerStatement(const TokenPos &pos) {
return new_(pos);
}
@@ -193,8 +202,6 @@ class FullParseHandler
inline bool addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody);
- inline void morphNameIntoLabel(ParseNode *name, ParseNode *statement);
-
inline void setLeaveBlockResult(ParseNode *block, ParseNode *kid, bool leaveBlockExpr);
inline void setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *pn);
@@ -213,7 +220,6 @@ class FullParseHandler
return pn->isKind(kind) && !pn->isInParens();
}
- inline void noteLValue(ParseNode *pn);
inline bool finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op);
void setBeginPosition(ParseNode *pn, ParseNode *oth) {
@@ -292,9 +298,6 @@ class FullParseHandler
}
return NULL;
}
- bool isEmptySemicolon(ParseNode *pn) {
- return pn->isKind(PNK_SEMI) && !pn->pn_kid;
- }
inline ParseNode *makeAssignment(ParseNode *pn, ParseNode *rhs);
@@ -367,14 +370,6 @@ FullParseHandler::addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
return true;
}
-inline void
-FullParseHandler::morphNameIntoLabel(ParseNode *name, ParseNode *statement)
-{
- name->setKind(PNK_COLON);
- name->pn_pos.end = statement->pn_pos.end;
- name->pn_expr = statement;
-}
-
inline void
FullParseHandler::setLeaveBlockResult(ParseNode *block, ParseNode *kid, bool leaveBlockExpr)
{
@@ -419,15 +414,6 @@ FullParseHandler::newLexicalScope(ObjectBox *blockbox)
return pn;
}
-inline void
-FullParseHandler::noteLValue(ParseNode *pn)
-{
- if (pn->isUsed())
- pn->pn_lexdef->pn_dflags |= PND_ASSIGNED;
-
- pn->pn_dflags |= PND_ASSIGNED;
-}
-
inline bool
FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op)
{
@@ -445,7 +431,7 @@ FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JS
? JSOP_SETCONST
: JSOP_SETNAME);
- noteLValue(pn);
+ pn->markAsAssigned();
/* The declarator's position must include the initializer. */
pn->pn_pos.end = init->pn_pos.end;
diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp
index 109f22ce47c9..9f079059237b 100644
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -8,10 +8,13 @@
#include "jsfun.h"
#include "jsprf.h"
+
#include "frontend/BytecodeCompiler.h"
#include "frontend/ParseNode.h"
#include "frontend/SharedContext.h"
+#include "jsfuninlines.h"
+
#include "vm/String-inl.h"
#include "vm/StringBuffer.h"
@@ -175,8 +178,6 @@ class NameResolver
JSAtom *resolveFun(ParseNode *pn, HandleAtom prefix) {
JS_ASSERT(pn != NULL && pn->isKind(PNK_FUNCTION));
RootedFunction fun(cx, pn->pn_funbox->function());
- if (nparents == 0)
- return NULL;
StringBuffer buf(cx);
this->buf = &buf;
@@ -184,7 +185,7 @@ class NameResolver
/* If the function already has a name, use that */
if (fun->displayAtom() != NULL) {
if (prefix == NULL)
- return fun->atom();
+ return fun->displayAtom();
if (!buf.append(prefix) ||
!buf.append("/") ||
!buf.append(fun->displayAtom()))
diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp
index fe913db666d5..600d48260b56 100644
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -530,7 +530,7 @@ Parser::cloneLeftHandSide(ParseNode *opn)
pn2 = handler.new_(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
} else if (opn2->isArity(PN_NULLARY)) {
- JS_ASSERT(opn2->isKind(PNK_COMMA));
+ JS_ASSERT(opn2->isKind(PNK_ELISION));
pn2 = cloneParseTree(opn2);
} else {
pn2 = cloneLeftHandSide(opn2);
diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
index c3e0b2b79b55..474f4a2a048e 100644
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -75,7 +75,9 @@ class UpvarCookie
F(DOT) \
F(ELEM) \
F(ARRAY) \
+ F(ELISION) \
F(STATEMENTLIST) \
+ F(LABEL) \
F(OBJECT) \
F(CALL) \
F(NAME) \
@@ -181,7 +183,8 @@ class UpvarCookie
*
* The long comment after this enum block describes the kinds in detail.
*/
-enum ParseNodeKind {
+enum ParseNodeKind
+{
#define EMIT_ENUM(name) PNK_##name,
FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
#undef EMIT_ENUM
@@ -284,7 +287,7 @@ enum ParseNodeKind {
* pn_prologue: true if Directive Prologue member
* in original source, not introduced via
* constant folding or other tree rewriting
- * PNK_COLON name pn_atom: label, pn_expr: labeled statement
+ * PNK_LABEL name pn_atom: label, pn_expr: labeled statement
*
*
* All left-associated binary trees of the same type are optimized into lists
@@ -357,7 +360,7 @@ enum ParseNodeKind {
* PNK_GENEXP list Exactly like PNK_CALL, used for the implicit call
* in the desugaring of a generator-expression.
* PNK_ARRAY list pn_head: list of pn_count array element exprs
- * [,,] holes are represented by PNK_COMMA nodes
+ * [,,] holes are represented by PNK_ELISION nodes
* pn_xflags: PN_ENDCOMMA if extra comma at end
* PNK_OBJECT list pn_head: list of pn_count binary PNK_COLON nodes
* PNK_COLON binary key-value pair in object initializer or
@@ -392,7 +395,8 @@ enum ParseNodeKind {
* pn_kid: array comprehension expression
* PNK_NOP nullary
*/
-enum ParseNodeArity {
+enum ParseNodeArity
+{
PN_NULLARY, /* 0 kids, only pn_atom/pn_dval/etc. */
PN_UNARY, /* one kid, plus a couple of scalars */
PN_BINARY, /* two kids, plus a couple of scalars */
@@ -404,6 +408,7 @@ enum ParseNodeArity {
struct Definition;
+class LabeledStatement;
class LoopControlStatement;
class BreakStatement;
class ContinueStatement;
@@ -411,7 +416,8 @@ class ConditionalExpression;
class PropertyAccess;
class ModuleBox;
-struct ParseNode {
+struct ParseNode
+{
private:
uint32_t pn_type : 16, /* PNK_* type */
pn_op : 8, /* see JSOp enum and jsopcode.tbl */
@@ -723,11 +729,6 @@ struct ParseNode {
/* Return true if this node appears in a Directive Prologue. */
bool isDirectivePrologueMember() const { return pn_prologue; }
-#ifdef JS_HAS_DESTRUCTURING
- /* Return true if this represents a hole in an array literal. */
- bool isArrayHole() const { return isKind(PNK_COMMA) && isArity(PN_NULLARY); }
-#endif
-
#ifdef JS_HAS_GENERATOR_EXPRS
ParseNode *generatorExpr() const {
JS_ASSERT(isKind(PNK_GENEXP));
@@ -738,6 +739,8 @@ struct ParseNode {
}
#endif
+ inline void markAsAssigned();
+
/*
* Compute a pointer to the last element in a singly-linked list. NB: list
* must be non-empty for correct PN_LAST usage -- this is asserted!
@@ -813,7 +816,11 @@ struct ParseNode {
#endif
};
-struct NullaryNode : public ParseNode {
+struct NullaryNode : public ParseNode
+{
+ NullaryNode(ParseNodeKind kind, const TokenPos &pos)
+ : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {}
+
static inline NullaryNode *create(ParseNodeKind kind, FullParseHandler *handler) {
return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, handler);
}
@@ -827,7 +834,8 @@ struct NullaryNode : public ParseNode {
#endif
};
-struct UnaryNode : public ParseNode {
+struct UnaryNode : public ParseNode
+{
UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid)
: ParseNode(kind, op, PN_UNARY, pos)
{
@@ -847,7 +855,8 @@ struct UnaryNode : public ParseNode {
#endif
};
-struct BinaryNode : public ParseNode {
+struct BinaryNode : public ParseNode
+{
BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
: ParseNode(kind, op, PN_BINARY, pos)
{
@@ -875,7 +884,8 @@ struct BinaryNode : public ParseNode {
#endif
};
-struct TernaryNode : public ParseNode {
+struct TernaryNode : public ParseNode
+{
TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
: ParseNode(kind, op, PN_TERNARY,
TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
@@ -921,7 +931,8 @@ struct ListNode : public ParseNode
#endif
};
-struct CodeNode : public ParseNode {
+struct CodeNode : public ParseNode
+{
static inline CodeNode *create(ParseNodeKind kind, FullParseHandler *handler) {
return (CodeNode *) ParseNode::create(kind, PN_CODE, handler);
}
@@ -935,7 +946,8 @@ struct CodeNode : public ParseNode {
#endif
};
-struct NameNode : public ParseNode {
+struct NameNode : public ParseNode
+{
static NameNode *create(ParseNodeKind kind, JSAtom *atom,
FullParseHandler *handler, ParseContext *pc);
@@ -950,13 +962,41 @@ struct NameNode : public ParseNode {
#endif
};
-struct LexicalScopeNode : public ParseNode {
+struct LexicalScopeNode : public ParseNode
+{
static inline LexicalScopeNode *create(ParseNodeKind kind, FullParseHandler *handler) {
return (LexicalScopeNode *) ParseNode::create(kind, PN_NAME, handler);
}
};
-class LoopControlStatement : public ParseNode {
+class LabeledStatement : public ParseNode
+{
+ public:
+ LabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin)
+ : ParseNode(PNK_LABEL, JSOP_NOP, PN_NAME, TokenPos::make(begin, stmt->pn_pos.end))
+ {
+ pn_atom = label;
+ pn_expr = stmt;
+ }
+
+ PropertyName *label() const {
+ return pn_atom->asPropertyName();
+ }
+
+ ParseNode *statement() const {
+ return pn_expr;
+ }
+
+ static bool test(const ParseNode &node) {
+ bool match = node.isKind(PNK_LABEL);
+ JS_ASSERT_IF(match, node.isArity(PN_NAME));
+ JS_ASSERT_IF(match, node.isOp(JSOP_NOP));
+ return match;
+ }
+};
+
+class LoopControlStatement : public ParseNode
+{
protected:
LoopControlStatement(ParseNodeKind kind, PropertyName *label, uint32_t begin, uint32_t end)
: ParseNode(kind, JSOP_NOP, PN_NULLARY, TokenPos::make(begin, end))
@@ -979,7 +1019,8 @@ class LoopControlStatement : public ParseNode {
}
};
-class BreakStatement : public LoopControlStatement {
+class BreakStatement : public LoopControlStatement
+{
public:
BreakStatement(PropertyName *label, uint32_t begin, uint32_t end)
: LoopControlStatement(PNK_BREAK, label, begin, end)
@@ -993,7 +1034,8 @@ class BreakStatement : public LoopControlStatement {
}
};
-class ContinueStatement : public LoopControlStatement {
+class ContinueStatement : public LoopControlStatement
+{
public:
ContinueStatement(PropertyName *label, uint32_t begin, uint32_t end)
: LoopControlStatement(PNK_CONTINUE, label, begin, end)
@@ -1007,14 +1049,16 @@ class ContinueStatement : public LoopControlStatement {
}
};
-class DebuggerStatement : public ParseNode {
+class DebuggerStatement : public ParseNode
+{
public:
DebuggerStatement(const TokenPos &pos)
: ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos)
{ }
};
-class ConditionalExpression : public ParseNode {
+class ConditionalExpression : public ParseNode
+{
public:
ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr)
: ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
@@ -1048,24 +1092,28 @@ class ConditionalExpression : public ParseNode {
}
};
-class ThisLiteral : public ParseNode {
+class ThisLiteral : public ParseNode
+{
public:
ThisLiteral(const TokenPos &pos) : ParseNode(PNK_THIS, JSOP_THIS, PN_NULLARY, pos) { }
};
-class NullLiteral : public ParseNode {
+class NullLiteral : public ParseNode
+{
public:
NullLiteral(const TokenPos &pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
};
-class BooleanLiteral : public ParseNode {
+class BooleanLiteral : public ParseNode
+{
public:
BooleanLiteral(bool b, const TokenPos &pos)
: ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos)
{ }
};
-class PropertyAccess : public ParseNode {
+class PropertyAccess : public ParseNode
+{
public:
PropertyAccess(ParseNode *lhs, PropertyName *name, uint32_t begin, uint32_t end)
: ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end))
@@ -1091,7 +1139,8 @@ class PropertyAccess : public ParseNode {
}
};
-class PropertyByValue : public ParseNode {
+class PropertyByValue : public ParseNode
+{
public:
PropertyByValue(ParseNode *lhs, ParseNode *propExpr, uint32_t begin, uint32_t end)
: ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
@@ -1239,7 +1288,8 @@ struct Definition : public ParseNode
}
};
-class ParseNodeAllocator {
+class ParseNodeAllocator
+{
public:
explicit ParseNodeAllocator(JSContext *cx) : cx(cx), freelist(NULL) {}
@@ -1268,6 +1318,15 @@ ParseNode::test(unsigned flag) const
return !!(pn_dflags & flag);
}
+inline void
+ParseNode::markAsAssigned()
+{
+ JS_ASSERT(js_CodeSpec[pn_op].format & JOF_NAME);
+ if (isUsed())
+ pn_lexdef->pn_dflags |= PND_ASSIGNED;
+ pn_dflags |= PND_ASSIGNED;
+}
+
inline Definition *
ParseNode::resolve()
{
@@ -1295,7 +1354,8 @@ ParseNode::isConstant()
}
}
-class ObjectBox {
+class ObjectBox
+{
public:
JSObject *object;
@@ -1316,7 +1376,8 @@ class ObjectBox {
ObjectBox(Module *module, ObjectBox *traceLink);
};
-enum ParseReportKind {
+enum ParseReportKind
+{
ParseError,
ParseWarning,
ParseExtraWarning,
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 97580b021f3f..fca697549035 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -48,6 +48,7 @@
#include "vm/Shape.h"
#include "jsatominlines.h"
+#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "frontend/ParseMaps-inl.h"
@@ -419,9 +420,6 @@ Parser::Parser(JSContext *cx, const CompileOptions &options,
abortedSyntaxParse(false),
handler(cx, tokenStream, foldConstants, syntaxParser, lazyOuterFunction)
{
- // XXX bug 678037 always disable syntax parsing for now.
- handler.disableSyntaxParser();
-
cx->runtime()->activeCompilations++;
// The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
@@ -487,6 +485,8 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
inGenexpLambda(false),
useAsm(false),
insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
+ usesArguments(false),
+ usesApply(false),
funCxFlags()
{
JS_ASSERT(fun->isTenured());
@@ -925,6 +925,7 @@ Parser::checkFunctionArguments()
dn->pn_dflags |= PND_IMPLICITARGUMENTS;
if (!pc->define(context, arguments, dn, Definition::VAR))
return false;
+ pc->sc->asFunctionBox()->usesArguments = true;
break;
}
}
@@ -1014,11 +1015,15 @@ template <>
bool
Parser::checkFunctionArguments()
{
- if (pc->sc->asFunctionBox()->function()->hasRest()) {
- if (pc->lexdeps->lookup(context->names().arguments)) {
+ bool hasRest = pc->sc->asFunctionBox()->function()->hasRest();
+
+ if (pc->lexdeps->lookup(context->names().arguments)) {
+ pc->sc->asFunctionBox()->usesArguments = true;
+ if (hasRest) {
report(ParseError, false, null(), JSMSG_ARGUMENTS_AND_REST);
return false;
}
+ } else if (hasRest) {
DefinitionNode maybeArgDef = pc->decls().lookupFirst(context->names().arguments);
if (maybeArgDef && handler.getDefinitionKind(maybeArgDef) != Definition::ARG) {
report(ParseError, false, null(), JSMSG_ARGUMENTS_AND_REST);
@@ -1074,27 +1079,6 @@ Parser::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
return pn;
}
-static void
-ForgetUse(ParseNode *pn)
-{
- if (!pn->isUsed()) {
- JS_ASSERT(!pn->isDefn());
- return;
- }
-
- ParseNode **pnup = &pn->lexdef()->dn_uses;
- ParseNode *pnu;
- while ((pnu = *pnup) != pn)
- pnup = &pnu->pn_link;
- *pnup = pn->pn_link;
- pn->setUsed(false);
-}
-
-static void
-ForgetUse(SyntaxParseHandler::Node pn)
-{
-}
-
/* See comment for use in Parser::functionDef. */
template <>
bool
@@ -1341,14 +1325,6 @@ Parser::leaveFunction(ParseNode *fn, HandlePropertyName funNam
continue;
}
- /*
- * If there are no uses of this placeholder (e.g., it was created
- * for an identifierName that turned out to be a label), there is
- * nothing left to do.
- */
- if (!dn->dn_uses)
- continue;
-
Definition *outer_dn = outerpc->decls().lookupFirst(atom);
/*
@@ -2046,7 +2022,7 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox *funbo
size_t numFreeVariables = pc->lexdeps->count();
size_t numInnerFunctions = pc->innerFunctions.length();
- LazyScript *lazy = LazyScript::Create(context, numFreeVariables, numInnerFunctions,
+ LazyScript *lazy = LazyScript::Create(context, numFreeVariables, numInnerFunctions, versionNumber(),
funbox->bufStart, funbox->bufEnd,
funbox->startLine, funbox->startColumn);
if (!lazy)
@@ -2064,6 +2040,8 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox *funbo
if (pc->sc->strict)
lazy->setStrict();
+ if (funbox->usesArguments && funbox->usesApply)
+ lazy->setUsesArgumentsAndApply();
PropagateTransitiveParseFlags(funbox, lazy);
funbox->object->toFunction()->initLazyScript(lazy);
@@ -2173,6 +2151,11 @@ Parser::functionArgsAndBody(Node pn, HandleFunction fun,
*becameStrict = false;
ParseContext *outerpc = pc;
+ // As from a full parse handler, abort if functions are defined within
+ // lexical scopes.
+ if (pc->topScopeStmt)
+ return abortIfSyntaxParser();
+
// Create box for fun->object early to protect against last-ditch GC.
FunctionBox *funbox = newFunctionBox(fun, pc, strict);
if (!funbox)
@@ -2503,7 +2486,7 @@ Parser::maybeParseDirective(Node pn, bool *cont)
template <>
void
-Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool *hasFunctionStmt)
+Parser::addStatementToList(ParseNode *pn, ParseNode *kid)
{
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
@@ -2512,21 +2495,12 @@ Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool
* PNX_FUNCDEFS notifies the emitter that the block contains body-
* level function definitions that should be processed before the
* rest of nodes.
- *
- * |hasFunctionStmt| is for the TOK_LC case in Statement. It
- * is relevant only for function definitions not at body-level,
- * which we call function statements.
*/
if (pc->atBodyLevel()) {
pn->pn_xflags |= PNX_FUNCDEFS;
} else {
- /*
- * General deoptimization was done in functionDef, here we just
- * need to tell TOK_LC in Parser::statement to add braces.
- */
+ /* General deoptimization was done in functionDef. */
JS_ASSERT_IF(pc->sc->isFunctionBox(), pc->sc->asFunctionBox()->hasExtensibleScope());
- if (hasFunctionStmt)
- *hasFunctionStmt = true;
}
}
@@ -2536,7 +2510,7 @@ Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool
template <>
void
-Parser::addStatementToList(Node pn, Node kid, bool *hasFunctionStmt)
+Parser::addStatementToList(Node pn, Node kid)
{
}
@@ -2547,11 +2521,9 @@ Parser::addStatementToList(Node pn, Node kid, bool *hasFunct
*/
template
typename ParseHandler::Node
-Parser::statements(bool *hasFunctionStmt)
+Parser::statements()
{
JS_CHECK_RECURSION(context, return null());
- if (hasFunctionStmt)
- *hasFunctionStmt = false;
Node pn = handler.newList(PNK_STATEMENTLIST);
if (!pn)
@@ -2584,7 +2556,7 @@ Parser::statements(bool *hasFunctionStmt)
return null();
}
- addStatementToList(pn, next, hasFunctionStmt);
+ addStatementToList(pn, next);
}
/*
@@ -2993,7 +2965,7 @@ Parser::bindDestructuringVar(BindData *data,
if (data->op == JSOP_DEFCONST)
pn->pn_dflags |= PND_CONST;
- handler.noteLValue(pn);
+ pn->markAsAssigned();
return true;
}
@@ -3021,7 +2993,7 @@ Parser::bindDestructuringLHS(ParseNode *pn)
{
switch (pn->getKind()) {
case PNK_NAME:
- handler.noteLValue(pn);
+ pn->markAsAssigned();
/* FALL THROUGH */
case PNK_DOT:
@@ -3105,8 +3077,7 @@ Parser::checkDestructuring(BindData *data,
if (left->isKind(PNK_ARRAY)) {
for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) {
- /* Nullary comma is an elision; binary comma is an expression.*/
- if (!pn->isArrayHole()) {
+ if (!pn->isKind(PNK_ELISION)) {
if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
ok = checkDestructuring(data, pn, false);
} else {
@@ -3542,7 +3513,10 @@ Parser::switchStatement()
bool seenDefault = false;
TokenKind tt;
while ((tt = tokenStream.getToken()) != TOK_RC) {
- Node casepn;
+ uint32_t caseBegin = tokenStream.currentToken().pos.begin;
+
+ ParseNodeKind caseKind;
+ Node caseExpr;
switch (tt) {
case TOK_DEFAULT:
if (seenDefault) {
@@ -3550,21 +3524,16 @@ Parser::switchStatement()
return null();
}
seenDefault = true;
- casepn = handler.newBinary(PNK_DEFAULT);
- if (!casepn)
- return null();
+ caseKind = PNK_DEFAULT;
+ caseExpr = null();
break;
case TOK_CASE:
- {
- Node left = expr();
- if (!left)
- return null();
- casepn = handler.newBinary(PNK_CASE, left);
- if (!casepn)
+ caseKind = PNK_CASE;
+ caseExpr = expr();
+ if (!caseExpr)
return null();
break;
- }
case TOK_ERROR:
return null();
@@ -3574,8 +3543,6 @@ Parser::switchStatement()
return null();
}
- handler.addList(caseList, casepn);
-
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
Node body = handler.newList(PNK_STATEMENTLIST);
@@ -3593,7 +3560,10 @@ Parser::switchStatement()
handler.addList(body, stmt);
}
- handler.setBinaryRHS(casepn, body);
+ Node casepn = handler.newCaseOrDefault(caseBegin, caseExpr, body);
+ if (!casepn)
+ return null();
+ handler.addList(caseList, casepn);
}
/*
@@ -3916,7 +3886,7 @@ Parser::forStatement()
switch (pn2->getKind()) {
case PNK_NAME:
/* Beware 'for (arguments in ...)' with or without a 'var'. */
- handler.noteLValue(pn2);
+ pn2->markAsAssigned();
break;
#if JS_HAS_DESTRUCTURING
@@ -4099,6 +4069,7 @@ Parser::forStatement()
/* Check that the left side of the 'in' or 'of' is valid. */
if (!forDecl &&
lhsNode != SyntaxParseHandler::NodeName &&
+ lhsNode != SyntaxParseHandler::NodeGetProp &&
lhsNode != SyntaxParseHandler::NodeLValue)
{
JS_ALWAYS_FALSE(abortIfSyntaxParser());
@@ -4311,12 +4282,15 @@ Parser::tryStatement()
return pn;
}
-template
-typename ParseHandler::Node
-Parser::withStatement()
+template <>
+ParseNode *
+Parser::withStatement()
{
- if (!abortIfSyntaxParser())
+ if (handler.syntaxParser) {
+ handler.disableSyntaxParser();
+ abortedSyntaxParse = true;
return null();
+ }
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH));
uint32_t begin = tokenStream.currentToken().pos.begin;
@@ -4354,7 +4328,7 @@ Parser::withStatement()
* to safely optimize binding globals (see bug 561923).
*/
for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
- DefinitionNode defn = r.front().value().get();
+ DefinitionNode defn = r.front().value().get();
DefinitionNode lexdep = handler.resolve(defn);
handler.deoptimizeUsesWithin(lexdep,
TokenPos::make(begin, tokenStream.currentToken().pos.begin));
@@ -4369,6 +4343,14 @@ Parser::withStatement()
return pn;
}
+template <>
+SyntaxParseHandler::Node
+Parser::withStatement()
+{
+ JS_ALWAYS_FALSE(abortIfSyntaxParser());
+ return null();
+}
+
#if JS_HAS_BLOCK_SCOPE
template <>
ParseNode *
@@ -4499,6 +4481,35 @@ Parser::letStatement()
#endif // JS_HAS_BLOCK_SCOPE
+template
+typename ParseHandler::Node
+Parser::labeledStatement()
+{
+ uint32_t begin = tokenStream.currentToken().pos.begin;
+ RootedPropertyName label(context, tokenStream.currentToken().name());
+ for (StmtInfoPC *stmt = pc->topStmt; stmt; stmt = stmt->down) {
+ if (stmt->type == STMT_LABEL && stmt->label == label) {
+ report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL);
+ return null();
+ }
+ }
+
+ tokenStream.consumeKnownToken(TOK_COLON);
+
+ /* Push a label struct and parse the statement. */
+ StmtInfoPC stmtInfo(context);
+ PushStatementPC(pc, &stmtInfo, STMT_LABEL);
+ stmtInfo.label = label;
+ Node pn = statement();
+ if (!pn)
+ return null();
+
+ /* Pop the label, set pn_expr, and return early. */
+ PopStatementPC(context, pc);
+
+ return handler.newLabeledStatement(label, pn, begin);
+}
+
template
typename ParseHandler::Node
Parser::expressionStatement()
@@ -4508,37 +4519,6 @@ Parser::expressionStatement()
if (!pn2)
return null();
- if (tokenStream.peekToken() == TOK_COLON) {
- RootedAtom label(context, handler.isName(pn2));
- if (!label) {
- report(ParseError, false, null(), JSMSG_BAD_LABEL);
- return null();
- }
- for (StmtInfoPC *stmt = pc->topStmt; stmt; stmt = stmt->down) {
- if (stmt->type == STMT_LABEL && stmt->label == label) {
- report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL);
- return null();
- }
- }
- ForgetUse(pn2);
-
- (void) tokenStream.getToken();
-
- /* Push a label struct and parse the statement. */
- StmtInfoPC stmtInfo(context);
- PushStatementPC(pc, &stmtInfo, STMT_LABEL);
- stmtInfo.label = label;
- Node pn = statement();
- if (!pn)
- return null();
-
- /* Pop the label, set pn_expr, and return early. */
- PopStatementPC(context, pc);
-
- handler.morphNameIntoLabel(pn2, pn);
- return pn2;
- }
-
Node pn = handler.newUnary(PNK_SEMI, pn2);
/* Check termination of this primitive statement. */
@@ -4566,18 +4546,18 @@ Parser::statement()
if (!cond)
return null();
+ if (tokenStream.peekToken() == TOK_SEMI &&
+ !report(ParseExtraWarning, false, null(), JSMSG_EMPTY_CONSEQUENT))
+ {
+ return null();
+ }
+
StmtInfoPC stmtInfo(context);
PushStatementPC(pc, &stmtInfo, STMT_IF);
Node thenBranch = statement();
if (!thenBranch)
return null();
- if (handler.isEmptySemicolon(thenBranch) &&
- !report(ParseExtraWarning, false, null(), JSMSG_EMPTY_CONSEQUENT))
- {
- return null();
- }
-
Node elseBranch;
if (tokenStream.matchToken(TOK_ELSE, TSF_OPERAND)) {
stmtInfo.type = STMT_ELSE;
@@ -4803,8 +4783,8 @@ Parser::statement()
StmtInfoPC stmtInfo(context);
if (!PushBlocklikeStatement(&stmtInfo, STMT_BLOCK, pc))
return null();
- bool hasFunctionStmt;
- pn = statements(&hasFunctionStmt);
+
+ pn = statements();
if (!pn)
return null();
@@ -4827,12 +4807,16 @@ Parser::statement()
case TOK_ERROR:
return null();
- case TOK_NAME:
- if (tokenStream.currentToken().name() == context->names().module &&
- tokenStream.peekTokenSameLine(TSF_OPERAND) == TOK_STRING)
+ case TOK_NAME: {
+ if (tokenStream.peekToken() == TOK_COLON)
+ return labeledStatement();
+ if (tokenStream.currentToken().name() == context->names().module
+ && tokenStream.peekTokenSameLine() == TOK_STRING)
{
return moduleDecl();
}
+ }
+ /* FALL THROUGH */
default:
return expressionStatement();
@@ -5200,7 +5184,7 @@ Parser::setAssignmentLhsOps(ParseNode *pn, JSOp op)
if (!checkStrictAssignment(pn))
return false;
pn->setOp(pn->isOp(JSOP_GETLOCAL) ? JSOP_SETLOCAL : JSOP_SETNAME);
- handler.noteLValue(pn);
+ pn->markAsAssigned();
break;
case PNK_DOT:
pn->setOp(JSOP_SETPROP);
@@ -5235,8 +5219,12 @@ bool
Parser::setAssignmentLhsOps(Node pn, JSOp op)
{
/* Full syntax checking of valid assignment LHS terms requires a parse tree. */
- if (pn != SyntaxParseHandler::NodeName && pn != SyntaxParseHandler::NodeLValue)
+ if (pn != SyntaxParseHandler::NodeName &&
+ pn != SyntaxParseHandler::NodeGetProp &&
+ pn != SyntaxParseHandler::NodeLValue)
+ {
return abortIfSyntaxParser();
+ }
return checkStrictAssignment(pn);
}
@@ -5337,7 +5325,7 @@ Parser::setIncOpKid(ParseNode *pn, ParseNode *kid, TokenKind t
switch (kid->getKind()) {
case PNK_NAME:
- handler.noteLValue(kid);
+ kid->markAsAssigned();
break;
case PNK_CALL:
@@ -5419,8 +5407,12 @@ Parser::checkDeleteExpression(Node *pn)
// Treat deletion of non-lvalues as ambiguous, so that any error associated
// with deleting a call expression is reported.
- if (*pn != SyntaxParseHandler::NodeLValue && strictMode())
+ if (*pn != SyntaxParseHandler::NodeGetProp &&
+ *pn != SyntaxParseHandler::NodeLValue &&
+ strictMode())
+ {
return abortIfSyntaxParser();
+ }
return true;
}
@@ -6444,10 +6436,13 @@ Parser::memberExpr(TokenKind tt, bool allowCallSyntax)
}
} else if (JSAtom *atom = handler.isGetProp(lhs)) {
/* Select JSOP_FUNAPPLY given foo.apply(...). */
- if (atom == context->names().apply)
+ if (atom == context->names().apply) {
handler.setOp(nextMember, JSOP_FUNAPPLY);
- else if (atom == context->names().call)
+ if (pc->sc->isFunctionBox())
+ pc->sc->asFunctionBox()->usesApply = true;
+ } else if (atom == context->names().call) {
handler.setOp(nextMember, JSOP_FUNCALL);
+ }
}
handler.setBeginPosition(nextMember, lhs);
@@ -6551,7 +6546,17 @@ template <>
SyntaxParseHandler::Node
Parser::newRegExp(const jschar *buf, size_t length, RegExpFlag flags)
{
- return SyntaxParseHandler::NodeGeneric;
+ // Create the regexp even when doing a syntax parse, to check the regexp's syntax.
+ const StableCharPtr chars(buf, length);
+ RegExpStatics *res = context->regExpStatics();
+
+ RegExpObject *reobj;
+ if (context->hasfp())
+ reobj = RegExpObject::create(context, res, chars.get(), length, flags, &tokenStream);
+ else
+ reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream);
+
+ return reobj ? SyntaxParseHandler::NodeGeneric : SyntaxParseHandler::NodeFailure;
}
template
@@ -6601,9 +6606,8 @@ Parser::primaryExpr(TokenKind tt)
break;
if (tt == TOK_COMMA) {
- /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */
tokenStream.matchToken(TOK_COMMA);
- pn2 = handler.newNullary(PNK_COMMA);
+ pn2 = handler.newElision();
if (!pn2)
return null();
handler.setListFlag(pn, PNX_SPECIALARRAYINIT | PNX_NONCONST);
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index 4a041f553c47..4f7f361984c2 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -421,10 +421,11 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
Node moduleDecl();
Node functionStmt();
Node functionExpr();
- Node statements(bool *hasFunctionStmt = NULL);
+ Node statements();
Node switchStatement();
Node forStatement();
+ Node labeledStatement();
Node tryStatement();
Node withStatement();
#if JS_HAS_BLOCK_SCOPE
@@ -482,7 +483,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
bool setAssignmentLhsOps(Node pn, JSOp op);
bool matchInOrOf(bool *isForOfp);
- void addStatementToList(Node pn, Node kid, bool *hasFunctionStmt);
+ void addStatementToList(Node pn, Node kid);
bool checkFunctionArguments();
bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom);
bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind,
diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h
index ae17cf1e3a2e..0585971a12b5 100644
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -184,9 +184,9 @@ class GlobalSharedContext : public SharedContext
JSObject *scopeChain() const { return scopeChain_; }
};
-
-class ModuleBox : public ObjectBox, public SharedContext {
-public:
+class ModuleBox : public ObjectBox, public SharedContext
+{
+ public:
Bindings bindings;
ModuleBox(JSContext *cx, ObjectBox *traceListHead, Module *module,
@@ -210,6 +210,10 @@ class FunctionBox : public ObjectBox, public SharedContext
bool useAsm:1; /* function contains "use asm" directive */
bool insideUseAsm:1; /* nested function of function of "use asm" directive */
+ // Fields for use in heuristics.
+ bool usesArguments:1; /* contains a free use of 'arguments' */
+ bool usesApply:1; /* contains an f.apply() call */
+
FunctionContextFlags funCxFlags;
template
diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
index 19f411f5becc..3a6d17d5aff4 100644
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -32,6 +32,7 @@ class SyntaxParseHandler
NodeFailure = 0,
NodeGeneric,
NodeName,
+ NodeGetProp,
NodeString,
NodeStringExprStatement,
NodeLValue
@@ -70,7 +71,7 @@ class SyntaxParseHandler
Node newNullLiteral(const TokenPos &pos) { return NodeGeneric; }
Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; }
- Node newNullary(ParseNodeKind kind) { return NodeGeneric; }
+ Node newElision() { return NodeGeneric; }
Node newUnary(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
if (kind == PNK_SEMI && kid == NodeString)
@@ -89,12 +90,17 @@ class SyntaxParseHandler
ParseContext *pc, JSOp op = JSOP_NOP) {
return NodeGeneric;
}
- void setBinaryRHS(Node pn, Node rhs) {}
Node newTernary(ParseNodeKind kind, Node first, Node second, Node third, JSOp op = JSOP_NOP) {
return NodeGeneric;
}
+ Node newLabeledStatement(PropertyName *label, Node stmt, uint32_t begin) {
+ return NodeGeneric;
+ }
+ Node newCaseOrDefault(uint32_t begin, Node expr, Node body) {
+ return NodeGeneric;
+ }
Node newBreak(PropertyName *label, uint32_t begin, uint32_t end) {
return NodeGeneric;
}
@@ -102,13 +108,16 @@ class SyntaxParseHandler
return NodeGeneric;
}
Node newDebuggerStatement(const TokenPos &pos) { return NodeGeneric; }
- Node newPropertyAccess(Node pn, PropertyName *name, uint32_t end) { return NodeLValue; }
+ Node newPropertyAccess(Node pn, PropertyName *name, uint32_t end)
+ {
+ lastAtom = name;
+ return NodeGetProp;
+ }
Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeLValue; }
bool addCatchBlock(Node catchList, Node letBlock,
Node catchName, Node catchGuard, Node catchBody) { return true; }
- void morphNameIntoLabel(Node name, Node statement) {}
void setLeaveBlockResult(Node block, Node kid, bool leaveBlockExpr) {}
void setLastFunctionArgumentDefault(Node funcpn, Node pn) {}
@@ -124,7 +133,6 @@ class SyntaxParseHandler
return false;
}
- void noteLValue(Node pn) {}
bool finishInitializerAssignment(Node pn, Node init, JSOp op) { return true; }
void setBeginPosition(Node pn, Node oth) {}
@@ -159,7 +167,9 @@ class SyntaxParseHandler
PropertyName *isName(Node pn) {
return (pn == NodeName) ? lastAtom->asPropertyName() : NULL;
}
- PropertyName *isGetProp(Node pn) { return NULL; }
+ PropertyName *isGetProp(Node pn) {
+ return (pn == NodeGetProp) ? lastAtom->asPropertyName() : NULL;
+ }
JSAtom *isStringExprStatement(Node pn, TokenPos *pos) {
if (pn == NodeStringExprStatement) {
*pos = lastStringPos;
@@ -167,7 +177,6 @@ class SyntaxParseHandler
}
return NULL;
}
- bool isEmptySemicolon(Node pn) { return false; }
Node makeAssignment(Node pn, Node rhs) { return NodeGeneric; }
diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp
index e658b8bbef78..6c83d6434afa 100644
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -557,7 +557,7 @@ TokenStream::advance(size_t position)
void
TokenStream::tell(Position *pos)
{
- pos->buf = userbuf.addressOfNextRawChar();
+ pos->buf = userbuf.addressOfNextRawChar(/* allowPoisoned = */ true);
pos->flags = flags;
pos->lineno = lineno;
pos->linebase = linebase;
@@ -571,7 +571,7 @@ TokenStream::tell(Position *pos)
void
TokenStream::seek(const Position &pos)
{
- userbuf.setAddressOfNextRawChar(pos.buf);
+ userbuf.setAddressOfNextRawChar(pos.buf, /* allowPoisoned = */ true);
flags = pos.flags;
lineno = pos.lineno;
linebase = pos.linebase;
@@ -587,6 +587,7 @@ void
TokenStream::seek(const Position &pos, const TokenStream &other)
{
srcCoords.fill(other.srcCoords);
+ lastFunctionKeyword = other.lastFunctionKeyword;
seek(pos);
}
diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
index 941b6401dbe3..278a2360cc3e 100644
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -832,14 +832,14 @@ class MOZ_STACK_CLASS TokenStream
ptr--;
}
- const jschar *addressOfNextRawChar() const {
- JS_ASSERT(ptr); /* make sure haven't been poisoned */
+ const jschar *addressOfNextRawChar(bool allowPoisoned = false) const {
+ JS_ASSERT_IF(!allowPoisoned, ptr); /* make sure haven't been poisoned */
return ptr;
}
/* Use this with caution! */
- void setAddressOfNextRawChar(const jschar *a) {
- JS_ASSERT(a);
+ void setAddressOfNextRawChar(const jschar *a, bool allowPoisoned = false) {
+ JS_ASSERT_IF(!allowPoisoned, a);
ptr = a;
}
diff --git a/js/src/gc/Iteration.cpp b/js/src/gc/Iteration.cpp
index 76693e5fecff..9421fd9f8882 100644
--- a/js/src/gc/Iteration.cpp
+++ b/js/src/gc/Iteration.cpp
@@ -12,7 +12,6 @@
#include "js/HashTable.h"
#include "gc/GCInternals.h"
-#include "jsobjinlines.h"
#include "jsgcinlines.h"
using namespace js;
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index 05748691f39f..de6ba90068aa 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -10,12 +10,12 @@
#include "jsstr.h"
#include "gc/Marking.h"
-#include "gc/Nursery-inl.h"
+#include "ion/IonCode.h"
#include "vm/Shape.h"
-#include "jsobjinlines.h"
+#include "jscompartmentinlines.h"
-#include "ion/IonCode.h"
+#include "gc/Nursery-inl.h"
#include "vm/Shape-inl.h"
#include "vm/String-inl.h"
diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp
index 1666fcd640f4..f16c685710f8 100644
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -19,6 +19,7 @@
#include "frontend/BytecodeCompiler.h"
#include "gc/GCInternals.h"
#include "gc/Marking.h"
+#include "ion/IonCode.h"
#ifdef JS_ION
# include "ion/IonMacroAssembler.h"
# include "ion/IonFrameIterator.h"
@@ -28,7 +29,6 @@
#include "jsgcinlines.h"
#include "jsobjinlines.h"
-#include "ion/IonCode.h"
#ifdef MOZ_VALGRIND
# include
diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp
index 6273f3e56fe2..bb15dddbdde3 100644
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -16,7 +16,6 @@
#include "js/HashTable.h"
#include "gc/GCInternals.h"
-#include "jsobjinlines.h"
#include "jsgcinlines.h"
#ifdef MOZ_VALGRIND
diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
index 28fcb0602fc4..ff75dac9846f 100644
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -19,7 +19,6 @@
#include "ion/Ion.h"
#endif
-#include "jsobjinlines.h"
#include "jsgcinlines.h"
using namespace js;
diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp
index 378ae3f3c412..c54d503f36fc 100644
--- a/js/src/ion/AsmJS.cpp
+++ b/js/src/ion/AsmJS.cpp
@@ -11,7 +11,6 @@
#include "ion/AsmJS.h"
#include "ion/AsmJSModule.h"
-#include "jsobjinlines.h"
#include "frontend/ParseNode-inl.h"
using namespace js;
@@ -168,15 +167,13 @@ LoopControlMaybeLabel(ParseNode *pn)
static inline PropertyName *
LabeledStatementLabel(ParseNode *pn)
{
- JS_ASSERT(pn->isKind(PNK_COLON));
- return pn->pn_atom->asPropertyName();
+ return pn->as().label();
}
static inline ParseNode *
LabeledStatementStatement(ParseNode *pn)
{
- JS_ASSERT(pn->isKind(PNK_COLON));
- return pn->expr();
+ return pn->as().statement();
}
static double
@@ -1501,9 +1498,8 @@ class MOZ_STACK_CLASS ModuleCompiler
JSAutoByteString name;
if (!js_AtomToPrintableString(cx_, func.name, &name))
return;
- slowFuns.reset(JS_smprintf("%s%s:%u:%u (%ums, %g%%)%s", slowFuns.get(),
+ slowFuns.reset(JS_smprintf("%s%s:%u:%u (%ums)%s", slowFuns.get(),
name.ptr(), func.line, func.column, func.ms,
- double(func.ms)/double(msTotal),
i+1 < slowFunctions_.length() ? ", " : ""));
if (!slowFuns)
return;
@@ -4353,7 +4349,7 @@ CheckDoWhile(FunctionCompiler &f, ParseNode *whileStmt, const LabelVector *maybe
static bool
CheckLabel(FunctionCompiler &f, ParseNode *labeledStmt, LabelVector *maybeLabels)
{
- JS_ASSERT(labeledStmt->isKind(PNK_COLON));
+ JS_ASSERT(labeledStmt->isKind(PNK_LABEL));
PropertyName *label = LabeledStatementLabel(labeledStmt);
ParseNode *stmt = LabeledStatementStatement(labeledStmt);
@@ -4624,7 +4620,7 @@ CheckStatement(FunctionCompiler &f, ParseNode *stmt, LabelVector *maybeLabels)
case PNK_WHILE: return CheckWhile(f, stmt, maybeLabels);
case PNK_FOR: return CheckFor(f, stmt, maybeLabels);
case PNK_DOWHILE: return CheckDoWhile(f, stmt, maybeLabels);
- case PNK_COLON: return CheckLabel(f, stmt, maybeLabels);
+ case PNK_LABEL: return CheckLabel(f, stmt, maybeLabels);
case PNK_IF: return CheckIf(f, stmt);
case PNK_SWITCH: return CheckSwitch(f, stmt);
case PNK_RETURN: return CheckReturn(f, stmt);
@@ -6264,7 +6260,7 @@ AsmJSModule::~AsmJSModule()
if (!exitDatum.fun)
continue;
- if (!exitDatum.fun->isInterpreted())
+ if (!exitDatum.fun->hasScript())
continue;
JSScript *script = exitDatum.fun->nonLazyScript();
diff --git a/js/src/ion/BaselineIC.cpp b/js/src/ion/BaselineIC.cpp
index 871d92018b37..6a5fcb9f188c 100644
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -1324,6 +1324,9 @@ ICUpdatedStub::addUpdateStubForValue(JSContext *cx, HandleScript script, HandleO
return true;
}
+ if (!obj->getType(cx))
+ return false;
+
types::EnsureTrackPropertyTypes(cx, obj, id);
if (val.isPrimitive()) {
diff --git a/js/src/ion/BaselineIC.h b/js/src/ion/BaselineIC.h
index 8f61016075cb..128283c48601 100644
--- a/js/src/ion/BaselineIC.h
+++ b/js/src/ion/BaselineIC.h
@@ -2717,7 +2717,7 @@ class ICUnaryArith_Double : public ICStub
friend class ICStubSpace;
ICUnaryArith_Double(IonCode *stubCode)
- : ICStub(UnaryArith_Int32, stubCode)
+ : ICStub(UnaryArith_Double, stubCode)
{}
public:
@@ -2733,7 +2733,7 @@ class ICUnaryArith_Double : public ICStub
public:
Compiler(JSContext *cx, JSOp op)
- : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op)
+ : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op)
{}
ICStub *getStub(ICStubSpace *space) {
diff --git a/js/src/ion/BytecodeAnalysis.cpp b/js/src/ion/BytecodeAnalysis.cpp
index 4a9a1be05596..c2f978fc8f53 100644
--- a/js/src/ion/BytecodeAnalysis.cpp
+++ b/js/src/ion/BytecodeAnalysis.cpp
@@ -7,7 +7,6 @@
#include "ion/BytecodeAnalysis.h"
#include "jsopcode.h"
#include "jsopcodeinlines.h"
-#include "jsobjinlines.h"
using namespace js;
using namespace js::ion;
diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp
index 53e18ba9d6c7..a8b5b8df7eb4 100644
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1694,6 +1694,10 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
return true;
}
+ // The calleereg is known to be a non-native function, but might point to
+ // a LazyScript instead of a JSScript.
+ masm.branchIfFunctionHasNoScript(calleereg, &uncompiled);
+
// Knowing that calleereg is a non-native function, load the JSScript.
masm.loadPtr(Address(calleereg, JSFunction::offsetOfNativeOrScript()), objreg);
diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp
index 4e829bb4a2df..1990a4fb89dc 100644
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -40,9 +40,12 @@
# include "arm/Lowering-arm.h"
#endif
#include "gc/Marking.h"
+
+#include "jscompartmentinlines.h"
#include "jsgcinlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
+
+#include "gc/Barrier-inl.h"
#include "vm/Stack-inl.h"
#include "ion/IonFrames-inl.h"
#include "ion/CompilerRoot.h"
diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp
index 4d8786b3b11a..defa2286ded3 100644
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -200,6 +200,8 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
targets.clear();
return true;
}
+ if (!typeObj->interpretedFunction->getOrCreateScript(cx))
+ return false;
DebugOnly appendOk = targets.append(typeObj->interpretedFunction);
JS_ASSERT(appendOk);
@@ -6264,8 +6266,11 @@ IonBuilder::jsop_getelem()
if (ElementAccessIsDenseNative(obj, index)) {
// Don't generate a fast path if there have been bounds check failures
// and this access might be on a sparse property.
- if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_)
- return jsop_getelem_dense();
+ if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_) {
+ MDefinition *id = current->pop();
+ MDefinition *obj = current->pop();
+ return jsop_getelem_dense(GetElem_Normal, obj, id);
+ }
}
int arrayType = TypedArray::TYPE_MAX;
@@ -6330,11 +6335,8 @@ IonBuilder::jsop_getelem()
}
bool
-IonBuilder::jsop_getelem_dense()
+IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefinition *id)
{
- MDefinition *id = current->pop();
- MDefinition *obj = current->pop();
-
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
if (JSOp(*pc) == JSOP_CALLELEM && !id->mightBeType(MIRType_String) && types->noConstraints()) {
@@ -6351,6 +6353,7 @@ IonBuilder::jsop_getelem_dense()
// undefined values have been observed at this access site and the access
// cannot hit another indexed property on the object or its prototypes.
bool readOutOfBounds =
+ safety == GetElem_Normal &&
types->hasType(types::Type::UndefinedType()) &&
!ElementAccessHasExtraIndexedProperty(cx, obj);
@@ -6387,9 +6390,6 @@ IonBuilder::jsop_getelem_dense()
if (loadDouble)
elements = addConvertElementsToDoubles(elements);
- MInitializedLength *initLength = MInitializedLength::New(elements);
- current->add(initLength);
-
MInstruction *load;
if (!readOutOfBounds) {
@@ -6397,14 +6397,28 @@ IonBuilder::jsop_getelem_dense()
// in-bounds elements, and the array is packed or its holes are not
// read. This is the best case: we can separate the bounds check for
// hoisting.
- id = addBoundsCheck(id, initLength);
+ switch (safety) {
+ case GetElem_Normal: {
+ MInitializedLength *initLength = MInitializedLength::New(elements);
+ current->add(initLength);
+ id = addBoundsCheck(id, initLength);
+ break;
+ }
- load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble);
+ case GetElem_Unsafe: break;
+ case GetElem_UnsafeImmutable: break;
+ }
+
+ bool knownImmutable = (safety == GetElem_UnsafeImmutable);
+ load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble,
+ knownImmutable);
current->add(load);
} else {
// This load may return undefined, so assume that we *can* read holes,
// or that we can read out-of-bounds accesses. In this case, the bounds
// check is part of the opcode.
+ MInitializedLength *initLength = MInitializedLength::New(elements);
+ current->add(initLength);
load = MLoadElementHole::New(elements, id, initLength, needsHoleCheck);
current->add(load);
diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h
index e1a47e2c01da..d918f84eca56 100644
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -41,6 +41,20 @@ class IonBuilder : public MIRGenerator
SetElem_Unsafe,
};
+ enum GetElemSafety {
+ // Normal read like a[b]
+ GetElem_Normal,
+
+ // Read due to UnsafeGetElement:
+ // - assumed to be in bounds,
+ GetElem_Unsafe,
+
+ // Read due to UnsafeGetImmutableElement:
+ // - assumed to be in bounds,
+ // - assumed not to alias any stores
+ GetElem_UnsafeImmutable,
+ };
+
struct DeferredEdge : public TempObject
{
MBasicBlock *block;
@@ -391,7 +405,7 @@ class IonBuilder : public MIRGenerator
bool jsop_intrinsic(HandlePropertyName name);
bool jsop_bindname(PropertyName *name);
bool jsop_getelem();
- bool jsop_getelem_dense();
+ bool jsop_getelem_dense(GetElemSafety safety, MDefinition *object, MDefinition *index);
bool jsop_getelem_typed(int arrayType);
bool jsop_getelem_typed_static(bool *psucceeded);
bool jsop_getelem_string();
@@ -486,6 +500,8 @@ class IonBuilder : public MIRGenerator
InliningStatus inlineUnsafeSetElement(CallInfo &callInfo);
bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base);
bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, int arrayType);
+ InliningStatus inlineUnsafeGetElement(CallInfo &callInfo,
+ GetElemSafety safety);
InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
InliningStatus inlineNewDenseArray(CallInfo &callInfo);
InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp
index 6b66a4abdebd..d5ef296fe055 100644
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -13,7 +13,6 @@
#include "jsanalyze.h"
#include "jsbool.h"
#include "jsnum.h"
-#include "jsobjinlines.h"
#include "shared/Lowering-shared-inl.h"
#include "mozilla/DebugOnly.h"
diff --git a/js/src/ion/MCallOptimize.cpp b/js/src/ion/MCallOptimize.cpp
index e2691532e577..06cb9a79297f 100644
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -90,6 +90,10 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
// Array intrinsics.
if (native == intrinsic_UnsafeSetElement)
return inlineUnsafeSetElement(callInfo);
+ if (native == intrinsic_UnsafeGetElement)
+ return inlineUnsafeGetElement(callInfo, GetElem_Unsafe);
+ if (native == intrinsic_UnsafeGetImmutableElement)
+ return inlineUnsafeGetElement(callInfo, GetElem_UnsafeImmutable);
if (native == intrinsic_NewDenseArray)
return inlineNewDenseArray(callInfo);
@@ -952,9 +956,10 @@ IonBuilder::inlineUnsafeSetElement(CallInfo &callInfo)
/* Important:
*
* Here we inline each of the stores resulting from a call to
- * %UnsafeSetElement(). It is essential that these stores occur
+ * UnsafeSetElement(). It is essential that these stores occur
* atomically and cannot be interrupted by a stack or recursion
* check. If this is not true, race conditions can occur.
+ * See definition of UnsafeSetElement() for more details.
*/
for (uint32_t base = 0; base < argc; base += 3) {
@@ -1053,6 +1058,30 @@ IonBuilder::inlineUnsafeSetTypedArrayElement(CallInfo &callInfo,
return true;
}
+IonBuilder::InliningStatus
+IonBuilder::inlineUnsafeGetElement(CallInfo &callInfo,
+ GetElemSafety safety)
+{
+ JS_ASSERT(safety != GetElem_Normal);
+
+ uint32_t argc = callInfo.argc();
+ if (argc < 2 || callInfo.constructing())
+ return InliningStatus_NotInlined;
+ const uint32_t obj = 0;
+ const uint32_t index = 1;
+ if (!ElementAccessIsDenseNative(callInfo.getArg(obj),
+ callInfo.getArg(index)))
+ return InliningStatus_NotInlined;
+ if (ElementAccessHasExtraIndexedProperty(cx, callInfo.getArg(obj)))
+ return InliningStatus_NotInlined;
+ callInfo.unwrapArgs();
+ if (!jsop_getelem_dense(safety,
+ callInfo.getArg(obj),
+ callInfo.getArg(index)))
+ return InliningStatus_Error;
+ return InliningStatus_Inlined;
+}
+
IonBuilder::InliningStatus
IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo)
{
diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h
index 4450915e2a9c..3a36021cb223 100644
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -4510,11 +4510,13 @@ class MLoadElement
{
bool needsHoleCheck_;
bool loadDoubles_;
+ bool knownImmutable_; // load of data that is known to be immutable
- MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles)
+ MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles, bool knownImmutable)
: MBinaryInstruction(elements, index),
needsHoleCheck_(needsHoleCheck),
- loadDoubles_(loadDoubles)
+ loadDoubles_(loadDoubles),
+ knownImmutable_(knownImmutable)
{
setResultType(MIRType_Value);
setMovable();
@@ -4526,8 +4528,10 @@ class MLoadElement
INSTRUCTION_HEADER(LoadElement)
static MLoadElement *New(MDefinition *elements, MDefinition *index,
- bool needsHoleCheck, bool loadDoubles) {
- return new MLoadElement(elements, index, needsHoleCheck, loadDoubles);
+ bool needsHoleCheck, bool loadDoubles,
+ bool knownImmutable) {
+ return new MLoadElement(elements, index, needsHoleCheck, loadDoubles,
+ knownImmutable);
}
TypePolicy *typePolicy() {
@@ -4549,6 +4553,9 @@ class MLoadElement
return needsHoleCheck();
}
AliasSet getAliasSet() const {
+ if (knownImmutable_)
+ return AliasSet::None();
+
return AliasSet::Load(AliasSet::Element);
}
};
diff --git a/js/src/ion/ParallelArrayAnalysis.cpp b/js/src/ion/ParallelArrayAnalysis.cpp
index 3a34014bda1c..84b40624a1f2 100644
--- a/js/src/ion/ParallelArrayAnalysis.cpp
+++ b/js/src/ion/ParallelArrayAnalysis.cpp
@@ -856,14 +856,18 @@ GetPossibleCallees(JSContext *cx,
if (!rootedFun->isInterpreted())
continue;
- if (rootedFun->nonLazyScript()->shouldCloneAtCallsite) {
+ rootedScript = rootedFun->getOrCreateScript(cx);
+ if (!rootedScript)
+ return false;
+
+ if (rootedScript->shouldCloneAtCallsite) {
rootedFun = CloneFunctionAtCallsite(cx, rootedFun, script, pc);
if (!rootedFun)
return false;
+ rootedScript = rootedFun->nonLazyScript();
}
// check if this call target is already known
- rootedScript = rootedFun->nonLazyScript();
if (!AddCallTarget(rootedScript, targets))
return false;
}
diff --git a/js/src/ion/ParallelFunctions.cpp b/js/src/ion/ParallelFunctions.cpp
index c1572f07ce29..f05894ac1490 100644
--- a/js/src/ion/ParallelFunctions.cpp
+++ b/js/src/ion/ParallelFunctions.cpp
@@ -434,6 +434,8 @@ ion::ParCallToUncompiledScript(JSFunction *func)
JSScript *script = func->nonLazyScript();
Spew(SpewBailouts, "Call to uncompiled script: %p:%s:%d",
script, script->filename(), script->lineno);
+ } else if (func->isInterpretedLazy()) {
+ Spew(SpewBailouts, "Call to uncompiled lazy script");
} else if (func->isBoundFunction()) {
int depth = 0;
JSFunction *target = func->getBoundFunctionTarget()->toFunction();
diff --git a/js/src/ion/RangeAnalysis.cpp b/js/src/ion/RangeAnalysis.cpp
index fb7db64a222a..e374b2cd69ee 100644
--- a/js/src/ion/RangeAnalysis.cpp
+++ b/js/src/ion/RangeAnalysis.cpp
@@ -85,11 +85,6 @@ using mozilla::IsNegative;
// after range analysis is performed. The remaining compiler phases do not ever
// encounter beta nodes.
-RangeAnalysis::RangeAnalysis(MIRGraph &graph)
- : graph_(graph)
-{
-}
-
static bool
IsDominatedUse(MBasicBlock *block, MUse *use)
{
@@ -749,7 +744,13 @@ void
MTruncateToInt32::computeRange()
{
Range input(getOperand(0));
- setRange(new Range(input.lower(), input.upper()));
+ int32_t lower = input.lower();
+ int32_t upper = input.upper();
+ if (input.isLowerInfinite() || input.isUpperInfinite()) {
+ lower = JSVAL_INT_MIN;
+ upper = JSVAL_INT_MAX;
+ }
+ setRange(new Range(lower, upper));
}
void
diff --git a/js/src/ion/RangeAnalysis.h b/js/src/ion/RangeAnalysis.h
index 93e0206ec079..0dc1206eb8ce 100644
--- a/js/src/ion/RangeAnalysis.h
+++ b/js/src/ion/RangeAnalysis.h
@@ -78,7 +78,8 @@ class RangeAnalysis
MIRGraph &graph_;
public:
- RangeAnalysis(MIRGraph &graph);
+ MOZ_CONSTEXPR RangeAnalysis(MIRGraph &graph) :
+ graph_(graph) {}
bool addBetaNobes();
bool analyze();
bool removeBetaNobes();
diff --git a/js/src/ion/RegisterAllocator.h b/js/src/ion/RegisterAllocator.h
index fe76b3504ee9..751479175827 100644
--- a/js/src/ion/RegisterAllocator.h
+++ b/js/src/ion/RegisterAllocator.h
@@ -7,6 +7,8 @@
#ifndef js_ion_registerallocator_h__
#define js_ion_registerallocator_h__
+#include "mozilla/Attributes.h"
+
#include "Ion.h"
#include "MIR.h"
#include "MIRGraph.h"
@@ -140,7 +142,7 @@ struct AllocationIntegrityState
class CodePosition
{
private:
- CodePosition(const uint32_t &bits)
+ MOZ_CONSTEXPR CodePosition(const uint32_t &bits)
: bits_(bits)
{ }
@@ -159,7 +161,7 @@ class CodePosition
OUTPUT
};
- CodePosition() : bits_(0)
+ MOZ_CONSTEXPR CodePosition() : bits_(0)
{ }
CodePosition(uint32_t instruction, SubPosition where) {
diff --git a/js/src/ion/RegisterSets.h b/js/src/ion/RegisterSets.h
index dc15038b2c86..9bcf0823e4bd 100644
--- a/js/src/ion/RegisterSets.h
+++ b/js/src/ion/RegisterSets.h
@@ -92,7 +92,7 @@ class ValueOperand
Register payload_;
public:
- ValueOperand(Register type, Register payload)
+ MOZ_CONSTEXPR ValueOperand(Register type, Register payload)
: type_(type), payload_(payload)
{ }
@@ -117,7 +117,7 @@ class ValueOperand
Register value_;
public:
- explicit ValueOperand(Register value)
+ explicit MOZ_CONSTEXPR ValueOperand(Register value)
: value_(value)
{ }
@@ -297,13 +297,13 @@ class TypedRegisterSet
uint32_t bits_;
public:
- explicit TypedRegisterSet(uint32_t bits)
+ explicit MOZ_CONSTEXPR TypedRegisterSet(uint32_t bits)
: bits_(bits)
{ }
- TypedRegisterSet() : bits_(0)
+ MOZ_CONSTEXPR TypedRegisterSet() : bits_(0)
{ }
- TypedRegisterSet(const TypedRegisterSet &set) : bits_(set.bits_)
+ MOZ_CONSTEXPR TypedRegisterSet(const TypedRegisterSet &set) : bits_(set.bits_)
{ }
static inline TypedRegisterSet All() {
@@ -471,7 +471,7 @@ class RegisterSet {
public:
RegisterSet()
{ }
- RegisterSet(const GeneralRegisterSet &gpr, const FloatRegisterSet &fpu)
+ MOZ_CONSTEXPR RegisterSet(const GeneralRegisterSet &gpr, const FloatRegisterSet &fpu)
: gpr_(gpr),
fpu_(fpu)
{ }
@@ -579,10 +579,10 @@ class RegisterSet {
gpr_.clear();
fpu_.clear();
}
- GeneralRegisterSet gprs() const {
+ MOZ_CONSTEXPR GeneralRegisterSet gprs() const {
return gpr_;
}
- FloatRegisterSet fpus() const {
+ MOZ_CONSTEXPR FloatRegisterSet fpus() const {
return fpu_;
}
bool operator ==(const RegisterSet &other) const {
diff --git a/js/src/ion/arm/Assembler-arm.cpp b/js/src/ion/arm/Assembler-arm.cpp
index 42afb5a0a2f4..798933656f07 100644
--- a/js/src/ion/arm/Assembler-arm.cpp
+++ b/js/src/ion/arm/Assembler-arm.cpp
@@ -2791,5 +2791,12 @@ AutoFlushCache::flushAnyway()
}
used_ = false;
}
-
+InstructionIterator::InstructionIterator(Instruction *i_) : i(i_) {
+ const PoolHeader *ph;
+ // If this is a guard, and the next instruction is a header, always work around the pool
+ // If it isn't a guard, then start looking ahead.
+ if (InstIsGuard(i, &ph)) {
+ i = i->next();
+ }
+}
Assembler *Assembler::dummy = NULL;
diff --git a/js/src/ion/arm/Assembler-arm.h b/js/src/ion/arm/Assembler-arm.h
index 68acd6338f16..5e2dfe8d8f13 100644
--- a/js/src/ion/arm/Assembler-arm.h
+++ b/js/src/ion/arm/Assembler-arm.h
@@ -7,6 +7,7 @@
#ifndef jsion_cpu_arm_assembler_h__
#define jsion_cpu_arm_assembler_h__
+#include "mozilla/Attributes.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Util.h"
@@ -26,44 +27,44 @@ namespace ion {
// clearer than bl r14). HOWEVER, this register can
// easily be a gpr when it is not busy holding the return
// address.
-static const Register r0 = { Registers::r0 };
-static const Register r1 = { Registers::r1 };
-static const Register r2 = { Registers::r2 };
-static const Register r3 = { Registers::r3 };
-static const Register r4 = { Registers::r4 };
-static const Register r5 = { Registers::r5 };
-static const Register r6 = { Registers::r6 };
-static const Register r7 = { Registers::r7 };
-static const Register r8 = { Registers::r8 };
-static const Register r9 = { Registers::r9 };
-static const Register r10 = { Registers::r10 };
-static const Register r11 = { Registers::r11 };
-static const Register r12 = { Registers::ip };
-static const Register ip = { Registers::ip };
-static const Register sp = { Registers::sp };
-static const Register r14 = { Registers::lr };
-static const Register lr = { Registers::lr };
-static const Register pc = { Registers::pc };
+static const MOZ_CONSTEXPR Register r0 = { Registers::r0 };
+static const MOZ_CONSTEXPR Register r1 = { Registers::r1 };
+static const MOZ_CONSTEXPR Register r2 = { Registers::r2 };
+static const MOZ_CONSTEXPR Register r3 = { Registers::r3 };
+static const MOZ_CONSTEXPR Register r4 = { Registers::r4 };
+static const MOZ_CONSTEXPR Register r5 = { Registers::r5 };
+static const MOZ_CONSTEXPR Register r6 = { Registers::r6 };
+static const MOZ_CONSTEXPR Register r7 = { Registers::r7 };
+static const MOZ_CONSTEXPR Register r8 = { Registers::r8 };
+static const MOZ_CONSTEXPR Register r9 = { Registers::r9 };
+static const MOZ_CONSTEXPR Register r10 = { Registers::r10 };
+static const MOZ_CONSTEXPR Register r11 = { Registers::r11 };
+static const MOZ_CONSTEXPR Register r12 = { Registers::ip };
+static const MOZ_CONSTEXPR Register ip = { Registers::ip };
+static const MOZ_CONSTEXPR Register sp = { Registers::sp };
+static const MOZ_CONSTEXPR Register r14 = { Registers::lr };
+static const MOZ_CONSTEXPR Register lr = { Registers::lr };
+static const MOZ_CONSTEXPR Register pc = { Registers::pc };
-static const Register ScratchRegister = {Registers::ip};
+static const MOZ_CONSTEXPR Register ScratchRegister = {Registers::ip};
-static const Register OsrFrameReg = r3;
-static const Register ArgumentsRectifierReg = r8;
-static const Register CallTempReg0 = r5;
-static const Register CallTempReg1 = r6;
-static const Register CallTempReg2 = r7;
-static const Register CallTempReg3 = r8;
-static const Register CallTempReg4 = r0;
-static const Register CallTempReg5 = r1;
-static const Register CallTempReg6 = r2;
+static const MOZ_CONSTEXPR Register OsrFrameReg = r3;
+static const MOZ_CONSTEXPR Register ArgumentsRectifierReg = r8;
+static const MOZ_CONSTEXPR Register CallTempReg0 = r5;
+static const MOZ_CONSTEXPR Register CallTempReg1 = r6;
+static const MOZ_CONSTEXPR Register CallTempReg2 = r7;
+static const MOZ_CONSTEXPR Register CallTempReg3 = r8;
+static const MOZ_CONSTEXPR Register CallTempReg4 = r0;
+static const MOZ_CONSTEXPR Register CallTempReg5 = r1;
+static const MOZ_CONSTEXPR Register CallTempReg6 = r2;
-static const Register IntArgReg0 = r0;
-static const Register IntArgReg1 = r1;
-static const Register IntArgReg2 = r2;
-static const Register IntArgReg3 = r3;
-static const Register GlobalReg = r10;
-static const Register HeapReg = r11;
-static const Register CallTempNonArgRegs[] = { r5, r6, r7, r8 };
+static const MOZ_CONSTEXPR Register IntArgReg0 = r0;
+static const MOZ_CONSTEXPR Register IntArgReg1 = r1;
+static const MOZ_CONSTEXPR Register IntArgReg2 = r2;
+static const MOZ_CONSTEXPR Register IntArgReg3 = r3;
+static const MOZ_CONSTEXPR Register GlobalReg = r10;
+static const MOZ_CONSTEXPR Register HeapReg = r11;
+static const MOZ_CONSTEXPR Register CallTempNonArgRegs[] = { r5, r6, r7, r8 };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
class ABIArgGenerator
@@ -87,37 +88,37 @@ class ABIArgGenerator
};
-static const Register PreBarrierReg = r1;
+static const MOZ_CONSTEXPR Register PreBarrierReg = r1;
-static const Register InvalidReg = { Registers::invalid_reg };
-static const FloatRegister InvalidFloatReg = { FloatRegisters::invalid_freg };
+static const MOZ_CONSTEXPR Register InvalidReg = { Registers::invalid_reg };
+static const MOZ_CONSTEXPR FloatRegister InvalidFloatReg = { FloatRegisters::invalid_freg };
-static const Register JSReturnReg_Type = r3;
-static const Register JSReturnReg_Data = r2;
-static const Register StackPointer = sp;
-static const Register FramePointer = InvalidReg;
-static const Register ReturnReg = r0;
-static const FloatRegister ReturnFloatReg = { FloatRegisters::d0 };
-static const FloatRegister ScratchFloatReg = { FloatRegisters::d1 };
+static const MOZ_CONSTEXPR Register JSReturnReg_Type = r3;
+static const MOZ_CONSTEXPR Register JSReturnReg_Data = r2;
+static const MOZ_CONSTEXPR Register StackPointer = sp;
+static const MOZ_CONSTEXPR Register FramePointer = InvalidReg;
+static const MOZ_CONSTEXPR Register ReturnReg = r0;
+static const MOZ_CONSTEXPR FloatRegister ReturnFloatReg = { FloatRegisters::d0 };
+static const MOZ_CONSTEXPR FloatRegister ScratchFloatReg = { FloatRegisters::d1 };
-static const FloatRegister NANReg = { FloatRegisters::d15 };
+static const MOZ_CONSTEXPR FloatRegister NANReg = { FloatRegisters::d15 };
-static const FloatRegister d0 = {FloatRegisters::d0};
-static const FloatRegister d1 = {FloatRegisters::d1};
-static const FloatRegister d2 = {FloatRegisters::d2};
-static const FloatRegister d3 = {FloatRegisters::d3};
-static const FloatRegister d4 = {FloatRegisters::d4};
-static const FloatRegister d5 = {FloatRegisters::d5};
-static const FloatRegister d6 = {FloatRegisters::d6};
-static const FloatRegister d7 = {FloatRegisters::d7};
-static const FloatRegister d8 = {FloatRegisters::d8};
-static const FloatRegister d9 = {FloatRegisters::d9};
-static const FloatRegister d10 = {FloatRegisters::d10};
-static const FloatRegister d11 = {FloatRegisters::d11};
-static const FloatRegister d12 = {FloatRegisters::d12};
-static const FloatRegister d13 = {FloatRegisters::d13};
-static const FloatRegister d14 = {FloatRegisters::d14};
-static const FloatRegister d15 = {FloatRegisters::d15};
+static const MOZ_CONSTEXPR FloatRegister d0 = {FloatRegisters::d0};
+static const MOZ_CONSTEXPR FloatRegister d1 = {FloatRegisters::d1};
+static const MOZ_CONSTEXPR FloatRegister d2 = {FloatRegisters::d2};
+static const MOZ_CONSTEXPR FloatRegister d3 = {FloatRegisters::d3};
+static const MOZ_CONSTEXPR FloatRegister d4 = {FloatRegisters::d4};
+static const MOZ_CONSTEXPR FloatRegister d5 = {FloatRegisters::d5};
+static const MOZ_CONSTEXPR FloatRegister d6 = {FloatRegisters::d6};
+static const MOZ_CONSTEXPR FloatRegister d7 = {FloatRegisters::d7};
+static const MOZ_CONSTEXPR FloatRegister d8 = {FloatRegisters::d8};
+static const MOZ_CONSTEXPR FloatRegister d9 = {FloatRegisters::d9};
+static const MOZ_CONSTEXPR FloatRegister d10 = {FloatRegisters::d10};
+static const MOZ_CONSTEXPR FloatRegister d11 = {FloatRegisters::d11};
+static const MOZ_CONSTEXPR FloatRegister d12 = {FloatRegisters::d12};
+static const MOZ_CONSTEXPR FloatRegister d13 = {FloatRegisters::d13};
+static const MOZ_CONSTEXPR FloatRegister d14 = {FloatRegisters::d14};
+static const MOZ_CONSTEXPR FloatRegister d15 = {FloatRegisters::d15};
// For maximal awesomeness, 8 should be sufficent.
// ldrd/strd (dual-register load/store) operate in a single cycle
@@ -2061,7 +2062,7 @@ class InstructionIterator {
private:
Instruction *i;
public:
- InstructionIterator(Instruction *i_) : i(i_) {}
+ InstructionIterator(Instruction *i_);
Instruction *next() {
i = i->next();
return cur();
diff --git a/js/src/ion/x64/Assembler-x64.h b/js/src/ion/x64/Assembler-x64.h
index 909327bca425..82874703737b 100644
--- a/js/src/ion/x64/Assembler-x64.h
+++ b/js/src/ion/x64/Assembler-x64.h
@@ -15,39 +15,39 @@
namespace js {
namespace ion {
-static const Register rax = { JSC::X86Registers::eax };
-static const Register rbx = { JSC::X86Registers::ebx };
-static const Register rcx = { JSC::X86Registers::ecx };
-static const Register rdx = { JSC::X86Registers::edx };
-static const Register rsi = { JSC::X86Registers::esi };
-static const Register rdi = { JSC::X86Registers::edi };
-static const Register rbp = { JSC::X86Registers::ebp };
-static const Register r8 = { JSC::X86Registers::r8 };
-static const Register r9 = { JSC::X86Registers::r9 };
-static const Register r10 = { JSC::X86Registers::r10 };
-static const Register r11 = { JSC::X86Registers::r11 };
-static const Register r12 = { JSC::X86Registers::r12 };
-static const Register r13 = { JSC::X86Registers::r13 };
-static const Register r14 = { JSC::X86Registers::r14 };
-static const Register r15 = { JSC::X86Registers::r15 };
-static const Register rsp = { JSC::X86Registers::esp };
+static const MOZ_CONSTEXPR Register rax = { JSC::X86Registers::eax };
+static const MOZ_CONSTEXPR Register rbx = { JSC::X86Registers::ebx };
+static const MOZ_CONSTEXPR Register rcx = { JSC::X86Registers::ecx };
+static const MOZ_CONSTEXPR Register rdx = { JSC::X86Registers::edx };
+static const MOZ_CONSTEXPR Register rsi = { JSC::X86Registers::esi };
+static const MOZ_CONSTEXPR Register rdi = { JSC::X86Registers::edi };
+static const MOZ_CONSTEXPR Register rbp = { JSC::X86Registers::ebp };
+static const MOZ_CONSTEXPR Register r8 = { JSC::X86Registers::r8 };
+static const MOZ_CONSTEXPR Register r9 = { JSC::X86Registers::r9 };
+static const MOZ_CONSTEXPR Register r10 = { JSC::X86Registers::r10 };
+static const MOZ_CONSTEXPR Register r11 = { JSC::X86Registers::r11 };
+static const MOZ_CONSTEXPR Register r12 = { JSC::X86Registers::r12 };
+static const MOZ_CONSTEXPR Register r13 = { JSC::X86Registers::r13 };
+static const MOZ_CONSTEXPR Register r14 = { JSC::X86Registers::r14 };
+static const MOZ_CONSTEXPR Register r15 = { JSC::X86Registers::r15 };
+static const MOZ_CONSTEXPR Register rsp = { JSC::X86Registers::esp };
-static const FloatRegister xmm0 = { JSC::X86Registers::xmm0 };
-static const FloatRegister xmm1 = { JSC::X86Registers::xmm1 };
-static const FloatRegister xmm2 = { JSC::X86Registers::xmm2 };
-static const FloatRegister xmm3 = { JSC::X86Registers::xmm3 };
-static const FloatRegister xmm4 = { JSC::X86Registers::xmm4 };
-static const FloatRegister xmm5 = { JSC::X86Registers::xmm5 };
-static const FloatRegister xmm6 = { JSC::X86Registers::xmm6 };
-static const FloatRegister xmm7 = { JSC::X86Registers::xmm7 };
-static const FloatRegister xmm8 = { JSC::X86Registers::xmm8 };
-static const FloatRegister xmm9 = { JSC::X86Registers::xmm9 };
-static const FloatRegister xmm10 = { JSC::X86Registers::xmm10 };
-static const FloatRegister xmm11 = { JSC::X86Registers::xmm11 };
-static const FloatRegister xmm12 = { JSC::X86Registers::xmm12 };
-static const FloatRegister xmm13 = { JSC::X86Registers::xmm13 };
-static const FloatRegister xmm14 = { JSC::X86Registers::xmm14 };
-static const FloatRegister xmm15 = { JSC::X86Registers::xmm15 };
+static const MOZ_CONSTEXPR FloatRegister xmm0 = { JSC::X86Registers::xmm0 };
+static const MOZ_CONSTEXPR FloatRegister xmm1 = { JSC::X86Registers::xmm1 };
+static const MOZ_CONSTEXPR FloatRegister xmm2 = { JSC::X86Registers::xmm2 };
+static const MOZ_CONSTEXPR FloatRegister xmm3 = { JSC::X86Registers::xmm3 };
+static const MOZ_CONSTEXPR FloatRegister xmm4 = { JSC::X86Registers::xmm4 };
+static const MOZ_CONSTEXPR FloatRegister xmm5 = { JSC::X86Registers::xmm5 };
+static const MOZ_CONSTEXPR FloatRegister xmm6 = { JSC::X86Registers::xmm6 };
+static const MOZ_CONSTEXPR FloatRegister xmm7 = { JSC::X86Registers::xmm7 };
+static const MOZ_CONSTEXPR FloatRegister xmm8 = { JSC::X86Registers::xmm8 };
+static const MOZ_CONSTEXPR FloatRegister xmm9 = { JSC::X86Registers::xmm9 };
+static const MOZ_CONSTEXPR FloatRegister xmm10 = { JSC::X86Registers::xmm10 };
+static const MOZ_CONSTEXPR FloatRegister xmm11 = { JSC::X86Registers::xmm11 };
+static const MOZ_CONSTEXPR FloatRegister xmm12 = { JSC::X86Registers::xmm12 };
+static const MOZ_CONSTEXPR FloatRegister xmm13 = { JSC::X86Registers::xmm13 };
+static const MOZ_CONSTEXPR FloatRegister xmm14 = { JSC::X86Registers::xmm14 };
+static const MOZ_CONSTEXPR FloatRegister xmm15 = { JSC::X86Registers::xmm15 };
// X86-common synonyms.
static const Register eax = rax;
@@ -59,74 +59,74 @@ static const Register edi = rdi;
static const Register ebp = rbp;
static const Register esp = rsp;
-static const Register InvalidReg = { JSC::X86Registers::invalid_reg };
-static const FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
+static const MOZ_CONSTEXPR Register InvalidReg = { JSC::X86Registers::invalid_reg };
+static const MOZ_CONSTEXPR FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
static const Register StackPointer = rsp;
static const Register FramePointer = rbp;
-static const Register JSReturnReg = rcx;
+static const MOZ_CONSTEXPR Register JSReturnReg = rcx;
// Avoid, except for assertions.
-static const Register JSReturnReg_Type = JSReturnReg;
-static const Register JSReturnReg_Data = JSReturnReg;
+static const MOZ_CONSTEXPR Register JSReturnReg_Type = JSReturnReg;
+static const MOZ_CONSTEXPR Register JSReturnReg_Data = JSReturnReg;
-static const Register ReturnReg = rax;
-static const Register ScratchReg = r11;
-static const Register HeapReg = r15;
-static const FloatRegister ReturnFloatReg = xmm0;
-static const FloatRegister ScratchFloatReg = xmm15;
+static const MOZ_CONSTEXPR Register ReturnReg = rax;
+static const MOZ_CONSTEXPR Register ScratchReg = r11;
+static const MOZ_CONSTEXPR Register HeapReg = r15;
+static const MOZ_CONSTEXPR FloatRegister ReturnFloatReg = xmm0;
+static const MOZ_CONSTEXPR FloatRegister ScratchFloatReg = xmm15;
-static const Register ArgumentsRectifierReg = r8;
-static const Register CallTempReg0 = rax;
-static const Register CallTempReg1 = rdi;
-static const Register CallTempReg2 = rbx;
-static const Register CallTempReg3 = rcx;
-static const Register CallTempReg4 = rsi;
-static const Register CallTempReg5 = rdx;
-static const Register CallTempReg6 = rbp;
+static const MOZ_CONSTEXPR Register ArgumentsRectifierReg = r8;
+static const MOZ_CONSTEXPR Register CallTempReg0 = rax;
+static const MOZ_CONSTEXPR Register CallTempReg1 = rdi;
+static const MOZ_CONSTEXPR Register CallTempReg2 = rbx;
+static const MOZ_CONSTEXPR Register CallTempReg3 = rcx;
+static const MOZ_CONSTEXPR Register CallTempReg4 = rsi;
+static const MOZ_CONSTEXPR Register CallTempReg5 = rdx;
+static const MOZ_CONSTEXPR Register CallTempReg6 = rbp;
// Different argument registers for WIN64
#if defined(_WIN64)
-static const Register IntArgReg0 = rcx;
-static const Register IntArgReg1 = rdx;
-static const Register IntArgReg2 = r8;
-static const Register IntArgReg3 = r9;
-static const uint32_t NumIntArgRegs = 4;
-static const Register IntArgRegs[NumIntArgRegs] = { rcx, rdx, r8, r9 };
+static const MOZ_CONSTEXPR Register IntArgReg0 = rcx;
+static constMOZ_CONSTEXPRconstexpr Register IntArgReg1 = rdx;
+static const MOZ_CONSTEXPR Register IntArgReg2 = r8;
+static const MOZ_CONSTEXPR Register IntArgReg3 = r9;
+static constMOZ_CONSTEXPRuint32_t NumIntArgRegs = 4;
+static const MOZ_CONSTEXPR Register IntArgRegs[NumIntArgRegs] = { rcx, rdx, r8, r9 };
-static const Register CallTempNonArgRegs[] = { rax, rdi, rbx, rsi };
+static const MOZ_CONSTEXPR Register CallTempNonArgRegs[] = { rax, rdi, rbx, rsi };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
-static const FloatRegister FloatArgReg0 = xmm0;
-static const FloatRegister FloatArgReg1 = xmm1;
-static const FloatRegister FloatArgReg2 = xmm2;
-static const FloatRegister FloatArgReg3 = xmm3;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg0 = xmm0;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg1 = xmm1;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg2 = xmm2;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg3 = xmm3;
static const uint32_t NumFloatArgRegs = 4;
static const FloatRegister FloatArgRegs[NumFloatArgRegs] = { xmm0, xmm1, xmm2, xmm3 };
#else
-static const Register IntArgReg0 = rdi;
-static const Register IntArgReg1 = rsi;
-static const Register IntArgReg2 = rdx;
-static const Register IntArgReg3 = rcx;
-static const Register IntArgReg4 = r8;
-static const Register IntArgReg5 = r9;
-static const uint32_t NumIntArgRegs = 6;
-static const Register IntArgRegs[NumIntArgRegs] = { rdi, rsi, rdx, rcx, r8, r9 };
+static const MOZ_CONSTEXPR Register IntArgReg0 = rdi;
+static const MOZ_CONSTEXPR Register IntArgReg1 = rsi;
+static const MOZ_CONSTEXPR Register IntArgReg2 = rdx;
+static const MOZ_CONSTEXPR Register IntArgReg3 = rcx;
+static const MOZ_CONSTEXPR Register IntArgReg4 = r8;
+static const MOZ_CONSTEXPR Register IntArgReg5 = r9;
+static const MOZ_CONSTEXPR uint32_t NumIntArgRegs = 6;
+static const MOZ_CONSTEXPR Register IntArgRegs[NumIntArgRegs] = { rdi, rsi, rdx, rcx, r8, r9 };
-static const Register CallTempNonArgRegs[] = { rax, rbx };
+static const MOZ_CONSTEXPR Register CallTempNonArgRegs[] = { rax, rbx };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
-static const FloatRegister FloatArgReg0 = xmm0;
-static const FloatRegister FloatArgReg1 = xmm1;
-static const FloatRegister FloatArgReg2 = xmm2;
-static const FloatRegister FloatArgReg3 = xmm3;
-static const FloatRegister FloatArgReg4 = xmm4;
-static const FloatRegister FloatArgReg5 = xmm5;
-static const FloatRegister FloatArgReg6 = xmm6;
-static const FloatRegister FloatArgReg7 = xmm7;
-static const uint32_t NumFloatArgRegs = 8;
-static const FloatRegister FloatArgRegs[NumFloatArgRegs] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 };
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg0 = xmm0;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg1 = xmm1;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg2 = xmm2;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg3 = xmm3;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg4 = xmm4;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg5 = xmm5;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg6 = xmm6;
+static const MOZ_CONSTEXPR FloatRegister FloatArgReg7 = xmm7;
+static const MOZ_CONSTEXPR uint32_t NumFloatArgRegs = 8;
+static const MOZ_CONSTEXPR FloatRegister FloatArgRegs[NumFloatArgRegs] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 };
#endif
class ABIArgGenerator
@@ -152,9 +152,9 @@ class ABIArgGenerator
static const Register NonVolatileReg;
};
-static const Register OsrFrameReg = IntArgReg3;
+static const MOZ_CONSTEXPR Register OsrFrameReg = IntArgReg3;
-static const Register PreBarrierReg = rdx;
+static const MOZ_CONSTEXPR Register PreBarrierReg = rdx;
// GCC stack is aligned on 16 bytes, but we don't maintain the invariant in
// jitted code.
@@ -265,7 +265,7 @@ namespace js {
namespace ion {
// Return operand from a JS -> JS call.
-static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
+static const MOZ_CONSTEXPR ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
class Assembler : public AssemblerX86Shared
{
diff --git a/js/src/ion/x86/Assembler-x86.h b/js/src/ion/x86/Assembler-x86.h
index 64cfcdccd80f..e9476db4a43e 100644
--- a/js/src/ion/x86/Assembler-x86.h
+++ b/js/src/ion/x86/Assembler-x86.h
@@ -18,46 +18,46 @@
namespace js {
namespace ion {
-static const Register eax = { JSC::X86Registers::eax };
-static const Register ecx = { JSC::X86Registers::ecx };
-static const Register edx = { JSC::X86Registers::edx };
-static const Register ebx = { JSC::X86Registers::ebx };
-static const Register esp = { JSC::X86Registers::esp };
-static const Register ebp = { JSC::X86Registers::ebp };
-static const Register esi = { JSC::X86Registers::esi };
-static const Register edi = { JSC::X86Registers::edi };
+static const MOZ_CONSTEXPR Register eax = { JSC::X86Registers::eax };
+static const MOZ_CONSTEXPR Register ecx = { JSC::X86Registers::ecx };
+static const MOZ_CONSTEXPR Register edx = { JSC::X86Registers::edx };
+static const MOZ_CONSTEXPR Register ebx = { JSC::X86Registers::ebx };
+static const MOZ_CONSTEXPR Register esp = { JSC::X86Registers::esp };
+static const MOZ_CONSTEXPR Register ebp = { JSC::X86Registers::ebp };
+static const MOZ_CONSTEXPR Register esi = { JSC::X86Registers::esi };
+static const MOZ_CONSTEXPR Register edi = { JSC::X86Registers::edi };
-static const FloatRegister xmm0 = { JSC::X86Registers::xmm0 };
-static const FloatRegister xmm1 = { JSC::X86Registers::xmm1 };
-static const FloatRegister xmm2 = { JSC::X86Registers::xmm2 };
-static const FloatRegister xmm3 = { JSC::X86Registers::xmm3 };
-static const FloatRegister xmm4 = { JSC::X86Registers::xmm4 };
-static const FloatRegister xmm5 = { JSC::X86Registers::xmm5 };
-static const FloatRegister xmm6 = { JSC::X86Registers::xmm6 };
-static const FloatRegister xmm7 = { JSC::X86Registers::xmm7 };
+static const MOZ_CONSTEXPR FloatRegister xmm0 = { JSC::X86Registers::xmm0 };
+static const MOZ_CONSTEXPR FloatRegister xmm1 = { JSC::X86Registers::xmm1 };
+static const MOZ_CONSTEXPR FloatRegister xmm2 = { JSC::X86Registers::xmm2 };
+static const MOZ_CONSTEXPR FloatRegister xmm3 = { JSC::X86Registers::xmm3 };
+static const MOZ_CONSTEXPR FloatRegister xmm4 = { JSC::X86Registers::xmm4 };
+static const MOZ_CONSTEXPR FloatRegister xmm5 = { JSC::X86Registers::xmm5 };
+static const MOZ_CONSTEXPR FloatRegister xmm6 = { JSC::X86Registers::xmm6 };
+static const MOZ_CONSTEXPR FloatRegister xmm7 = { JSC::X86Registers::xmm7 };
-static const Register InvalidReg = { JSC::X86Registers::invalid_reg };
-static const FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
+static const MOZ_CONSTEXPR Register InvalidReg = { JSC::X86Registers::invalid_reg };
+static const MOZ_CONSTEXPR FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
-static const Register JSReturnReg_Type = ecx;
-static const Register JSReturnReg_Data = edx;
-static const Register StackPointer = esp;
-static const Register FramePointer = ebp;
-static const Register ReturnReg = eax;
-static const FloatRegister ReturnFloatReg = xmm0;
-static const FloatRegister ScratchFloatReg = xmm7;
+static const MOZ_CONSTEXPR Register JSReturnReg_Type = ecx;
+static const MOZ_CONSTEXPR Register JSReturnReg_Data = edx;
+static const MOZ_CONSTEXPR Register StackPointer = esp;
+static const MOZ_CONSTEXPR Register FramePointer = ebp;
+static const MOZ_CONSTEXPR Register ReturnReg = eax;
+static const MOZ_CONSTEXPR FloatRegister ReturnFloatReg = xmm0;
+static const MOZ_CONSTEXPR FloatRegister ScratchFloatReg = xmm7;
-static const Register ArgumentsRectifierReg = esi;
-static const Register CallTempReg0 = edi;
-static const Register CallTempReg1 = eax;
-static const Register CallTempReg2 = ebx;
-static const Register CallTempReg3 = ecx;
-static const Register CallTempReg4 = esi;
-static const Register CallTempReg5 = edx;
-static const Register CallTempReg6 = ebp;
+static const MOZ_CONSTEXPR Register ArgumentsRectifierReg = esi;
+static const MOZ_CONSTEXPR Register CallTempReg0 = edi;
+static const MOZ_CONSTEXPR Register CallTempReg1 = eax;
+static const MOZ_CONSTEXPR Register CallTempReg2 = ebx;
+static const MOZ_CONSTEXPR Register CallTempReg3 = ecx;
+static const MOZ_CONSTEXPR Register CallTempReg4 = esi;
+static const MOZ_CONSTEXPR Register CallTempReg5 = edx;
+static const MOZ_CONSTEXPR Register CallTempReg6 = ebp;
// We have no arg regs, so our NonArgRegs are just our CallTempReg*
-static const Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx };
+static const MOZ_CONSTEXPR Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx };
static const uint32_t NumCallTempNonArgRegs =
mozilla::ArrayLength(CallTempNonArgRegs);
@@ -78,8 +78,8 @@ class ABIArgGenerator
static const Register NonVolatileReg;
};
-static const Register OsrFrameReg = edx;
-static const Register PreBarrierReg = edx;
+static const MOZ_CONSTEXPR Register OsrFrameReg = edx;
+static const MOZ_CONSTEXPR Register PreBarrierReg = edx;
// GCC stack is aligned on 16 bytes, but we don't maintain the invariant in
// jitted code.
diff --git a/js/src/jit-test/tests/auto-regress/bug827821.js b/js/src/jit-test/tests/auto-regress/bug827821.js
deleted file mode 100644
index 1000e99219b9..000000000000
--- a/js/src/jit-test/tests/auto-regress/bug827821.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Binary: cache/js-dbg-32-795632f0e4fe-linux
-// Flags: --ion-eager
-//
-
-var lfcode = new Array();
-lfcode.push("3");
-lfcode.push("\
- gczeal(2);\
- for (let q = 0; q < 50; ++q) {\
- var w = \"r\".match(/r/);\
- }\
- let (eval) (function (a) {\
- Function = gczeal;\
- })();\
- // .js\
-");
-lfcode.push(" // .js");
-lfcode.push(" // .js");
-lfcode.push(" // .js");
-while (true) {
- var file = lfcode.shift(); if (file == undefined) { break; }
- loadFile(file)
-}
-function loadFile(lfVarx) {
- try {
- if (lfVarx.substr(-3) == ".js") {
- uneval("foo");
- switch (lfRunTypeId) {
- case 3: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
- case 4: eval("(function() { " + lfVarx + " })();"); break;
- }
- } else if (!isNaN(lfVarx)) {
- lfRunTypeId = parseInt(lfVarx);
- }
- } catch (lfVare) {}
-}
diff --git a/js/src/jit-test/tests/basic/functionnames.js b/js/src/jit-test/tests/basic/functionnames.js
index 1f89047143eb..92fbf258c634 100644
--- a/js/src/jit-test/tests/basic/functionnames.js
+++ b/js/src/jit-test/tests/basic/functionnames.js
@@ -36,7 +36,7 @@ var Foo = function (){
assertName(arguments.callee, 'Foo<')
return function(){};
}();
-assertName(Foo, 'Foo');
+assertName(Foo, 'Foo<');
/* various properties and such */
var x = {fox: { bax: function(){} } };
@@ -94,7 +94,7 @@ a.b = function() {
assertName(arguments.callee, 'a.b<');
return { a: function() {} }
}();
-assertName(a.b.a, 'a.b.a');
+assertName(a.b.a, 'a.b<.a');
a = {
b: function(a) {
diff --git a/js/src/jit-test/tests/basic/lazyparse.js b/js/src/jit-test/tests/basic/lazyparse.js
new file mode 100644
index 000000000000..0aff8fe78fab
--- /dev/null
+++ b/js/src/jit-test/tests/basic/lazyparse.js
@@ -0,0 +1,36 @@
+
+function outer() {
+ var xyz = 0;
+ function foo() {
+ function bar() { xyz++; }
+ bar();
+ let x = 3;
+ }
+ foo();
+ assertEq(xyz, 1);
+}
+outer();
+
+function mapfloor(a) {
+ var b = a.map(function(v) {
+ "use strict";
+ try {
+ eval("delete String;");
+ } catch (e) {
+ return e instanceof res;
+ }
+ });
+ var res = "";
+}
+try {
+ mapfloor([1,2]);
+} catch (e) {}
+
+test();
+function test() {
+ try {
+ eval('let(z) { with({}) let y = 3; }');
+ } catch(ex) {
+ (function(x) { return !(x) })(0/0)
+ }
+}
diff --git a/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js b/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js
index 9d282af71c87..e81aeab2e0de 100644
--- a/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js
+++ b/js/src/jit-test/tests/basic/testOOMInAutoEnterCompartment.js
@@ -1,5 +1,3 @@
-foo = evalcx("(function foo() { foo.bar() })");
-foo.bar = evalcx("(function bar() {})");
function fatty() {
try {
@@ -9,4 +7,9 @@ function fatty() {
}
}
-fatty();
+if (!getBuildConfiguration()['root-analysis']) { // >:(
+ foo = evalcx("(function foo() { foo.bar() })");
+ foo.bar = evalcx("(function bar() {})");
+
+ fatty();
+}
diff --git a/js/src/jit-test/tests/modules/nonkeyword.js b/js/src/jit-test/tests/modules/nonkeyword.js
index deab3bb8025c..40dae8e5328d 100644
--- a/js/src/jit-test/tests/modules/nonkeyword.js
+++ b/js/src/jit-test/tests/modules/nonkeyword.js
@@ -4,3 +4,5 @@ module = {};
module.p = 0;
assertEq(this.module.p, 0);
+assertEq(eval('module \n "hello"'), "hello");
+assertEq(eval('module \n "world" \n {}'), "world");
diff --git a/js/src/jsapi-tests/testBug604087.cpp b/js/src/jsapi-tests/testBug604087.cpp
index 4bda71b5e0fd..436d79017512 100644
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -7,7 +7,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
#include "tests.h"
#include "jsobj.h"
#include "jswrapper.h"
diff --git a/js/src/jsapi-tests/testFuncCallback.cpp b/js/src/jsapi-tests/testFuncCallback.cpp
index 924233598f41..fe7bd7e33921 100644
--- a/js/src/jsapi-tests/testFuncCallback.cpp
+++ b/js/src/jsapi-tests/testFuncCallback.cpp
@@ -6,8 +6,6 @@
#include "jsfun.h"
#include "jscntxt.h"
-#include "jsobjinlines.h"
-
#ifdef MOZ_TRACE_JSCALLS
static int depth = 0;
diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
index b17182f988e6..e9328ac1c39e 100644
--- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp
+++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
@@ -9,6 +9,8 @@
#include "jsfriendapi.h"
#include "jscntxt.h"
+#include "vm/ObjectImpl-inl.h"
+
const unsigned BufferSize = 20;
static unsigned FinalizeCalls = 0;
static JSFinalizeStatus StatusBuffer[BufferSize];
diff --git a/js/src/jsapi-tests/testOriginPrincipals.cpp b/js/src/jsapi-tests/testOriginPrincipals.cpp
index 4e0419e79d6a..0b03014bff1a 100644
--- a/js/src/jsapi-tests/testOriginPrincipals.cpp
+++ b/js/src/jsapi-tests/testOriginPrincipals.cpp
@@ -4,7 +4,6 @@
#include "tests.h"
#include "jsdbgapi.h"
-#include "jsobjinlines.h"
JSPrincipals *sOriginPrincipalsInErrorReporter = NULL;
diff --git a/js/src/jsapi-tests/testStringBuffer.cpp b/js/src/jsapi-tests/testStringBuffer.cpp
index ebbd2dff1f61..5b0a219fedbc 100644
--- a/js/src/jsapi-tests/testStringBuffer.cpp
+++ b/js/src/jsapi-tests/testStringBuffer.cpp
@@ -12,8 +12,6 @@
#include "vm/StringBuffer.h"
-#include "jsobjinlines.h"
-
BEGIN_TEST(testStringBuffer_finishString)
{
JSString *str = JS_NewStringCopyZ(cx, "foopy");
diff --git a/js/src/jsapi-tests/testVersion.cpp b/js/src/jsapi-tests/testVersion.cpp
index ccbb7497321d..f2f972968a8a 100644
--- a/js/src/jsapi-tests/testVersion.cpp
+++ b/js/src/jsapi-tests/testVersion.cpp
@@ -7,7 +7,6 @@
#include "jscntxt.h"
#include "jscntxtinlines.h"
-#include "jsobjinlines.h"
using namespace js;
diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp
index 053f8f8c2e8f..2b5900b7365b 100644
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -9,6 +9,8 @@
#include "jsstr.h"
#include "jsfriendapi.h"
+#include "jsscriptinlines.h"
+
static JSScript *
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
JSPrincipals *principals, JSPrincipals *originPrincipals,
diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h
index c3c7e4cb8265..03c8ea7fd403 100644
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -12,7 +12,6 @@
// For js::gc::AutoSuppressGC
#include "jsgc.h"
-#include "jsobjinlines.h"
#include "jsgcinlines.h"
#include "js/Vector.h"
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 828bd264e51b..0c40486226f6 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -77,7 +77,6 @@
#include "jsatominlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/Interpreter-inl.h"
@@ -5289,10 +5288,10 @@ AutoFile::open(JSContext *cx, const char *filename)
}
-JS::CompileOptions::CompileOptions(JSContext *cx)
+JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
: principals(NULL),
originPrincipals(NULL),
- version(cx->findVersion()),
+ version(version != JSVERSION_UNKNOWN ? version : cx->findVersion()),
versionSet(false),
utf8(false),
filename(NULL),
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index fb8790bdef0f..f3c62a1d825d 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3907,7 +3907,7 @@ struct JS_PUBLIC_API(CompileOptions) {
SAVE_SOURCE
} sourcePolicy;
- explicit CompileOptions(JSContext *cx);
+ explicit CompileOptions(JSContext *cx, JSVersion version = JSVERSION_UNKNOWN);
CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; }
CompileOptions &setOriginPrincipals(JSPrincipals *p) { originPrincipals = p; return *this; }
CompileOptions &setVersion(JSVersion v) { version = v; versionSet = true; return *this; }
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 9079b6e495f9..803cda5df7ae 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -33,7 +33,6 @@
#include "jsatominlines.h"
#include "jscntxtinlines.h"
-#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "vm/ArgumentsObject-inl.h"
diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp
index 46f20662493b..10c10b07457b 100644
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -26,6 +26,7 @@
#include "vm/Xdr.h"
#include "jsatominlines.h"
+#include "jscompartmentinlines.h"
#include "vm/String-inl.h"
diff --git a/js/src/jsatominlines.h b/js/src/jsatominlines.h
index c119f0c122fc..1a66b6930f5c 100644
--- a/js/src/jsatominlines.h
+++ b/js/src/jsatominlines.h
@@ -11,6 +11,7 @@
#include "mozilla/RangedPtr.h"
#include "jsatom.h"
+#include "jscntxt.h"
#include "jsnum.h"
#include "jsobj.h"
#include "jsstr.h"
diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp
index 8718c95a0b24..7569cc1794be 100644
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -21,7 +21,6 @@
#include "vm/StringBuffer.h"
#include "jsboolinlines.h"
-#include "jsobjinlines.h"
#include "vm/BooleanObject-inl.h"
#include "vm/GlobalObject-inl.h"
diff --git a/js/src/jsboolinlines.h b/js/src/jsboolinlines.h
index bcf242b5c061..52d3d3f6aca1 100644
--- a/js/src/jsboolinlines.h
+++ b/js/src/jsboolinlines.h
@@ -12,8 +12,6 @@
#include "js/RootingAPI.h"
-#include "jsobjinlines.h"
-
#include "vm/BooleanObject-inl.h"
namespace js {
diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp
index 982f0222ca4a..03fff82cd175 100644
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -27,6 +27,7 @@
#include "jstypes.h"
#include "jsprf.h"
#include "jsatom.h"
+#include "jscompartment.h"
#include "jsdbgapi.h"
#include "jsexn.h"
#include "jsfun.h"
@@ -52,7 +53,6 @@
#include "yarr/BumpPointerAllocator.h"
#include "jscntxtinlines.h"
-#include "jscompartment.h"
#include "jsobjinlines.h"
using namespace js;
@@ -1464,6 +1464,18 @@ JSContext::mark(JSTracer *trc)
MarkValueRoot(trc, &iterValue, "iterValue");
}
+JSVersion
+JSContext::findVersion() const
+{
+ if (hasVersionOverride)
+ return versionOverride;
+
+ if (JSScript *script = stack.currentScript(NULL, js::ContextStack::ALLOW_CROSS_COMPARTMENT))
+ return script->getVersion();
+
+ return defaultVersion;
+}
+
#if defined JS_THREADSAFE && defined DEBUG
JS::AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
@@ -1481,3 +1493,18 @@ JS::AutoCheckRequestDepth::~AutoCheckRequestDepth()
}
#endif
+
+#ifdef JS_CRASH_DIAGNOSTICS
+void CompartmentChecker::check(StackFrame *fp)
+{
+ if (fp)
+ check(fp->scopeChain());
+}
+
+void CompartmentChecker::check(AbstractFramePtr frame)
+{
+ if (frame)
+ check(frame.scopeChain());
+}
+#endif
+
diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h
index 1a01b6cda11d..42a8b7bc6fee 100644
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -357,7 +357,7 @@ class NewObjectCache
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry, js::gc::InitialHeap heap);
/* Fill an entry after a cache miss. */
- inline void fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj);
+ void fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj);
inline void fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj);
inline void fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj);
@@ -1529,7 +1529,11 @@ struct JSContext : js::ContextFriendFields,
JSRuntime *runtime() const { return runtime_; }
JSCompartment *compartment() const { return compartment_; }
- inline JS::Zone *zone() const;
+ inline JS::Zone *zone() const {
+ JS_ASSERT_IF(!compartment(), !zone_);
+ JS_ASSERT_IF(compartment(), js::GetCompartmentZone(compartment()) == zone_);
+ return zone_;
+ }
js::PerThreadData &mainThread() { return runtime()->mainThread; }
private:
@@ -1695,7 +1699,7 @@ struct JSContext : js::ContextFriendFields,
*
* Note: if this ever shows up in a profile, just add caching!
*/
- inline JSVersion findVersion() const;
+ JSVersion findVersion() const;
void setOptions(unsigned opts) {
JS_ASSERT((opts & JSOPTION_MASK) == opts);
@@ -1762,7 +1766,9 @@ struct JSContext : js::ContextFriendFields,
void *onOutOfMemory(void *p, size_t nbytes) {
return runtime()->onOutOfMemory(p, nbytes, this);
}
- void updateMallocCounter(size_t nbytes);
+ void updateMallocCounter(size_t nbytes) {
+ runtime()->updateMallocCounter(zone(), nbytes);
+ }
void reportAllocationOverflow() {
js_ReportAllocationOverflow(this);
}
@@ -2360,6 +2366,9 @@ JSBool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp);
+JSBool intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp);
+JSBool intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc,
+ Value *vp);
JSBool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp);
diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h
index 103de78ad18a..6713e4464a57 100644
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -20,6 +20,8 @@
#include "jsgcinlines.h"
+#include "vm/ObjectImpl-inl.h"
+
namespace js {
inline void
@@ -85,14 +87,6 @@ NewObjectCache::fill(EntryIndex entry_, Class *clasp, gc::Cell *key, gc::AllocKi
js_memcpy(&entry->templateObject, obj, entry->nbytes);
}
-inline void
-NewObjectCache::fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj)
-{
- JS_ASSERT_IF(proto.isObject(), !proto.toObject()->isGlobal());
- JS_ASSERT(obj->getTaggedProto() == proto);
- return fill(entry, clasp, proto.raw(), kind, obj);
-}
-
inline void
NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
{
@@ -107,6 +101,16 @@ NewObjectCache::fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *
return fill(entry, clasp, type, kind, obj);
}
+inline void
+NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src, gc::AllocKind kind)
+{
+ js_memcpy(dst, src, gc::Arena::thingSize(kind));
+#ifdef JSGC_GENERATIONAL
+ Shape::writeBarrierPost(dst->shape_, &dst->shape_);
+ types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
+#endif
+}
+
inline JSObject *
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
{
@@ -248,15 +252,8 @@ class CompartmentChecker
check(script->compartment());
}
- void check(StackFrame *fp) {
- if (fp)
- check(fp->scopeChain());
- }
-
- void check(AbstractFramePtr frame) {
- if (frame)
- check(frame.scopeChain());
- }
+ void check(StackFrame *fp);
+ void check(AbstractFramePtr frame);
};
#endif /* JS_CRASH_DIAGNOSTICS */
@@ -465,18 +462,6 @@ CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, un
} /* namespace js */
-inline JSVersion
-JSContext::findVersion() const
-{
- if (hasVersionOverride)
- return versionOverride;
-
- if (JSScript *script = stack.currentScript(NULL, js::ContextStack::ALLOW_CROSS_COMPARTMENT))
- return script->getVersion();
-
- return defaultVersion;
-}
-
inline bool
JSContext::canSetDefaultVersion() const
{
@@ -589,20 +574,6 @@ JSContext::leaveCompartment(JSCompartment *oldCompartment)
wrapPendingException();
}
-inline JS::Zone *
-JSContext::zone() const
-{
- JS_ASSERT_IF(!compartment(), !zone_);
- JS_ASSERT_IF(compartment(), compartment()->zone() == zone_);
- return zone_;
-}
-
-inline void
-JSContext::updateMallocCounter(size_t nbytes)
-{
- runtime()->updateMallocCounter(zone(), nbytes);
-}
-
inline void
JSContext::setCompartment(JSCompartment *comp)
{
diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp
index 48b8459d7890..065757c39b02 100644
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -25,6 +25,8 @@
#include "jsgcinlines.h"
#include "jsobjinlines.h"
+#include "gc/Barrier-inl.h"
+
using namespace js;
using namespace js::gc;
@@ -603,6 +605,77 @@ JSCompartment::hasScriptsOnStack()
return false;
}
+static bool
+AddInnerLazyFunctionsFromScript(JSScript *script, AutoObjectVector &lazyFunctions)
+{
+ if (!script->hasObjects())
+ return true;
+ ObjectArray *objects = script->objects();
+ for (size_t i = script->innerObjectsStart(); i < objects->length; i++) {
+ JSObject *obj = objects->vector[i];
+ if (obj->isFunction() && obj->toFunction()->isInterpretedLazy()) {
+ if (!lazyFunctions.append(obj))
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+CreateLazyScriptsForCompartment(JSContext *cx)
+{
+ AutoObjectVector lazyFunctions(cx);
+
+ // Find all root lazy functions in the compartment: those which have not been
+ // compiled and which have a source object, indicating that their parent has
+ // been compiled.
+ for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
+ JSObject *obj = i.get();
+ if (obj->compartment() == cx->compartment() && obj->isFunction()) {
+ JSFunction *fun = obj->toFunction();
+ if (fun->isInterpretedLazy()) {
+ LazyScript *lazy = fun->lazyScript();
+ if (lazy->sourceObject() && !lazy->maybeScript()) {
+ if (!lazyFunctions.append(fun))
+ return false;
+ }
+ }
+ }
+ }
+
+ // Create scripts for each lazy function, updating the list of functions to
+ // process with any newly exposed inner functions in created scripts.
+ // A function cannot be delazified until its outer script exists.
+ for (size_t i = 0; i < lazyFunctions.length(); i++) {
+ JSFunction *fun = lazyFunctions[i]->toFunction();
+
+ // lazyFunctions may have been populated with multiple functions for
+ // a lazy script.
+ if (!fun->isInterpretedLazy())
+ continue;
+
+ JSScript *script = fun->getOrCreateScript(cx);
+ if (!script)
+ return false;
+ if (!AddInnerLazyFunctionsFromScript(script, lazyFunctions))
+ return false;
+ }
+
+ // Repoint any clones of the original functions to their new script.
+ for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
+ JSObject *obj = i.get();
+ if (obj->compartment() == cx->compartment() && obj->isFunction()) {
+ JSFunction *fun = obj->toFunction();
+ if (fun->isInterpretedLazy()) {
+ JS_ASSERT(fun->lazyScript()->maybeScript());
+ JS_ALWAYS_TRUE(fun->getOrCreateScript(cx));
+ }
+ }
+ }
+
+ return true;
+}
+
bool
JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeGC &dmgc)
{
@@ -626,6 +699,8 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeGC &dmgc)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
return false;
}
+ if (enabledAfter && !CreateLazyScriptsForCompartment(cx))
+ return false;
}
debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0);
@@ -677,10 +752,14 @@ JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global)
bool
JSCompartment::addDebuggee(JSContext *cx,
- js::GlobalObject *global,
+ GlobalObject *globalArg,
AutoDebugModeGC &dmgc)
{
+ Rooted global(cx, globalArg);
+
bool wasEnabled = debugMode();
+ if (!wasEnabled && !CreateLazyScriptsForCompartment(cx))
+ return false;
if (!debuggees.put(global)) {
js_ReportOutOfMemory(cx);
return false;
diff --git a/js/src/jscompartmentinlines.h b/js/src/jscompartmentinlines.h
index 2925632dec25..0cd9475eab7c 100644
--- a/js/src/jscompartmentinlines.h
+++ b/js/src/jscompartmentinlines.h
@@ -9,6 +9,8 @@
#include "jscompartment.h"
+#include "jscntxtinlines.h"
+
inline void
JSCompartment::initGlobal(js::GlobalObject &global)
{
diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp
index 2a603f26446a..44c434ca6730 100644
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -38,6 +38,7 @@
#include "jsobj.h"
#include "jsstr.h"
+#include "js/Date.h"
#include "vm/DateTime.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
@@ -47,8 +48,6 @@
#include "jsobjinlines.h"
-#include "js/Date.h"
-
using namespace js;
using namespace js::types;
diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp
index 5ee1c1a98e50..371fd74fb692 100644
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -35,7 +35,6 @@
#include "jsatominlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/Debugger-inl.h"
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index 4e528f027ffd..413f5e7fea9b 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -13,6 +13,7 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsgc.h"
+#include "jsobj.h"
#include "jswrapper.h"
#include "jsweakmap.h"
#include "jswatchpoint.h"
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index aa763956641e..122db3f6d914 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -35,7 +35,6 @@
#include "jsfuninlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/Interpreter-inl.h"
@@ -350,9 +349,11 @@ js::XDRInterpretedFunction(XDRState *xdr, HandleObject enclosingScope, Han
return false;
}
firstword = !!fun->atom();
- flagsword = (fun->nargs << 16) | fun->flags;
+ script = fun->getOrCreateScript(cx);
+ if (!script)
+ return false;
atom = fun->atom();
- script = fun->nonLazyScript();
+ flagsword = (fun->nargs << 16) | fun->flags;
} else {
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr(),
JSFunction::FinalizeKind, TenuredObject);
@@ -1057,9 +1058,10 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
if (cx->zone()->needsBarrier())
LazyScript::writeBarrierPre(lazy);
+ fun->flags &= ~INTERPRETED_LAZY;
+ fun->flags |= INTERPRETED;
+
if (JSScript *script = lazy->maybeScript()) {
- fun->flags &= ~INTERPRETED_LAZY;
- fun->flags |= INTERPRETED;
fun->initScript(script);
/*
@@ -1072,10 +1074,9 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
return true;
}
- /* Lazily parsed script. */
- const jschar *chars = lazy->source()->chars(cx);
- if (!chars)
- return false;
+ fun->initScript(NULL);
+
+ JS_ASSERT(lazy->source()->hasSourceData());
/*
* GC must be suppressed for the remainder of the lazy parse, as any
@@ -1083,9 +1084,10 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti
*/
AutoSuppressGC suppressGC(cx);
- fun->flags &= ~INTERPRETED_LAZY;
- fun->flags |= INTERPRETED;
- fun->initScript(NULL);
+ /* Lazily parsed script. */
+ const jschar *chars = lazy->source()->chars(cx);
+ if (!chars)
+ return false;
const jschar *lazyStart = chars + lazy->begin();
size_t lazyLength = lazy->end() - lazy->begin();
diff --git a/js/src/jsfun.h b/js/src/jsfun.h
index c93557a90ea8..e5d060a0e831 100644
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -142,7 +142,6 @@ class JSFunction : public JSObject
// Can be called multiple times by the parser.
void setArgCount(uint16_t nargs) {
- JS_ASSERT(this->nargs == 0 || this->nargs == nargs);
this->nargs = nargs;
}
@@ -186,13 +185,6 @@ class JSFunction : public JSObject
flags |= EXPR_CLOSURE;
}
- void markNotLazy() {
- JS_ASSERT(isInterpretedLazy());
- JS_ASSERT(hasScript());
- flags |= INTERPRETED;
- flags &= ~INTERPRETED_LAZY;
- }
-
JSAtom *atom() const { return hasGuessedAtom() ? NULL : atom_.get(); }
js::PropertyName *name() const { return hasGuessedAtom() || !atom_ ? NULL : atom_->asPropertyName(); }
inline void initAtom(JSAtom *atom);
@@ -221,7 +213,6 @@ class JSFunction : public JSObject
JS_ASSERT(cx);
if (isInterpretedLazy()) {
JS::RootedFunction self(cx, this);
- js::MaybeCheckStackRoots(cx);
if (!createScriptForLazilyInterpretedFunction(cx, self))
return NULL;
JS_ASSERT(self->hasScript());
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index bb92eedcd3df..3b1e1e6e6d08 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -168,7 +168,8 @@ static const AllocKind FinalizePhaseStrings[] = {
};
static const AllocKind FinalizePhaseScripts[] = {
- FINALIZE_SCRIPT
+ FINALIZE_SCRIPT,
+ FINALIZE_LAZY_SCRIPT
};
static const AllocKind FinalizePhaseIonCode[] = {
@@ -213,7 +214,6 @@ static const AllocKind BackgroundPhaseStrings[] = {
};
static const AllocKind BackgroundPhaseShapes[] = {
- FINALIZE_LAZY_SCRIPT,
FINALIZE_SHAPE,
FINALIZE_BASE_SHAPE,
FINALIZE_TYPE_OBJECT
@@ -1440,7 +1440,7 @@ ArenaLists::queueScriptsForSweep(FreeOp *fop)
{
gcstats::AutoPhase ap(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_SCRIPT);
queueForForegroundSweep(fop, FINALIZE_SCRIPT);
- queueForBackgroundSweep(fop, FINALIZE_LAZY_SCRIPT);
+ queueForForegroundSweep(fop, FINALIZE_LAZY_SCRIPT);
}
void
diff --git a/js/src/jsgc.h b/js/src/jsgc.h
index 4eec8386f750..8eb84af8de3f 100644
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -204,7 +204,7 @@ IsBackgroundFinalized(AllocKind kind)
false, /* FINALIZE_OBJECT16 */
true, /* FINALIZE_OBJECT16_BACKGROUND */
false, /* FINALIZE_SCRIPT */
- true, /* FINALIZE_LAZY_SCRIPT */
+ false, /* FINALIZE_LAZY_SCRIPT */
true, /* FINALIZE_SHAPE */
true, /* FINALIZE_BASE_SHAPE */
true, /* FINALIZE_TYPE_OBJECT */
diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp
index d25c20b483bb..1f239121d9e7 100644
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -32,8 +32,8 @@
#include "jsatominlines.h"
#include "jsgcinlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsopcodeinlines.h"
+#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/Stack-inl.h"
diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h
index 80a74ecd756e..cae493ee3270 100644
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -22,6 +22,8 @@
#include "vm/GlobalObject.h"
#include "jsanalyzeinlines.h"
+
+#include "gc/Barrier-inl.h"
#include "vm/Stack-inl.h"
#ifndef jsinferinlines_h___
@@ -734,28 +736,20 @@ UseNewTypeForClone(JSFunction *fun)
* instance a singleton type and clone the underlying script.
*/
- JSScript *script = fun->nonLazyScript();
-
- if (script->length >= 50)
- return false;
-
- if (script->hasConsts() || script->hasObjects() || script->hasRegexps() || fun->isHeavyweight())
- return false;
-
- bool hasArguments = false;
- bool hasApply = false;
-
- for (jsbytecode *pc = script->code;
- pc != script->code + script->length;
- pc += GetBytecodeLength(pc))
- {
- if (*pc == JSOP_ARGUMENTS)
- hasArguments = true;
- if (*pc == JSOP_FUNAPPLY)
- hasApply = true;
+ uint32_t begin, end;
+ if (fun->hasScript()) {
+ if (!fun->nonLazyScript()->usesArgumentsAndApply)
+ return false;
+ begin = fun->nonLazyScript()->sourceStart;
+ end = fun->nonLazyScript()->sourceEnd;
+ } else {
+ if (!fun->lazyScript()->usesArgumentsAndApply())
+ return false;
+ begin = fun->lazyScript()->begin();
+ end = fun->lazyScript()->end();
}
- return hasArguments && hasApply;
+ return end - begin <= 100;
}
/////////////////////////////////////////////////////////////////////
diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp
index 3bd99e403d4d..2c8159b11b7f 100644
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -42,7 +42,6 @@
#include "vm/StringBuffer.h"
#include "jsatominlines.h"
-#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "vm/NumberObject-inl.h"
#include "vm/String-inl.h"
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index ae153ae604f5..6aaa1b01d461 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1222,6 +1222,8 @@ JSObject::isSealedOrFrozen(JSContext *cx, HandleObject obj, ImmutabilityType it,
const char *
JSObject::className(JSContext *cx, HandleObject obj)
{
+ assertSameCompartment(cx, obj);
+
if (obj->isProxy())
return Proxy::className(cx, obj);
@@ -1281,6 +1283,15 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
return obj;
}
+void
+NewObjectCache::fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto,
+ gc::AllocKind kind, JSObject *obj)
+{
+ JS_ASSERT_IF(proto.isObject(), !proto.toObject()->isGlobal());
+ JS_ASSERT(obj->getTaggedProto() == proto);
+ return fill(entry, clasp, proto.raw(), kind, obj);
+}
+
JSObject *
js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
js::TaggedProto proto_, JSObject *parent_,
diff --git a/js/src/jsobj.h b/js/src/jsobj.h
index 33cdab295ced..b308dc285cce 100644
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -463,7 +463,6 @@ class JSObject : public js::ObjectImpl
* GC in order to compute the proto. Currently, it will not run JS code.
*/
inline JSObject *getProto() const;
- using js::ObjectImpl::getTaggedProto;
static inline bool getProto(JSContext *cx, js::HandleObject obj,
js::MutableHandleObject protop);
@@ -539,7 +538,6 @@ class JSObject : public js::ObjectImpl
static bool setMetadata(JSContext *cx, js::HandleObject obj, js::HandleObject newMetadata);
inline js::GlobalObject &global() const;
- using js::ObjectImpl::compartment;
/* Remove the type (and prototype) or parent from a new object. */
static inline bool clearType(JSContext *cx, js::HandleObject obj);
@@ -970,54 +968,53 @@ class JSObject : public js::ObjectImpl
*/
/* Direct subtypes of JSObject: */
- inline bool isArray() const;
- inline bool isArguments() const;
- inline bool isArrayBuffer() const;
- inline bool isDataView() const;
- inline bool isDate() const;
- inline bool isElementIterator() const;
- inline bool isError() const;
- inline bool isFunction() const;
- inline bool isGenerator() const;
- inline bool isGlobal() const;
- inline bool isMapIterator() const;
- inline bool isModule() const;
- inline bool isObject() const;
- inline bool isPrimitive() const;
+ inline bool isArray() const { return hasClass(&js::ArrayClass); }
+ inline bool isArguments() const { return isNormalArguments() || isStrictArguments(); }
+ inline bool isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
+ inline bool isDataView() const { return hasClass(&js::DataViewClass); }
+ inline bool isDate() const { return hasClass(&js::DateClass); }
+ inline bool isElementIterator() const { return hasClass(&js::ElementIteratorClass); }
+ inline bool isError() const { return hasClass(&js::ErrorClass); }
+ inline bool isFunction() const { return hasClass(&js::FunctionClass); }
+ inline bool isGenerator() const { return hasClass(&js::GeneratorClass); }
+ inline bool isGlobal() const;
+ inline bool isMapIterator() const { return hasClass(&js::MapIteratorClass); }
+ inline bool isModule() const { return hasClass(&js::ModuleClass); }
+ inline bool isObject() const { return hasClass(&js::ObjectClass); }
+ inline bool isPrimitive() const { return isNumber() || isString() || isBoolean(); }
inline bool isPropertyIterator() const;
using js::ObjectImpl::isProxy;
- inline bool isRegExp() const;
- inline bool isRegExpStatics() const;
- inline bool isScope() const;
- inline bool isScript() const;
- inline bool isScriptSource() const;
- inline bool isSetIterator() const;
- inline bool isStopIteration() const;
- inline bool isTypedArray() const;
- inline bool isWeakMap() const;
+ inline bool isRegExp() const { return hasClass(&js::RegExpClass); }
+ inline bool isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
+ inline bool isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
+ inline bool isScriptSource() const { return hasClass(&js::ScriptSourceClass); }
+ inline bool isSetIterator() const { return hasClass(&js::SetIteratorClass); }
+ inline bool isStopIteration() const { return hasClass(&js::StopIterationClass); }
+ inline bool isTypedArray() const;
+ inline bool isWeakMap() const { return hasClass(&js::WeakMapClass); }
/* Subtypes of ScopeObject. */
- inline bool isBlock() const;
- inline bool isCall() const;
- inline bool isDeclEnv() const;
- inline bool isNestedScope() const;
- inline bool isWith() const;
+ inline bool isBlock() const { return hasClass(&js::BlockClass); }
+ inline bool isCall() const { return hasClass(&js::CallClass); }
+ inline bool isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
+ inline bool isNestedScope() const { return isBlock() || isWith(); }
+ inline bool isWith() const { return hasClass(&js::WithClass); }
inline bool isClonedBlock() const;
inline bool isStaticBlock() const;
/* Subtypes of PrimitiveObject. */
- inline bool isBoolean() const;
- inline bool isNumber() const;
- inline bool isString() const;
+ inline bool isBoolean() const { return hasClass(&js::BooleanClass); }
+ inline bool isNumber() const { return hasClass(&js::NumberClass); }
+ inline bool isString() const { return hasClass(&js::StringClass); }
/* Subtypes of ArgumentsObject. */
- inline bool isNormalArguments() const;
- inline bool isStrictArguments() const;
+ inline bool isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
+ inline bool isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
/* Subtypes of Proxy. */
- inline bool isDebugScope() const;
- inline bool isWrapper() const;
- inline bool isFunctionProxy() const;
+ inline bool isDebugScope() const;
+ inline bool isWrapper() const;
+ inline bool isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
inline bool isCrossCompartmentWrapper() const;
inline js::ArgumentsObject &asArguments();
@@ -1033,7 +1030,10 @@ class JSObject : public js::ObjectImpl
inline js::GlobalObject &asGlobal();
inline js::MapObject &asMap();
inline js::MapIteratorObject &asMapIterator();
- inline js::Module &asModule();
+ js::Module &asModule() {
+ JS_ASSERT(isModule());
+ return *reinterpret_cast(this);
+ }
inline js::NestedScopeObject &asNestedScope();
inline js::NormalArgumentsObject &asNormalArguments();
inline js::NumberObject &asNumber();
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index 404c26f06bd7..bd710547a77b 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -9,43 +9,16 @@
#include "jsobj.h"
-#include "jsapi.h"
-#include "jsarray.h"
-#include "jsbool.h"
-#include "jscntxt.h"
-#include "jsfun.h"
-#include "jsiter.h"
-#include "jslock.h"
-#include "jsnum.h"
-#include "jspropertytree.h"
-#include "jsproxy.h"
-#include "jsstr.h"
-#include "jstypedarray.h"
#include "jswrapper.h"
-#include "builtin/Module.h"
-#include "gc/Barrier.h"
-#include "gc/Marking.h"
-#include "js/MemoryMetrics.h"
-#include "js/RootingAPI.h"
-#include "js/TemplateLib.h"
-#include "vm/BooleanObject.h"
-#include "vm/GlobalObject.h"
-#include "vm/Shape.h"
#include "vm/NumberObject.h"
#include "vm/Probes.h"
-#include "vm/RegExpStatics.h"
#include "vm/StringObject.h"
#include "jsatominlines.h"
-#include "jscompartmentinlines.h"
#include "jsfuninlines.h"
-#include "jsgcinlines.h"
-#include "jsinferinlines.h"
-#include "gc/Barrier-inl.h"
+
#include "vm/ObjectImpl-inl.h"
-#include "vm/Shape-inl.h"
-#include "vm/String-inl.h"
/* static */ inline bool
JSObject::enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
@@ -872,40 +845,9 @@ inline bool JSObject::watched() const
return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
}
-inline bool JSObject::isArray() const { return hasClass(&js::ArrayClass); }
-inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
-inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
-inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
-inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
-inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
-inline bool JSObject::isDataView() const { return hasClass(&js::DataViewClass); }
-inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
-inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
-inline bool JSObject::isElementIterator() const { return hasClass(&js::ElementIteratorClass); }
-inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
-inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
-inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
-inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
-inline bool JSObject::isMapIterator() const { return hasClass(&js::MapIteratorClass); }
-inline bool JSObject::isModule() const { return hasClass(&js::ModuleClass); }
-inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
-inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
-inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
-inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
-inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
-inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
-inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
-inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
-inline bool JSObject::isScriptSource() const { return hasClass(&js::ScriptSourceClass); }
-inline bool JSObject::isSetIterator() const { return hasClass(&js::SetIteratorClass); }
inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
-inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
-inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
-inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
-inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
-inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
inline js::NumberObject &
JSObject::asNumber()
@@ -928,13 +870,6 @@ JSObject::asScriptSource()
return *static_cast(this);
}
-inline js::Module &
-JSObject::asModule()
-{
- JS_ASSERT(isModule());
- return *static_cast(this);
-}
-
inline bool
JSObject::isDebugScope() const
{
@@ -1532,16 +1467,6 @@ class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescri
friend void AutoGCRooter::trace(JSTracer *trc);
};
-inline void
-NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src, gc::AllocKind kind)
-{
- js_memcpy(dst, src, gc::Arena::thingSize(kind));
-#ifdef JSGC_GENERATIONAL
- Shape::writeBarrierPost(dst->shape_, &dst->shape_);
- types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
-#endif
-}
-
static inline bool
CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp)
{
diff --git a/js/src/json.cpp b/js/src/json.cpp
index b7944b6167ff..2f60a17827b3 100644
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -25,7 +25,6 @@
#include "jsatominlines.h"
#include "jsboolinlines.h"
-#include "jsobjinlines.h"
using namespace js;
using namespace js::gc;
diff --git a/js/src/jsonparser.cpp b/js/src/jsonparser.cpp
index 3e0dc7ee7675..2aa2ad678874 100644
--- a/js/src/jsonparser.cpp
+++ b/js/src/jsonparser.cpp
@@ -9,6 +9,7 @@
#include "mozilla/RangedPtr.h"
#include "jsarray.h"
+#include "jscompartment.h"
#include "jsnum.h"
#include "vm/StringBuffer.h"
diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp
index f3fe3cf445d0..9b81302ea067 100644
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -19,9 +19,11 @@
#include "jstypes.h"
#include "jsutil.h"
#include "jsprf.h"
+#include "jsanalyze.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
+#include "jscompartment.h"
#include "jsfun.h"
#include "jsnum.h"
#include "jsobj.h"
@@ -36,11 +38,13 @@
#include "jscntxtinlines.h"
#include "jsobjinlines.h"
+#include "jscompartmentinlines.h"
#include "jsopcodeinlines.h"
#include "jsautooplen.h"
#include "vm/RegExpObject-inl.h"
+#include "vm/ScopeObject-inl.h"
using namespace js;
using namespace js::gc;
diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp
index a76d8cc26cae..43fed35235ff 100644
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2147,12 +2147,12 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
: builder.continueStatement(label, &pn->pn_pos, dst));
}
- case PNK_COLON:
+ case PNK_LABEL:
{
JS_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos));
RootedValue label(cx), stmt(cx);
- RootedAtom pnAtom(cx, pn->pn_atom);
+ RootedAtom pnAtom(cx, pn->as().label());
return identifier(pnAtom, NULL, &label) &&
statement(pn->pn_expr, &stmt) &&
builder.labeledStatement(label, stmt, &pn->pn_pos, dst);
@@ -2516,7 +2516,7 @@ ASTSerializer::expression(ParseNode *pn, MutableHandleValue dst)
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
JS_ASSERT(pn->pn_pos.encloses(next->pn_pos));
- if (next->isKind(PNK_COMMA) && next->pn_count == 0) {
+ if (next->isKind(PNK_ELISION)) {
elts.infallibleAppend(NullValue());
} else {
RootedValue expr(cx);
@@ -2696,10 +2696,7 @@ ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValu
return false;
for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
- /* Comma expressions can't occur inside patterns, so no need to test pn_count. */
- JS_ASSERT_IF(next->isKind(PNK_COMMA), next->pn_count == 0);
-
- if (next->isKind(PNK_COMMA)) {
+ if (next->isKind(PNK_ELISION)) {
elts.infallibleAppend(NullValue());
} else {
RootedValue patt(cx);
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index eb777511d0bb..047322749b61 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -34,7 +34,6 @@
#include "vm/Xdr.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/Interpreter-inl.h"
@@ -666,7 +665,10 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc
/* Code the nested function's enclosing scope. */
uint32_t funEnclosingScopeIndex = 0;
if (mode == XDR_ENCODE) {
- RootedObject staticScope(cx, (*objp)->toFunction()->nonLazyScript()->enclosingStaticScope());
+ JSScript *innerScript = (*objp)->toFunction()->getOrCreateScript(cx);
+ if (!innerScript)
+ return false;
+ RootedObject staticScope(cx, innerScript->enclosingStaticScope());
StaticScopeIter ssi(cx, staticScope);
if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) {
JS_ASSERT(ssi.done() == !fun);
@@ -1226,16 +1228,13 @@ SourceDataCache::purge()
const jschar *
ScriptSource::chars(JSContext *cx)
{
-#ifdef USE_ZLIB
- Rooted cached(cx, NULL);
-#endif
#ifdef JS_THREADSAFE
if (!ready())
return cx->runtime()->sourceCompressorThread.currentChars();
#endif
#ifdef USE_ZLIB
if (compressed()) {
- cached = cx->runtime()->sourceDataCache.lookup(this);
+ JSStableString *cached = cx->runtime()->sourceDataCache.lookup(this);
if (!cached) {
const size_t nbytes = sizeof(jschar) * (length_ + 1);
jschar *decompressed = static_cast(cx->malloc_(nbytes));
@@ -1257,10 +1256,8 @@ ScriptSource::chars(JSContext *cx)
}
return cached->chars().get();
}
- return data.source;
-#else
- return data.source;
#endif
+ return data.source;
}
JSStableString *
@@ -2324,8 +2321,11 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
assertSameCompartment(cx, innerFun);
clone = innerFun;
} else {
- if (!innerFun->getOrCreateScript(cx))
- return NULL;
+ if (innerFun->isInterpretedLazy()) {
+ AutoCompartment ac(cx, innerFun);
+ if (!innerFun->getOrCreateScript(cx))
+ return NULL;
+ }
RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
StaticScopeIter ssi(cx, staticScope);
RootedObject enclosingScope(cx);
@@ -2771,11 +2771,14 @@ JSScript::markChildren(JSTracer *trc)
void
LazyScript::markChildren(JSTracer *trc)
{
- if (parent_)
- MarkScriptUnbarriered(trc, &parent_, "lazyScriptParent");
+ if (sourceObject_)
+ MarkObject(trc, &sourceObject_, "sourceObject");
+
+ if (parentFunction_)
+ MarkObject(trc, &parentFunction_, "parentFunction");
if (script_)
- MarkScriptUnbarriered(trc, &script_, "lazyScript");
+ MarkScript(trc, &script_, "realScript");
HeapPtrAtom *freeVariables = this->freeVariables();
for (size_t i = 0; i < numFreeVariables(); i++)
@@ -2791,6 +2794,9 @@ LazyScript::finalize(FreeOp *fop)
{
if (table_)
fop->free_(table_);
+
+ if (originPrincipals_)
+ JS_DropPrincipals(fop->runtime(), originPrincipals_);
}
void
@@ -2939,8 +2945,58 @@ JSScript::formalLivesInArgumentsObject(unsigned argSlot)
return argsObjAliasesFormals() && !formalIsAliased(argSlot);
}
+LazyScript::LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions,
+ JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
+ : script_(NULL),
+ parentFunction_(NULL),
+ sourceObject_(NULL),
+ table_(table),
+ originPrincipals_(NULL),
+ version_(version),
+ numFreeVariables_(numFreeVariables),
+ numInnerFunctions_(numInnerFunctions),
+ strict_(false),
+ bindingsAccessedDynamically_(false),
+ hasDebuggerStatement_(false),
+ directlyInsideEval_(false),
+ usesArgumentsAndApply_(false),
+ hasBeenCloned_(false),
+ begin_(begin),
+ end_(end),
+ lineno_(lineno),
+ column_(column)
+{
+ JS_ASSERT(this->version() == version);
+ JS_ASSERT(begin <= end);
+}
+
+void
+LazyScript::initScript(JSScript *script)
+{
+ JS_ASSERT(script && !script_);
+ script_ = script;
+}
+
+void
+LazyScript::setParent(JSFunction *parentFunction, ScriptSourceObject *sourceObject,
+ JSPrincipals *originPrincipals)
+{
+ JS_ASSERT(sourceObject && !sourceObject_ && !parentFunction_ && !originPrincipals_);
+ parentFunction_ = parentFunction;
+ sourceObject_ = sourceObject;
+ originPrincipals_ = originPrincipals;
+ if (originPrincipals)
+ JS_HoldPrincipals(originPrincipals);
+}
+
+ScriptSourceObject *
+LazyScript::sourceObject() const
+{
+ return sourceObject_ ? &sourceObject_->asScriptSource() : NULL;
+}
+
/* static */ LazyScript *
-LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions,
+LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
{
JS_ASSERT(begin <= end);
@@ -2959,7 +3015,13 @@ LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFu
if (!res)
return NULL;
- return new (res) LazyScript(table, numFreeVariables, numInnerFunctions, begin, end, lineno, column);
+ return new (res) LazyScript(table, numFreeVariables, numInnerFunctions, version,
+ begin, end, lineno, column);
+}
+
+uint32_t LazyScript::staticLevel() const
+{
+ return parentFunction() ? parentFunction()->nonLazyScript()->staticLevel + 1 : 1;
}
void
diff --git a/js/src/jsscript.h b/js/src/jsscript.h
index 173ba4c93a93..82b3232fd2e8 100644
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -538,9 +538,12 @@ class JSScript : public js::gc::Cell
bool isActiveEval:1; /* script came from eval(), and is still active */
bool isCachedEval:1; /* script came from eval(), and is in eval cache */
- /* Set for functions defined at the top level within an 'eval' script. */
+ // Set for functions defined at the top level within an 'eval' script.
bool directlyInsideEval:1;
+ // Both 'arguments' and f.apply() are used. This is likely to be a wrapper.
+ bool usesArgumentsAndApply:1;
+
/* script is attempted to be cloned anew at each callsite. This is
temporarily needed for ParallelArray selfhosted code until type
information can be made context sensitive. See discussion in
@@ -1099,19 +1102,20 @@ class AliasedFormalIter
struct SourceCompressionToken;
-
// Information about a script which may be (or has been) lazily compiled to
// bytecode from its source.
class LazyScript : public js::gc::Cell
{
- // Immediate parent in which the script is nested, or NULL if the parent
- // has not been compiled yet. Lazy scripts are always functions within a
- // global or eval script so there will be a parent.
- JSScript *parent_;
-
// If non-NULL, the script has been compiled and this is a forwarding
// pointer to the result.
- JSScript *script_;
+ HeapPtrScript script_;
+
+ // Immediate parent in which the script is nested, or NULL.
+ HeapPtrFunction parentFunction_;
+
+ // Source code object, or NULL if the script in which this is nested has
+ // not been compiled yet.
+ HeapPtrObject sourceObject_;
// Heap allocated table with any free variables or inner functions.
void *table_;
@@ -1120,14 +1124,20 @@ class LazyScript : public js::gc::Cell
uint32_t padding;
#endif
- uint32_t numFreeVariables_;
+ // Assorted bits that should really be in ScriptSourceObject.
+ JSPrincipals *originPrincipals_;
+ uint32_t version_ : 8;
+
+ uint32_t numFreeVariables_ : 24;
uint32_t numInnerFunctions_ : 26;
- bool strict_ : 1;
- bool bindingsAccessedDynamically_ : 1;
- bool hasDebuggerStatement_ : 1;
- bool directlyInsideEval_:1;
- bool hasBeenCloned_:1;
+ // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
+ uint32_t strict_ : 1;
+ uint32_t bindingsAccessedDynamically_ : 1;
+ uint32_t hasDebuggerStatement_ : 1;
+ uint32_t directlyInsideEval_:1;
+ uint32_t usesArgumentsAndApply_:1;
+ uint32_t hasBeenCloned_:1;
// Source location for the script.
uint32_t begin_;
@@ -1135,46 +1145,33 @@ class LazyScript : public js::gc::Cell
uint32_t lineno_;
uint32_t column_;
- LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions,
- uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
- : parent_(NULL),
- script_(NULL),
- table_(table),
- numFreeVariables_(numFreeVariables),
- numInnerFunctions_(numInnerFunctions),
- strict_(false),
- bindingsAccessedDynamically_(false),
- hasDebuggerStatement_(false),
- directlyInsideEval_(false),
- hasBeenCloned_(false),
- begin_(begin),
- end_(end),
- lineno_(lineno),
- column_(column)
- {
- JS_ASSERT(begin <= end);
- }
+ LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
+ uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
public:
static LazyScript *Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions,
- uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
+ JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
- void initParent(JSScript *parent) {
- JS_ASSERT(parent && !parent_);
- parent_ = parent;
- }
- JSScript *parent() const {
- return parent_;
- }
-
- void initScript(JSScript *script) {
- JS_ASSERT(script && !script_);
- script_ = script;
- }
+ void initScript(JSScript *script);
JSScript *maybeScript() {
return script_;
}
+ JSFunction *parentFunction() const {
+ return parentFunction_;
+ }
+ ScriptSourceObject *sourceObject() const;
+ JSPrincipals *originPrincipals() const {
+ return originPrincipals_;
+ }
+ JSVersion version() const {
+ JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
+ return (version_ == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(version_);
+ }
+
+ void setParent(JSFunction *parentFunction, ScriptSourceObject *sourceObject,
+ JSPrincipals *originPrincipals);
+
uint32_t numFreeVariables() const {
return numFreeVariables_;
}
@@ -1217,6 +1214,13 @@ class LazyScript : public js::gc::Cell
directlyInsideEval_ = true;
}
+ bool usesArgumentsAndApply() const {
+ return usesArgumentsAndApply_;
+ }
+ void setUsesArgumentsAndApply() {
+ usesArgumentsAndApply_ = true;
+ }
+
bool hasBeenCloned() const {
return hasBeenCloned_;
}
@@ -1225,7 +1229,7 @@ class LazyScript : public js::gc::Cell
}
ScriptSource *source() const {
- return parent()->scriptSource();
+ return sourceObject()->source();
}
uint32_t begin() const {
return begin_;
@@ -1240,6 +1244,8 @@ class LazyScript : public js::gc::Cell
return column_;
}
+ uint32_t staticLevel() const;
+
Zone *zone() const {
return Cell::tenuredZone();
}
diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h
index ff422e94ba98..dce41aae863f 100644
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -18,6 +18,8 @@
#include "vm/RegExpObject.h"
#include "vm/Shape.h"
+#include "jscompartmentinlines.h"
+
#include "vm/Shape-inl.h"
namespace js {
diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
index 752b2a45a3fe..193a6ffb6265 100644
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -47,7 +47,6 @@
#include "vm/StringBuffer.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "jsautooplen.h" // generated headers last
diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp
index 8f9b6d2a715d..aece0b479aa7 100644
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -30,7 +30,6 @@
#include "jsatominlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jstypedarrayinlines.h"
#include "vm/GlobalObject-inl.h"
diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp
index 7e35298701d8..db9d8a198d35 100644
--- a/js/src/jswatchpoint.cpp
+++ b/js/src/jswatchpoint.cpp
@@ -7,9 +7,11 @@
#include "jswatchpoint.h"
#include "jsatom.h"
+#include "jscompartment.h"
#include "gc/Marking.h"
+#include "jsgcinlines.h"
#include "jsobjinlines.h"
using namespace js;
diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp
index 86f70a84950d..1c70d9de41d0 100644
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -17,6 +17,8 @@
#include "jsobjinlines.h"
+#include "gc/Barrier-inl.h"
+
using namespace js;
WeakMapBase::WeakMapBase(JSObject *memOf, JSCompartment *c)
diff --git a/js/src/perf/jsperf.cpp b/js/src/perf/jsperf.cpp
index 4940e9da8fd8..d1b36f54e124 100644
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -8,7 +8,6 @@
#include "jscntxt.h" /* for error messages */
#include "jsobj.h" /* for unwrapping without a context */
-#include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
using JS::PerfMeasurement;
diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
index 55a0a1b3c89c..18a174ff95c6 100644
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -52,7 +52,6 @@
#include "jsheaptools.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "ion/Ion.h"
diff --git a/js/src/tests/ecma_2/Statements/label-003.js b/js/src/tests/ecma_2/Statements/label-003.js
new file mode 100644
index 000000000000..d3ed464f5f8b
--- /dev/null
+++ b/js/src/tests/ecma_2/Statements/label-003.js
@@ -0,0 +1,15 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// The colon for a labeled statement may be on a separate line.
+var x;
+label
+: {
+ x = 1;
+ break label;
+ x = 2;
+}
+assertEq(x, 1);
+reportCompare(0, 0, 'ok');
diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp
index 29c2a4378804..b9f9345dfb96 100644
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -18,7 +18,7 @@
#include "vm/Stack-inl.h"
#include "vm/ArgumentsObject-inl.h"
-#if defined(JS_ION)
+#if defined(JS_ION)
#include "ion/IonFrames.h"
#endif
diff --git a/js/src/vm/BooleanObject-inl.h b/js/src/vm/BooleanObject-inl.h
index b84171b8eb1d..688330031a3c 100644
--- a/js/src/vm/BooleanObject-inl.h
+++ b/js/src/vm/BooleanObject-inl.h
@@ -7,10 +7,10 @@
#ifndef BooleanObject_inl_h___
#define BooleanObject_inl_h___
-#include "jsobjinlines.h"
-
#include "vm/BooleanObject.h"
+#include "jsobjinlines.h"
+
inline js::BooleanObject &
JSObject::asBoolean()
{
diff --git a/js/src/vm/Debugger-inl.h b/js/src/vm/Debugger-inl.h
index 61117ebde761..c05766ed9e52 100644
--- a/js/src/vm/Debugger-inl.h
+++ b/js/src/vm/Debugger-inl.h
@@ -11,7 +11,7 @@
#include "vm/Stack-inl.h"
-bool
+inline bool
js::Debugger::onLeaveFrame(JSContext *cx, AbstractFramePtr frame, bool ok)
{
/* Traps must be cleared from eval frames, see slowPathOnLeaveFrame. */
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
index fd14b3bba038..63a6413b8060 100644
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -21,8 +21,8 @@
#include "js/Vector.h"
#include "jsgcinlines.h"
-#include "jsobjinlines.h"
#include "jsopcodeinlines.h"
+
#include "gc/FindSCCs-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/Stack-inl.h"
@@ -229,7 +229,6 @@ class Debugger::FrameRange
}
};
-
/*** Breakpoints *********************************************************************************/
BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
@@ -686,7 +685,6 @@ Debugger::wrapDebuggeeValue(JSContext *cx, MutableHandleValue vp)
assertSameCompartment(cx, object.get());
if (vp.isObject()) {
- // Do we need this RootedObject?
RootedObject obj(cx, &vp.toObject());
ObjectWeakMap::AddPtr p = objects.lookupForAdd(obj);
@@ -2887,16 +2885,6 @@ DebuggerScript_getSourceMapUrl(JSContext *cx, unsigned argc, Value *vp)
return true;
}
-static bool
-EnsureFunctionHasScript(JSContext *cx, JSFunction *fun)
-{
- if (fun->isInterpretedLazy()) {
- AutoCompartment ac(cx, fun);
- return fun->getOrCreateScript(cx);
- }
- return true;
-}
-
static JSBool
DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp)
{
@@ -2921,10 +2909,6 @@ DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp)
obj = objects->vector[i];
if (obj->isFunction()) {
fun = static_cast(obj.get());
-
- if (!EnsureFunctionHasScript(cx, fun))
- return false;
-
funScript = fun->nonLazyScript();
s = dbg->wrapScript(cx, funScript);
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
@@ -4397,7 +4381,11 @@ static JSBool
DebuggerObject_getClass(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "get class", args, refobj);
- const char *className = JSObject::className(cx, refobj);
+ const char *className;
+ {
+ AutoCompartment ac(cx, refobj);
+ className = JSObject::className(cx, refobj);
+ }
JSAtom *str = Atomize(cx, className, strlen(className));
if (!str)
return false;
@@ -4473,9 +4461,6 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
result->ensureDenseInitializedLength(cx, 0, fun->nargs);
if (fun->isInterpreted()) {
- if (!EnsureFunctionHasScript(cx, fun))
- return false;
-
JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs());
if (fun->nargs > 0) {
@@ -4517,9 +4502,6 @@ DebuggerObject_getScript(JSContext *cx, unsigned argc, Value *vp)
return true;
}
- if (!EnsureFunctionHasScript(cx, fun))
- return false;
-
RootedScript script(cx, fun->nonLazyScript());
RootedObject scriptObject(cx, dbg->wrapScript(cx, script));
if (!scriptObject)
diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
index 7e77fc47ea13..dc63a22b6fa1 100644
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -422,7 +422,7 @@ class Debugger : private mozilla::LinkedListElement
inline bool observesNewScript() const;
inline bool observesNewGlobalObject() const;
inline bool observesGlobal(GlobalObject *global) const;
- inline bool observesFrame(AbstractFramePtr frame) const;
+ bool observesFrame(AbstractFramePtr frame) const;
bool observesScript(JSScript *script) const;
/*
diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp
index ed46bec8d4f1..e91e0ba1fa15 100644
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -20,6 +20,7 @@
#include "builtin/Object.h"
#include "builtin/RegExp.h"
+#include "jscompartmentinlines.h"
#include "jsobjinlines.h"
#include "vm/GlobalObject-inl.h"
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index a9a224f43dec..c4332a21ff18 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -42,9 +42,9 @@
#include "jsatominlines.h"
#include "jsboolinlines.h"
#include "jsinferinlines.h"
-#include "jsobjinlines.h"
#include "jsopcodeinlines.h"
#include "jsscriptinlines.h"
+
#include "builtin/Iterator-inl.h"
#include "ion/IonFrames-inl.h"
#include "vm/Interpreter-inl.h"
@@ -280,6 +280,9 @@ js::ValueToCallable(JSContext *cx, const Value &v, int numToSkip, MaybeConstruct
return NULL;
}
+static JS_NEVER_INLINE bool
+Interpret(JSContext *cx, StackFrame *entryFrame);
+
bool
js::RunScript(JSContext *cx, StackFrame *fp)
{
@@ -342,7 +345,7 @@ js::RunScript(JSContext *cx, StackFrame *fp)
}
#endif
- return Interpret(cx, fp) != Interpret_Error;
+ return Interpret(cx, fp);
}
/*
@@ -985,13 +988,12 @@ js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
return js_IteratorNext(cx, iterobj, rval);
}
-JS_NEVER_INLINE InterpretStatus
-js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool useNewType)
+static JS_NEVER_INLINE bool
+Interpret(JSContext *cx, StackFrame *entryFrame)
{
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
- if (interpMode == JSINTERP_NORMAL)
- gc::MaybeVerifyBarriers(cx, true);
+ gc::MaybeVerifyBarriers(cx, true);
JS_ASSERT(!cx->compartment()->activeAnalysis);
@@ -1060,8 +1062,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool
script = (s); \
if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts) \
interrupts.enable(); \
- JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP, \
- script->hasAnyBreakpointsOrStepMode()); \
JS_END_MACRO
/* Repoint cx->regs to a local variable for faster access. */
@@ -1128,43 +1128,28 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool
/* State communicated between non-local jumps: */
bool interpReturnOK;
- /* Don't call the script prologue if executing between Method and Trace JIT. */
- if (interpMode == JSINTERP_NORMAL) {
- StackFrame *fp = regs.fp();
- if (!fp->isGeneratorFrame()) {
- if (!fp->prologue(cx))
- goto error;
- } else {
- Probes::enterScript(cx, script, script->function(), fp);
- }
- if (cx->compartment()->debugMode()) {
- JSTrapStatus status = ScriptDebugPrologue(cx, fp);
- switch (status) {
- case JSTRAP_CONTINUE:
- break;
- case JSTRAP_RETURN:
- interpReturnOK = true;
- goto forced_return;
- case JSTRAP_THROW:
- case JSTRAP_ERROR:
- goto error;
- default:
- JS_NOT_REACHED("bad ScriptDebugPrologue status");
- }
+ if (!entryFrame->isGeneratorFrame()) {
+ if (!entryFrame->prologue(cx))
+ goto error;
+ } else {
+ Probes::enterScript(cx, script, script->function(), entryFrame);
+ }
+ if (cx->compartment()->debugMode()) {
+ JSTrapStatus status = ScriptDebugPrologue(cx, entryFrame);
+ switch (status) {
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ interpReturnOK = true;
+ goto forced_return;
+ case JSTRAP_THROW:
+ case JSTRAP_ERROR:
+ goto error;
+ default:
+ JS_NOT_REACHED("bad ScriptDebugPrologue status");
}
}
- /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */
- if (interpMode == JSINTERP_REJOIN)
- interpMode = JSINTERP_NORMAL;
-
- /*
- * The RETHROW mode acts like a bailout mode, except that it resume an
- * exception instead of resuming the script.
- */
- if (interpMode == JSINTERP_RETHROW)
- goto error;
-
/*
* It is important that "op" be initialized before calling DO_OP because
* it is possible for "op" to be specially assigned during the normal
@@ -1240,7 +1225,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool
if (script->hasAnyBreakpointsOrStepMode())
moreInterrupts = true;
- if (script->hasBreakpointsAt(regs.pc) && interpMode != JSINTERP_SKIP_TRAP) {
+ if (script->hasBreakpointsAt(regs.pc)) {
RootedValue rval(cx);
JSTrapStatus status = Debugger::onTrap(cx, &rval);
switch (status) {
@@ -1260,8 +1245,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool
JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
}
- interpMode = JSINTERP_NORMAL;
-
switchMask = moreInterrupts ? -1 : 0;
switchOp = int(op);
goto do_switch;
@@ -3022,9 +3005,6 @@ END_CASE(JSOP_ARRAYPUSH)
JS_ASSERT(&cx->regs() == ®s);
JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
- /* When rejoining, we must not err before finishing Interpret's prologue. */
- JS_ASSERT(interpMode != JSINTERP_REJOIN);
-
if (cx->isExceptionPending()) {
/* Call debugger throw hooks. */
if (cx->compartment()->debugMode()) {
@@ -3149,7 +3129,7 @@ END_CASE(JSOP_ARRAYPUSH)
leave_on_safe_point:
#endif
- return interpReturnOK ? Interpret_Ok : Interpret_Error;
+ return interpReturnOK;
}
bool
@@ -3259,7 +3239,7 @@ js::DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain,
*/
RootedFunction fun(cx, funArg);
if (fun->isNative() || fun->environment() != scopeChain) {
- fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain);
+ fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain, TenuredObject);
if (!fun)
return false;
} else {
diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h
index 61605bb508dd..f46b63d048ac 100644
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -164,31 +164,6 @@ ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Va
extern bool
Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval);
-/* Flags to toggle js::Interpret() execution. */
-enum InterpMode
-{
- JSINTERP_NORMAL = 0, /* interpreter is running normally */
- JSINTERP_REJOIN = 1, /* as normal, but the frame has already started */
- JSINTERP_SKIP_TRAP = 2, /* as REJOIN, but skip trap at first opcode */
- JSINTERP_BAILOUT = 3, /* interpreter is running from an Ion bailout */
- JSINTERP_RETHROW = 4 /* as BAILOUT, but unwind all frames */
-};
-
-enum InterpretStatus
-{
- Interpret_Error = 0, /* interpreter had an error */
- Interpret_Ok = 1, /* interpreter executed successfully */
- Interpret_OSR = 2 /* when mode=BAILOUT and we should OSR into Ion */
-};
-
-/*
- * Execute the caller-initialized frame for a user-defined script or function
- * pointed to by cx->fp until completion or error.
- */
-extern JS_NEVER_INLINE InterpretStatus
-Interpret(JSContext *cx, StackFrame *stopFp, InterpMode mode = JSINTERP_NORMAL,
- bool useNewType = false);
-
extern bool
RunScript(JSContext *cx, StackFrame *fp);
diff --git a/js/src/vm/NumberObject-inl.h b/js/src/vm/NumberObject-inl.h
index 651cb93d6ddd..5e899d288791 100644
--- a/js/src/vm/NumberObject-inl.h
+++ b/js/src/vm/NumberObject-inl.h
@@ -9,6 +9,8 @@
#include "NumberObject.h"
+#include "jsobjinlines.h"
+
namespace js {
inline NumberObject *
diff --git a/js/src/vm/ObjectImpl-inl.h b/js/src/vm/ObjectImpl-inl.h
index e539041f5636..745d75116f52 100644
--- a/js/src/vm/ObjectImpl-inl.h
+++ b/js/src/vm/ObjectImpl-inl.h
@@ -204,24 +204,6 @@ js::ObjectImpl::invalidateSlotRange(uint32_t start, uint32_t length)
#endif /* DEBUG */
}
-inline void
-js::ObjectImpl::initializeSlotRange(uint32_t start, uint32_t length)
-{
- /*
- * No bounds check, as this is used when the object's shape does not
- * reflect its allocated slots (updateSlotsForSpan).
- */
- HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
- getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
-
- JSRuntime *rt = runtime();
- uint32_t offset = start;
- for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
- sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
- for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
- sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
-}
-
inline bool
js::ObjectImpl::isNative() const
{
@@ -332,12 +314,6 @@ js::ObjectImpl::getJSClass() const
return Jsvalify(getClass());
}
-inline bool
-js::ObjectImpl::hasClass(const Class *c) const
-{
- return getClass() == c;
-}
-
inline const js::ObjectOps *
js::ObjectImpl::getOps() const
{
@@ -456,38 +432,6 @@ js::ObjectImpl::writeBarrierPost(ObjectImpl *obj, void *addr)
#endif
}
-inline bool
-js::ObjectImpl::hasPrivate() const
-{
- return getClass()->hasPrivate();
-}
-
-inline void *&
-js::ObjectImpl::privateRef(uint32_t nfixed) const
-{
- /*
- * The private pointer of an object can hold any word sized value.
- * Private pointers are stored immediately after the last fixed slot of
- * the object.
- */
- MOZ_ASSERT(nfixed == numFixedSlots());
- MOZ_ASSERT(hasPrivate());
- HeapSlot *end = &fixedSlots()[nfixed];
- return *reinterpret_cast(end);
-}
-
-inline void *
-js::ObjectImpl::getPrivate() const
-{
- return privateRef(numFixedSlots());
-}
-
-inline void *
-js::ObjectImpl::getPrivate(uint32_t nfixed) const
-{
- return privateRef(nfixed);
-}
-
inline void
js::ObjectImpl::setPrivate(void *data)
{
diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp
index 47614737b126..085d9f030d7c 100644
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -13,6 +13,7 @@
#include "vm/ObjectImpl.h"
#include "jsatominlines.h"
+#include "jsobjinlines.h"
#include "gc/Barrier-inl.h"
#include "gc/Marking.h"
@@ -247,6 +248,24 @@ js::ObjectImpl::checkShapeConsistency()
}
#endif
+void
+js::ObjectImpl::initializeSlotRange(uint32_t start, uint32_t length)
+{
+ /*
+ * No bounds check, as this is used when the object's shape does not
+ * reflect its allocated slots (updateSlotsForSpan).
+ */
+ HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
+ getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
+
+ JSRuntime *rt = runtime();
+ uint32_t offset = start;
+ for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
+ sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
+ for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
+ sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
+}
+
void
js::ObjectImpl::initSlotRange(uint32_t start, const Value *vector, uint32_t length)
{
diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h
index 1e8dd9b41256..7d58b3855d42 100644
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -1251,7 +1251,7 @@ class ObjectImpl : public gc::Cell
friend class NewObjectCache;
inline void invalidateSlotRange(uint32_t start, uint32_t count);
- inline void initializeSlotRange(uint32_t start, uint32_t count);
+ void initializeSlotRange(uint32_t start, uint32_t count);
/*
* Initialize a flat array of slots to this object at a start slot. The
@@ -1372,7 +1372,9 @@ class ObjectImpl : public gc::Cell
inline bool nativeContainsPure(Shape* shape);
inline JSClass *getJSClass() const;
- inline bool hasClass(const Class *c) const;
+ inline bool hasClass(const Class *c) const {
+ return getClass() == c;
+ }
inline const ObjectOps *getOps() const;
/*
@@ -1509,17 +1511,33 @@ class ObjectImpl : public gc::Cell
/* Private data accessors. */
- inline void *&privateRef(uint32_t nfixed) const; /* XXX should be private, not protected! */
+ inline void *&privateRef(uint32_t nfixed) const { /* XXX should be private, not protected! */
+ /*
+ * The private pointer of an object can hold any word sized value.
+ * Private pointers are stored immediately after the last fixed slot of
+ * the object.
+ */
+ MOZ_ASSERT(nfixed == numFixedSlots());
+ MOZ_ASSERT(hasPrivate());
+ HeapSlot *end = &fixedSlots()[nfixed];
+ return *reinterpret_cast(end);
+ }
- inline bool hasPrivate() const;
- inline void *getPrivate() const;
+ inline bool hasPrivate() const {
+ return getClass()->hasPrivate();
+ }
+ inline void *getPrivate() const {
+ return privateRef(numFixedSlots());
+ }
inline void setPrivate(void *data);
inline void setPrivateGCThing(gc::Cell *cell);
inline void setPrivateUnbarriered(void *data);
inline void initPrivate(void *data);
/* Access private data for an object with a known number of fixed slots. */
- inline void *getPrivate(uint32_t nfixed) const;
+ inline void *getPrivate(uint32_t nfixed) const {
+ return privateRef(nfixed);
+ }
/* JIT Accessors */
static size_t offsetOfShape() { return offsetof(ObjectImpl, shape_); }
diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h
index dba31d91f694..7a9fbd8ba255 100644
--- a/js/src/vm/RegExpObject-inl.h
+++ b/js/src/vm/RegExpObject-inl.h
@@ -11,7 +11,6 @@
#include "RegExpObject.h"
-#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "String-inl.h"
diff --git a/js/src/vm/RegExpStatics-inl.h b/js/src/vm/RegExpStatics-inl.h
index 56ad17d3efe0..c3311e825f18 100644
--- a/js/src/vm/RegExpStatics-inl.h
+++ b/js/src/vm/RegExpStatics-inl.h
@@ -7,9 +7,12 @@
#ifndef RegExpStatics_inl_h__
#define RegExpStatics_inl_h__
-#include "RegExpStatics.h"
+#include "vm/RegExpStatics.h"
#include "gc/Marking.h"
+
+#include "jsinferinlines.h"
+
#include "vm/String-inl.h"
namespace js {
diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp
index 3ec25d429e9e..0e59b38d14b1 100644
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -17,7 +17,8 @@
#include "jsatominlines.h"
#include "jsobjinlines.h"
-#include "ScopeObject-inl.h"
+#include "gc/Barrier-inl.h"
+#include "vm/ScopeObject-inl.h"
using namespace js;
using namespace js::types;
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
index a3f7798046d8..20addd06ae27 100644
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -341,15 +341,26 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
/*
* UnsafeSetElement(arr0, idx0, elem0, ..., arrN, idxN, elemN): For
* each set of (arr, idx, elem) arguments that are passed, performs
- * the assignment |arr[idx] = elem|. |arr| must be either a dense array
+ * the assignment `arr[idx] = elem`. `arr` must be either a dense array
* or a typed array.
*
- * If |arr| is a dense array, the index must be an int32 less than the
- * initialized length of |arr|. Use |%EnsureDenseResultArrayElements|
- * to ensure that the initialized length is long enough.
+ * If `arr` is a dense array, the index must be an int32 less than the
+ * initialized length of `arr`. Use `NewDenseAllocatedArray` to ensure
+ * that the initialized length is long enough.
*
- * If |arr| is a typed array, the index must be an int32 less than the
- * length of |arr|.
+ * If `arr` is a typed array, the index must be an int32 less than the
+ * length of `arr`.
+ *
+ * The reason that `UnsafeSetElement` takes multiple
+ * array/index/element triples is not for convenience but rather for
+ * semantic reasons: there are a few places in the parallel code where
+ * correctness relies on the fact that *all of the assignments occur
+ * or none of them*. This occurs in operations like reduce or fold
+ * which mutate the same data in place. That is, we do not want to
+ * bail out or interrupt in between the individual assignments. To
+ * convey this notion, we place all the assignments together into one
+ * `UnsafeSetElement` call. It is preferable to use multiple calls if
+ * it is not important that the assignments occur all-or-nothing.
*/
JSBool
js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
@@ -380,7 +391,6 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
} else {
JS_ASSERT(idx < TypedArray::length(arrobj));
RootedValue tmp(cx, args[elemi]);
- // XXX: Always non-strict.
if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false))
return false;
}
@@ -390,6 +400,46 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
return true;
}
+/*
+ * UnsafeGetElement(arr, idx)=elem:
+ *
+ * Loads an element from an array. Requires that `arr` be a dense
+ * array and `idx` be in bounds. In ion compiled code, no bounds
+ * check will be emitted.
+ */
+JSBool
+js::intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ const uint32_t arri = 0;
+ const uint32_t idxi = 1;
+
+ JS_ASSERT(args[arri].isObject());
+ JS_ASSERT(args[idxi].isInt32());
+
+ RootedObject arrobj(cx, &args[arri].toObject());
+ uint32_t idx = args[idxi].toInt32();
+
+ JS_ASSERT(args[arri].toObject().isNative());
+ JS_ASSERT(idx < arrobj->getDenseInitializedLength());
+ args.rval().set(arrobj->getDenseElement(idx));
+ return true;
+}
+
+/*
+ * UnsafeGetImmutableElement(arr, idx)=elem:
+ *
+ * Same as `UnsafeGetElement(arr, idx)`, except that the array is
+ * known by the self-hosting code to be immutable. Therefore, ion
+ * compilation can reorder this load freely with respect to stores.
+ */
+JSBool
+js::intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc, Value *vp)
+{
+ return intrinsic_UnsafeGetElement(cx, argc, vp);
+}
+
/*
* ParallelTestsShouldPass(): Returns false if we are running in a
* mode (such as --ion-eager) that is known to cause additional
@@ -468,6 +518,8 @@ const JSFunctionSpec intrinsic_functions[] = {
JS_FN("NewParallelArray", intrinsic_NewParallelArray, 3,0),
JS_FN("NewDenseArray", intrinsic_NewDenseArray, 1,0),
JS_FN("UnsafeSetElement", intrinsic_UnsafeSetElement, 3,0),
+ JS_FN("UnsafeGetElement", intrinsic_UnsafeGetElement, 2,0),
+ JS_FN("UnsafeGetImmutableElement", intrinsic_UnsafeGetImmutableElement, 2,0),
JS_FN("ShouldForceSequential", intrinsic_ShouldForceSequential, 0,0),
JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0),
diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h
index 8681fde27779..0d55fe13945a 100644
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -22,9 +22,9 @@
#include "vm/ScopeObject.h"
#include "vm/StringObject.h"
+#include "jsatominlines.h"
#include "jscntxtinlines.h"
#include "jsgcinlines.h"
-#include "jsobjinlines.h"
#include "vm/ScopeObject-inl.h"
diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h
index 191f01328e6d..1e8562961e69 100644
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -441,19 +441,6 @@ AbstractFramePtr::setReturnValue(const Value &rval) const
#endif
}
-inline bool
-AbstractFramePtr::hasPushedSPSFrame() const
-{
- if (isStackFrame())
- return asStackFrame()->hasPushedSPSFrame();
-#ifdef JS_ION
- return asBaselineFrame()->hasPushedSPSFrame();
-#else
- JS_NOT_REACHED("Invalid frame");
- return false;
-#endif
-}
-
inline JSObject *
AbstractFramePtr::scopeChain() const
{
diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp
index fc5c77484ee2..bffdaa8ae884 100644
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -4,22 +4,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "vm/Stack.h"
+
#include "mozilla/DebugOnly.h"
#include "mozilla/PodOperations.h"
#include "jscntxt.h"
#include "jsopcode.h"
+
#include "gc/Marking.h"
#ifdef JS_ION
#include "ion/BaselineFrame.h"
#include "ion/IonFrames.h"
#include "ion/IonCompartment.h"
#endif
-#include "vm/Stack.h"
#include "vm/ForkJoin.h"
#include "jsgcinlines.h"
-#include "jsobjinlines.h"
+
#include "vm/Interpreter-inl.h"
#include "vm/Stack-inl.h"
#include "vm/Probes-inl.h"
@@ -1826,6 +1828,19 @@ AbstractFramePtr::evalPrevScopeChain(JSContext *cx) const
return iter.scopeChain();
}
+bool
+AbstractFramePtr::hasPushedSPSFrame() const
+{
+ if (isStackFrame())
+ return asStackFrame()->hasPushedSPSFrame();
+#ifdef JS_ION
+ return asBaselineFrame()->hasPushedSPSFrame();
+#else
+ JS_NOT_REACHED("Invalid frame");
+ return false;
+#endif
+}
+
#ifdef DEBUG
void
js::CheckLocalUnaliased(MaybeCheckAliasing checkAliasing, JSScript *script,
diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h
index cf2a06396df8..2acbc1b2fd8e 100644
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -233,7 +233,7 @@ class AbstractFramePtr
inline Value returnValue() const;
inline void setReturnValue(const Value &rval) const;
- inline bool hasPushedSPSFrame() const;
+ bool hasPushedSPSFrame() const;
inline void popBlock(JSContext *cx) const;
inline void popWith(JSContext *cx) const;
diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h
index 3151bf8036e4..9feb52f18b36 100644
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -15,7 +15,6 @@
#include "gc/Marking.h"
#include "jsgcinlines.h"
-#include "jsobjinlines.h"
namespace js {
diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp
index fbb622588149..34de8b730a0e 100644
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -4,15 +4,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "vm/String.h"
+
#include "mozilla/PodOperations.h"
#include "mozilla/RangedPtr.h"
#include "gc/Marking.h"
-#include "String.h"
-#include "String-inl.h"
+#include "jscompartmentinlines.h"
-#include "jsobjinlines.h"
+#include "String-inl.h"
using namespace js;
diff --git a/js/src/vm/StringObject-inl.h b/js/src/vm/StringObject-inl.h
index 2dd4c70d9c47..852cdb76067b 100644
--- a/js/src/vm/StringObject-inl.h
+++ b/js/src/vm/StringObject-inl.h
@@ -9,6 +9,8 @@
#include "StringObject.h"
+#include "jsobjinlines.h"
+
namespace js {
inline bool
diff --git a/js/src/vm/Xdr.cpp b/js/src/vm/Xdr.cpp
index 73620f83ba9a..f32266d66b61 100644
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -19,10 +19,10 @@
#include "jsscript.h"
#include "jsstr.h"
-#include "Xdr.h"
-#include "Debugger.h"
+#include "vm/Xdr.h"
+#include "vm/Debugger.h"
-#include "jsobjinlines.h"
+#include "jsscriptinlines.h"
using namespace js;
@@ -139,6 +139,24 @@ XDRState::codeScript(MutableHandleScript scriptp)
return true;
}
+template
+void
+XDRState::initScriptPrincipals(JSScript *script)
+{
+ JS_ASSERT(mode == XDR_DECODE);
+
+ /* The origin principals must be normalized at this point. */
+ JS_ASSERT_IF(principals, originPrincipals);
+ JS_ASSERT(!script->originPrincipals);
+ if (principals)
+ JS_ASSERT(script->principals() == principals);
+
+ if (originPrincipals) {
+ script->originPrincipals = originPrincipals;
+ JS_HoldPrincipals(originPrincipals);
+ }
+}
+
XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,
JSPrincipals *principals, JSPrincipals *originPrincipals)
: XDRState(cx)
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index 595d4146aa46..b34a66e9bad4 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -211,20 +211,7 @@ class XDRState {
bool codeFunction(JS::MutableHandleObject objp);
bool codeScript(MutableHandleScript scriptp);
- void initScriptPrincipals(JSScript *script) {
- JS_ASSERT(mode == XDR_DECODE);
-
- /* The origin principals must be normalized at this point. */
- JS_ASSERT_IF(principals, originPrincipals);
- JS_ASSERT(!script->originPrincipals);
- if (principals)
- JS_ASSERT(script->principals() == principals);
-
- if (originPrincipals) {
- script->originPrincipals = originPrincipals;
- JS_HoldPrincipals(originPrincipals);
- }
- }
+ void initScriptPrincipals(JSScript *script);
};
class XDREncoder : public XDRState {
diff --git a/js/xpconnect/src/XPCCallContext.cpp b/js/xpconnect/src/XPCCallContext.cpp
index ca20ff70711b..44b3d0c0a705 100644
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -98,11 +98,8 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
}
} else {
js::Class *clasp = js::GetObjectClass(unwrapped);
- if (IS_WRAPPER_CLASS(clasp)) {
- if (IS_SLIM_WRAPPER_OBJECT(unwrapped))
- mFlattenedJSObject = unwrapped;
- else
- mWrapper = XPCWrappedNative::Get(unwrapped);
+ if (IS_WN_CLASS(clasp)) {
+ mWrapper = XPCWrappedNative::Get(unwrapped);
} else if (IS_TEAROFF_CLASS(clasp)) {
mTearOff = (XPCWrappedNativeTearOff*)js::GetObjectPrivate(unwrapped);
mWrapper = XPCWrappedNative::Get(js::GetObjectParent(unwrapped));
@@ -116,8 +113,7 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
else
mScriptableInfo = mWrapper->GetScriptableInfo();
} else {
- NS_ABORT_IF_FALSE(!mFlattenedJSObject || IS_SLIM_WRAPPER(mFlattenedJSObject),
- "should have a slim wrapper");
+ NS_ABORT_IF_FALSE(!mFlattenedJSObject, "What object do we have?");
}
if (!JSID_IS_VOID(name))
@@ -425,8 +421,7 @@ XPCCallContext::UnwrapThisIfAllowed(HandleObject obj, HandleObject fun, unsigned
MOZ_ASSERT(unwrapped == JS_ObjectToInnerObject(mJSContext, js::Wrapper::wrappedObject(obj)));
// Make sure we have an XPCWN, and grab it.
- MOZ_ASSERT(!IS_SLIM_WRAPPER(unwrapped), "security wrapping morphs slim wrappers");
- if (!IS_WRAPPER_CLASS(js::GetObjectClass(unwrapped)))
+ if (!IS_WN_REFLECTOR(unwrapped))
return nullptr;
XPCWrappedNative *wn = (XPCWrappedNative*)js::GetObjectPrivate(unwrapped);
diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index c9c4b2b7525b..21a477a64624 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2684,10 +2684,6 @@ nsXPCComponents_Utils::LookupMethod(const JS::Value& object,
// Enter the target compartment.
JSAutoCompartment ac(cx, obj);
- // Morph slim wrappers.
- if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
- return NS_ERROR_FAILURE;
-
// Now, try to create an Xray wrapper around the object. This won't work
// if the object isn't Xray-able. In that case, we throw.
JSObject *xray = WrapperFactory::WrapForSameCompartmentXray(cx, obj);
@@ -3316,7 +3312,7 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
// Now check what sort of thing we've got in |proto|
JSObject *unwrappedProto = js::UncheckedUnwrap(options.proto, false);
js::Class *unwrappedClass = js::GetObjectClass(unwrappedProto);
- if (IS_WRAPPER_CLASS(unwrappedClass) ||
+ if (IS_WN_CLASS(unwrappedClass) ||
mozilla::dom::IsDOMClass(Jsvalify(unwrappedClass))) {
// Wrap it up in a proxy that will do the right thing in terms
// of this-binding for methods.
diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp
index 4e90d835dd5c..f1ce4953544e 100644
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -819,7 +819,6 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
// object will create (and fill the cache) from its WrapObject call.
nsWrapperCache *cache = aHelper.GetWrapperCache();
- bool tryConstructSlimWrapper = false;
RootedObject flat(cx);
if (cache) {
flat = cache->GetWrapper();
@@ -839,40 +838,10 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
return CreateHolderIfNeeded(flat, d, dest);
}
}
-
- if (!dest) {
- if (!flat) {
- tryConstructSlimWrapper = true;
- } else if (IS_SLIM_WRAPPER_OBJECT(flat)) {
- if (js::IsObjectInContextCompartment(flat, cx)) {
- *d = OBJECT_TO_JSVAL(flat);
- return true;
- }
- }
- }
} else {
flat = nullptr;
}
- // If we're not handing this wrapper to an nsIXPConnectJSObjectHolder, and
- // the object supports slim wrappers, try to create one here.
- if (tryConstructSlimWrapper) {
- RootedValue slim(cx);
- if (ConstructSlimWrapper(aHelper, xpcscope, &slim)) {
- *d = slim;
- return true;
- }
-
- if (JS_IsExceptionPending(cx))
- return false;
-
- // Even if ConstructSlimWrapper returns false it might have created a
- // wrapper (while calling the PreCreate hook). In that case we need to
- // fall through because we either have a slim wrapper that needs to be
- // morphed or an XPCWrappedNative.
- flat = cache->GetWrapper();
- }
-
// We can't simply construct a slim wrapper. Go ahead and create an
// XPCWrappedNative for this object. At this point, |flat| could be
// non-null, meaning that either we already have a wrapped native from
@@ -893,8 +862,7 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
}
}
- NS_ASSERTION(!flat || IS_WRAPPER_CLASS(js::GetObjectClass(flat)),
- "What kind of wrapper is this?");
+ NS_ASSERTION(!flat || IS_WN_REFLECTOR(flat), "What kind of wrapper is this?");
nsresult rv;
XPCWrappedNative* wrapper;
@@ -904,7 +872,9 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
getter_AddRefs(strongWrapper));
wrapper = strongWrapper;
- } else if (IS_WN_WRAPPER_OBJECT(flat)) {
+ } else {
+ MOZ_ASSERT(IS_WN_REFLECTOR(flat));
+
wrapper = static_cast(xpc_GetJSPrivate(flat));
// If asked to return the wrapper we'll return a strong reference,
@@ -916,17 +886,6 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
wrapper->FindTearOff(iface, false, &rv);
else
rv = NS_OK;
- } else {
- NS_ASSERTION(IS_SLIM_WRAPPER(flat),
- "What kind of wrapper is this?");
-
- SLIM_LOG(("***** morphing from XPCConvert::NativeInterface2JSObject"
- "(%p)\n",
- static_cast(xpc_GetJSPrivate(flat))));
-
- rv = XPCWrappedNative::Morph(flat, iface, cache,
- getter_AddRefs(strongWrapper));
- wrapper = strongWrapper;
}
if (NS_FAILED(rv) && pErr)
@@ -1025,7 +984,7 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
// Is this really a native xpcom object with a wrapper?
XPCWrappedNative* wrappedNative = nullptr;
- if (IS_WN_WRAPPER(inner))
+ if (IS_WN_REFLECTOR(inner))
wrappedNative = XPCWrappedNative::Get(inner);
if (wrappedNative) {
iface = wrappedNative->GetIdentityObject();
@@ -1156,8 +1115,8 @@ XPCConvert::JSValToXPCException(jsval sArg,
JSObject *unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
if (!unwrapped)
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
- XPCWrappedNative* wrapper = IS_WN_WRAPPER(unwrapped) ? XPCWrappedNative::Get(unwrapped)
- : nullptr;
+ XPCWrappedNative* wrapper = IS_WN_REFLECTOR(unwrapped) ? XPCWrappedNative::Get(unwrapped)
+ : nullptr;
if (wrapper) {
nsISupports* supports = wrapper->GetIdentityObject();
nsCOMPtr iface = do_QueryInterface(supports);
diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h
index c17dec24cf23..30a303b9aabb 100644
--- a/js/xpconnect/src/XPCInlines.h
+++ b/js/xpconnect/src/XPCInlines.h
@@ -121,9 +121,7 @@ inline XPCWrappedNativeProto*
XPCCallContext::GetProto() const
{
CHECK_STATE(HAVE_OBJECT);
- if (mWrapper)
- return mWrapper->GetProto();
- return mFlattenedJSObject ? GetSlimWrapperProto(mFlattenedJSObject) : nullptr;
+ return mWrapper ? mWrapper->GetProto() : nullptr;
}
inline JSBool
diff --git a/js/xpconnect/src/XPCJSID.cpp b/js/xpconnect/src/XPCJSID.cpp
index 175731354f38..8c7d59807fda 100644
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -470,14 +470,13 @@ nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
* there's chrome code that relies on this.
*
* This static method handles both complexities, returning either an XPCWN, a
- * slim wrapper, a DOM object, or null. The object may well be cross-compartment
- * from |cx|.
+ * DOM object, or null. The object may well be cross-compartment from |cx|.
*/
static JSObject *
FindObjectForHasInstance(JSContext *cx, HandleObject objArg)
{
RootedObject obj(cx, objArg), proto(cx);
- while (obj && !IS_WRAPPER_CLASS(js::GetObjectClass(obj)) && !IsDOMObject(obj)) {
+ while (obj && !IS_WN_REFLECTOR(obj) && !IsDOMObject(obj)) {
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
continue;
@@ -505,7 +504,6 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
NS_ASSERTION(obj, "when is an object not an object?");
- nsISupports *identity = nullptr;
// is this really a native xpcom object with a wrapper?
const nsIID* iid;
mInfo->GetIIDShared(&iid);
@@ -514,33 +512,19 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
if (!obj)
return NS_OK;
- if (IS_SLIM_WRAPPER(obj)) {
- XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj);
- if (proto->GetSet()->HasInterfaceWithAncestor(iid)) {
- *bp = true;
+ if (IsDOMObject(obj)) {
+ // Not all DOM objects implement nsISupports. But if they don't,
+ // there's nothing to do in this HasInstance hook.
+ nsISupports *identity = UnwrapDOMObjectToISupports(obj);
+ if (!identity)
return NS_OK;
- }
-
-#ifdef DEBUG_slimwrappers
- char foo[NSID_LENGTH];
- iid->ToProvidedString(foo);
- SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, foo);
-#endif
- if (!MorphSlimWrapper(cx, obj))
- return NS_ERROR_FAILURE;
- } else if (IsDOMObject(obj)) {
- // Not all DOM objects implement nsISupports. But if they don't,
- // there's nothing to do in this HasInstance hook.
- identity = UnwrapDOMObjectToISupports(obj);
- if (!identity)
- return NS_OK;
- nsCOMPtr supp;
- identity->QueryInterface(*iid, getter_AddRefs(supp));
- *bp = supp;
- return NS_OK;
+ nsCOMPtr supp;
+ identity->QueryInterface(*iid, getter_AddRefs(supp));
+ *bp = supp;
+ return NS_OK;
}
- MOZ_ASSERT(IS_WN_WRAPPER(obj));
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
if (!other_wrapper)
return NS_OK;
@@ -857,11 +841,9 @@ nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
// is this really a native xpcom object with a wrapper?
nsIClassInfo* ci = nullptr;
obj = FindObjectForHasInstance(cx, obj);
- if (!obj || !IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
+ if (!obj || !IS_WN_REFLECTOR(obj))
return rv;
- if (IS_SLIM_WRAPPER_OBJECT(obj))
- ci = GetSlimWrapperProto(obj)->GetClassInfo();
- else if (XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj))
+ if (XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj))
ci = other_wrapper->GetClassInfo();
// We consider CID equality to be the thing that matters here.
@@ -911,7 +893,7 @@ xpc_JSObjectToID(JSContext *cx, JSObject* obj)
// NOTE: this call does NOT addref
XPCWrappedNative* wrapper = nullptr;
obj = js::CheckedUnwrap(obj);
- if (obj && IS_WN_WRAPPER(obj))
+ if (obj && IS_WN_REFLECTOR(obj))
wrapper = XPCWrappedNative::Get(obj);
if (wrapper &&
(wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
@@ -929,7 +911,7 @@ xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
// NOTE: this call does NOT addref
XPCWrappedNative* wrapper = nullptr;
obj = js::CheckedUnwrap(obj);
- if (obj && IS_WN_WRAPPER(obj))
+ if (obj && IS_WN_REFLECTOR(obj))
wrapper = XPCWrappedNative::Get(obj);
return wrapper &&
(wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
index cd3e312f7845..4b83e0fe56ed 100644
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2537,14 +2537,10 @@ PreserveWrapper(JSContext *cx, JSObject *objArg)
if (!ccx.IsValid())
return false;
- if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
+ if (!IS_WN_REFLECTOR(obj))
return mozilla::dom::TryPreserveWrapper(obj);
- nsISupports *supports = nullptr;
- if (IS_WN_WRAPPER_OBJECT(obj))
- supports = XPCWrappedNative::Get(obj)->Native();
- else
- supports = static_cast(xpc_GetJSPrivate(obj));
+ nsISupports *supports = XPCWrappedNative::Get(obj)->Native();
// For pre-Paris DOM bindings objects, we only support Node.
if (nsCOMPtr node = do_QueryInterface(supports)) {
diff --git a/js/xpconnect/src/XPCLog.cpp b/js/xpconnect/src/XPCLog.cpp
index eebe50fb98c8..c659183dc9c0 100644
--- a/js/xpconnect/src/XPCLog.cpp
+++ b/js/xpconnect/src/XPCLog.cpp
@@ -90,36 +90,3 @@ XPC_Log_Clear_Indent()
}
#endif
-
-#ifdef DEBUG_slimwrappers
-void
-LogSlimWrapperWillMorph(JSContext *cx, JSObject *obj, const char *propname,
- const char *functionName)
-{
- if (obj && IS_SLIM_WRAPPER(obj)) {
- XPCNativeScriptableInfo *si =
- GetSlimWrapperProto(obj)->GetScriptableInfo();
- printf("***** morphing %s from %s", si->GetJSClass()->name,
- functionName);
- if (propname)
- printf(" for %s", propname);
- printf(" (%p, %p)\n", obj,
- static_cast(xpc_GetJSPrivate(obj)));
- xpc_DumpJSStack(cx, false, false, false);
- }
-}
-
-void
-LogSlimWrapperNotCreated(JSContext *cx, nsISupports *obj, const char *reason)
-{
- char* className = nullptr;
- nsCOMPtr ci = do_QueryInterface(obj);
- if (ci)
- ci->GetClassDescription(&className);
- printf("***** refusing to create slim wrapper%s%s, reason: %s (%p)\n",
- className ? " for " : "", className ? className : "", reason, obj);
- if (className)
- PR_Free(className);
- xpc_DumpJSStack(cx, false, false, false);
-}
-#endif
diff --git a/js/xpconnect/src/XPCLog.h b/js/xpconnect/src/XPCLog.h
index 42b8c08ec999..7bf52900ae58 100644
--- a/js/xpconnect/src/XPCLog.h
+++ b/js/xpconnect/src/XPCLog.h
@@ -64,58 +64,4 @@ JS_END_EXTERN_C
#define XPC_LOG_FINISH() ((void)0)
#endif
-
-#ifdef DEBUG_peterv
-#define DEBUG_slimwrappers 1
-#endif
-
-#ifdef DEBUG_slimwrappers
-extern void LogSlimWrapperWillMorph(JSContext *cx, JSObject *obj,
- const char *propname,
- const char *functionName);
-extern void LogSlimWrapperNotCreated(JSContext *cx, nsISupports *obj,
- const char *reason);
-
-#define SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, prop) \
- PR_BEGIN_MACRO \
- LogSlimWrapperWillMorph(cx, obj, (const char*)prop, __FUNCTION__); \
- PR_END_MACRO
-#define SLIM_LOG_WILL_MORPH_FOR_ID(cx, obj, id) \
- PR_BEGIN_MACRO \
- JSString* strId = ::JS_ValueToString(cx, id); \
- if (strId) { \
- NS_ConvertUTF16toUTF8 name((PRUnichar*)::JS_GetStringChars(strId), \
- ::JS_GetStringLength(strId)); \
- LOG_WILL_MORPH_FOR_PROP(cx, obj, name.get()); \
- } \
- else \
- { \
- LOG_WILL_MORPH_FOR_PROP(cx, obj, nullptr); \
- } \
- PR_END_MACRO
-#define SLIM_LOG_NOT_CREATED(cx, obj, reason) \
- PR_BEGIN_MACRO \
- LogSlimWrapperNotCreated(cx, obj, reason); \
- PR_END_MACRO
-#define SLIM_LOG(_args) \
- PR_BEGIN_MACRO \
- printf _args; \
- PR_END_MACRO
-#else
-#define SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, prop) \
- PR_BEGIN_MACRO \
- PR_END_MACRO
-#define SLIM_LOG_WILL_MORPH_FOR_ID(cx, obj) \
- PR_BEGIN_MACRO \
- PR_END_MACRO
-#define SLIM_LOG_NOT_CREATED(cx, obj, reason) \
- PR_BEGIN_MACRO \
- PR_END_MACRO
-#define SLIM_LOG(_args) \
- PR_BEGIN_MACRO \
- PR_END_MACRO
-#endif
-#define SLIM_LOG_WILL_MORPH(cx, obj) \
- SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, nullptr)
-
#endif /* xpclog_h___ */
diff --git a/js/xpconnect/src/XPCQuickStubs.cpp b/js/xpconnect/src/XPCQuickStubs.cpp
index 924b95f33b6d..4599e9be9397 100644
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -69,7 +69,7 @@ LookupInterfaceOrAncestor(uint32_t tableSize, const xpc_qsHashEntry *table,
static MOZ_ALWAYS_INLINE bool
HasBitInInterfacesBitmap(JSObject *obj, uint32_t interfaceBit)
{
- NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(obj)), "Not a wrapper?");
+ NS_ASSERTION(IS_WN_REFLECTOR(obj), "Not a wrapper?");
XPCWrappedNativeJSClass *clasp =
(XPCWrappedNativeJSClass*)js::GetObjectClass(obj);
@@ -178,16 +178,10 @@ GetMemberInfo(JSObject *obj, jsid memberId, const char **ifaceName)
// because it isn't worth the risk of something going wrong just to generate
// an error message. Instead, only handle the simple case where we have the
// reflector in hand.
- if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
- XPCWrappedNativeProto *proto;
- if (IS_SLIM_WRAPPER_OBJECT(obj)) {
- proto = GetSlimWrapperProto(obj);
- } else {
- MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(obj));
- XPCWrappedNative *wrapper =
- static_cast(js::GetObjectPrivate(obj));
- proto = wrapper->GetProto();
- }
+ if (IS_WN_REFLECTOR(obj)) {
+ XPCWrappedNative *wrapper =
+ static_cast(js::GetObjectPrivate(obj));
+ XPCWrappedNativeProto *proto = wrapper->GetProto();
if (proto) {
XPCNativeSet *set = proto->GetSet();
if (set) {
@@ -565,14 +559,10 @@ getWrapper(JSContext *cx,
obj = js::GetObjectParent(obj);
}
- // If we've got a WN or slim wrapper, store things the way callers expect.
- // Otherwise, leave things null and return.
- if (IS_WRAPPER_CLASS(clasp)) {
- if (IS_WN_WRAPPER_OBJECT(obj))
- *wrapper = (XPCWrappedNative*) js::GetObjectPrivate(obj);
- else
- *cur = obj;
- }
+ // If we've got a WN, store things the way callers expect. Otherwise, leave
+ // things null and return.
+ if (IS_WN_CLASS(clasp))
+ *wrapper = XPCWrappedNative::Get(obj);
return NS_OK;
}
@@ -597,12 +587,8 @@ castNative(JSContext *cx,
} else if (cur) {
nsISupports *native;
if (!(native = mozilla::dom::UnwrapDOMObjectToISupports(cur))) {
- if (IS_SLIM_WRAPPER(cur)) {
- native = static_cast(xpc_GetJSPrivate(cur));
- } else {
- *pThisRef = nullptr;
- return NS_ERROR_ILLEGAL_VALUE;
- }
+ *pThisRef = nullptr;
+ return NS_ERROR_ILLEGAL_VALUE;
}
if (NS_SUCCEEDED(getNative(native, cur, iid, ppThis, pThisRef, vp))) {
@@ -628,11 +614,9 @@ castNativeFromWrapper(JSContext *cx,
XPCWrappedNativeTearOff *tearoff;
JSObject *cur;
- if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
+ if (IS_WN_REFLECTOR(obj)) {
cur = obj;
- wrapper = IS_WN_WRAPPER_OBJECT(cur) ?
- (XPCWrappedNative*)xpc_GetJSPrivate(obj) :
- nullptr;
+ wrapper = (XPCWrappedNative*)xpc_GetJSPrivate(obj);
tearoff = nullptr;
} else {
*rv = getWrapper(cx, obj, &wrapper, &cur, &tearoff);
@@ -647,11 +631,6 @@ castNativeFromWrapper(JSContext *cx,
if (!native || !HasBitInInterfacesBitmap(cur, interfaceBit)) {
native = nullptr;
}
- } else if (cur && IS_SLIM_WRAPPER(cur)) {
- native = static_cast(xpc_GetJSPrivate(cur));
- if (!native || !HasBitInInterfacesBitmap(cur, interfaceBit)) {
- native = nullptr;
- }
} else if (cur && protoDepth >= 0) {
const mozilla::dom::DOMClass* domClass =
mozilla::dom::GetDOMClass(cur);
diff --git a/js/xpconnect/src/XPCVariant.cpp b/js/xpconnect/src/XPCVariant.cpp
index 25de5166df89..814aa52c80e3 100644
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -45,7 +45,7 @@ XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal)
mJSVal = OBJECT_TO_JSVAL(obj);
JSObject *unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
- mReturnRawObject = !(unwrapped && IS_WN_WRAPPER(unwrapped));
+ mReturnRawObject = !(unwrapped && IS_WN_REFLECTOR(unwrapped));
} else
mReturnRawObject = false;
}
diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp
index 54f8afb19cbd..21588f80ce03 100644
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -699,8 +699,7 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
bool isSystem;
rv = secMan->IsSystemPrincipal(objPrin, &isSystem);
- if ((NS_FAILED(rv) || !isSystem) &&
- !IS_WRAPPER_CLASS(js::GetObjectClass(selfObj))) {
+ if ((NS_FAILED(rv) || !isSystem) && !IS_WN_REFLECTOR(selfObj)) {
// A content object.
nsRefPtr checked =
new SameOriginCheckedComponent(self);
diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp
index cf62f09bec81..4b60dd7c8677 100644
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -36,7 +36,7 @@ bool
xpc_OkToHandOutWrapper(nsWrapperCache *cache)
{
NS_ABORT_IF_FALSE(cache->GetWrapper(), "Must have wrapper");
- NS_ABORT_IF_FALSE(IS_WN_WRAPPER(cache->GetWrapper()),
+ NS_ABORT_IF_FALSE(IS_WN_REFLECTOR(cache->GetWrapper()),
"Must have XPCWrappedNative wrapper");
return
!static_cast(xpc_GetJSPrivate(cache->GetWrapper()))->
@@ -532,15 +532,8 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
if (cache) {
RootedObject cached(cx, cache->GetWrapper());
- if (cached) {
- if (IS_SLIM_WRAPPER_OBJECT(cached)) {
- if (NS_FAILED(XPCWrappedNative::Morph(cached,
- Interface, cache, getter_AddRefs(wrapper))))
- return NS_ERROR_FAILURE;
- } else {
- wrapper = static_cast(xpc_GetJSPrivate(cached));
- }
- }
+ if (cached)
+ wrapper = static_cast(xpc_GetJSPrivate(cached));
} else {
// scoped lock
XPCAutoLock lock(mapLock);
@@ -711,67 +704,6 @@ FinishCreate(XPCWrappedNativeScope* Scope,
return NS_OK;
}
-// static
-nsresult
-XPCWrappedNative::Morph(HandleObject existingJSObject,
- XPCNativeInterface* Interface,
- nsWrapperCache *cache,
- XPCWrappedNative** resultWrapper)
-{
- AutoJSContext cx;
- NS_ASSERTION(IS_SLIM_WRAPPER(existingJSObject),
- "Trying to morph a JSObject that's not a slim wrapper?");
-
- nsISupports *identity =
- static_cast(xpc_GetJSPrivate(existingJSObject));
- XPCWrappedNativeProto *proto = GetSlimWrapperProto(existingJSObject);
-
-#if DEBUG
- // FIXME Can't assert this until
- // https://bugzilla.mozilla.org/show_bug.cgi?id=343141 is fixed.
-#if 0
- if (proto->GetScriptableInfo()->GetFlags().WantPreCreate()) {
- JSObject* parent = JS_GetParent(existingJSObject);
- JSObject* plannedParent = parent;
- nsresult rv =
- proto->GetScriptableInfo()->GetCallback()->PreCreate(identity, ccx,
- parent,
- &parent);
- if (NS_FAILED(rv))
- return rv;
-
- NS_ASSERTION(parent == plannedParent,
- "PreCreate returned a different parent");
- }
-#endif
-#endif
-
- nsRefPtr wrapper = new XPCWrappedNative(dont_AddRef(identity), proto);
- if (!wrapper)
- return NS_ERROR_FAILURE;
-
- NS_ASSERTION(!xpc::WrapperFactory::IsXrayWrapper(js::GetObjectParent(existingJSObject)),
- "Xray wrapper being used to parent XPCWrappedNative?");
-
- // We use an AutoMarkingPtr here because it is possible for JS gc to happen
- // after we have Init'd the wrapper but *before* we add it to the hashtable.
- // This would cause the mSet to get collected and we'd later crash. I've
- // *seen* this happen.
- AutoMarkingWrappedNativePtr wrapperMarker(cx, wrapper);
-
- JSAutoCompartment ac(cx, existingJSObject);
- if (!wrapper->Init(existingJSObject))
- return NS_ERROR_FAILURE;
-
- nsresult rv;
- if (Interface && !wrapper->FindTearOff(Interface, false, &rv)) {
- NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
- return rv;
- }
-
- return FinishCreate(wrapper->GetScope(), Interface, cache, wrapper, resultWrapper);
-}
-
// static
nsresult
XPCWrappedNative::GetUsedOnly(nsISupports* Object,
@@ -787,17 +719,11 @@ XPCWrappedNative::GetUsedOnly(nsISupports* Object,
CallQueryInterface(Object, &cache);
if (cache) {
RootedObject flat(cx, cache->GetWrapper());
- if (flat && IS_SLIM_WRAPPER_OBJECT(flat) && !MorphSlimWrapper(cx, flat))
- return NS_ERROR_FAILURE;
-
- wrapper = flat ?
- static_cast(xpc_GetJSPrivate(flat)) :
- nullptr;
-
- if (!wrapper) {
+ if (!flat) {
*resultWrapper = nullptr;
return NS_OK;
}
+ wrapper = static_cast(xpc_GetJSPrivate(flat));
NS_ADDREF(wrapper);
} else {
nsCOMPtr identity = do_QueryInterface(Object);
@@ -1067,10 +993,6 @@ XPCWrappedNative::GatherScriptableCreateInfo(nsISupports* obj,
return sciProto;
}
-#ifdef DEBUG_slimwrappers
-static uint32_t sMorphedSlimWrappers;
-#endif
-
JSBool
XPCWrappedNative::Init(HandleObject parent,
const XPCNativeScriptableCreateInfo* sci)
@@ -1129,34 +1051,14 @@ XPCWrappedNative::Init(HandleObject parent,
return FinishInit();
}
-JSBool
-XPCWrappedNative::Init(JSObject *existingJSObject)
-{
- // Set up the private to point to the WN.
- JS_SetPrivate(existingJSObject, this);
-
- // Officially mark us as non-slim.
- MorphMultiSlot(existingJSObject);
-
- mScriptableInfo = GetProto()->GetScriptableInfo();
- mFlatJSObject = existingJSObject;
-
- SLIM_LOG(("----- %i morphed slim wrapper (mFlatJSObject: %p, %p)\n",
- ++sMorphedSlimWrappers, mFlatJSObject,
- static_cast(xpc_GetJSPrivate(mFlatJSObject))));
-
- return FinishInit();
-}
-
JSBool
XPCWrappedNative::FinishInit()
{
AutoJSContext cx;
- // For all WNs, we want to make sure that the multislot starts out as null.
- // This happens explicitly when morphing a slim wrapper, but we need to
- // make sure it happens in the other cases too.
- JS_SetReservedSlot(mFlatJSObject, WRAPPER_MULTISLOT, JSVAL_NULL);
+ // For all WNs, we want to make sure that the expando chain slot starts out
+ // as null.
+ JS_SetReservedSlot(mFlatJSObject, WN_XRAYEXPANDOCHAIN_SLOT, JSVAL_NULL);
// This reference will be released when mFlatJSObject is finalized.
// Since this reference will push the refcount to 2 it will also root
@@ -1419,7 +1321,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
CallQueryInterface(aCOMObj, &cache);
if (cache) {
flat = cache->GetWrapper();
- if (flat && !IS_SLIM_WRAPPER_OBJECT(flat)) {
+ if (flat) {
wrapper = static_cast(xpc_GetJSPrivate(flat));
NS_ASSERTION(wrapper->GetScope() == aOldScope,
"Incorrect scope passed");
@@ -1440,8 +1342,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
// ReparentWrapperIfFound is really only meant to be called from DOM code
// which must happen only on the main thread. Bail if we're on some other
// thread or have a non-main-thread-only wrapper.
- if (wrapper &&
- wrapper->GetProto() &&
+ if (wrapper->GetProto() &&
!wrapper->GetProto()->ClassIsMainThreadOnly()) {
return NS_ERROR_FAILURE;
}
@@ -1457,14 +1358,9 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
MOZ_ASSERT(js::GetObjectCompartment(aOldScope->GetGlobalJSObject()) !=
js::GetObjectCompartment(aNewScope->GetGlobalJSObject()));
NS_ASSERTION(aNewParent, "won't be able to find the new parent");
- NS_ASSERTION(wrapper, "can't transplant slim wrappers");
- if (!wrapper)
- oldProto = GetSlimWrapperProto(flat);
- else if (wrapper->HasProto())
+ if (wrapper->HasProto()) {
oldProto = wrapper->GetProto();
-
- if (oldProto) {
XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
XPCNativeScriptableCreateInfo ci(*info);
newProto =
@@ -1476,137 +1372,130 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
}
}
- if (wrapper) {
+ // First, the clone of the reflector, get a copy of its
+ // properties and clone its expando chain. The only part that is
+ // dangerous here if we have to return early is that we must avoid
+ // ending up with two reflectors pointing to the same WN. Other than
+ // that, the objects we create will just go away if we return early.
- // First, the clone of the reflector, get a copy of its
- // properties and clone its expando chain. The only part that is
- // dangerous here if we have to return early is that we must avoid
- // ending up with two reflectors pointing to the same WN. Other than
- // that, the objects we create will just go away if we return early.
+ RootedObject newobj(cx, JS_CloneObject(cx, flat,
+ newProto->GetJSProtoObject(),
+ aNewParent));
+ if (!newobj)
+ return NS_ERROR_FAILURE;
- RootedObject newobj(cx, JS_CloneObject(cx, flat,
- newProto->GetJSProtoObject(),
- aNewParent));
- if (!newobj)
+ // At this point, both |flat| and |newobj| point to the same wrapped
+ // native, which is bad, because one of them will end up finalizing
+ // a wrapped native it does not own. |cloneGuard| ensures that if we
+ // exit before calling clearing |flat|'s private the private of
+ // |newobj| will be set to NULL. |flat| will go away soon, because
+ // we swap it with another object during the transplant and let that
+ // object die.
+ RootedObject propertyHolder(cx);
+ {
+ AutoClonePrivateGuard cloneGuard(cx, flat, newobj);
+
+ propertyHolder = JS_NewObjectWithGivenProto(cx, NULL, NULL, aNewParent);
+ if (!propertyHolder)
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (!JS_CopyPropertiesFrom(cx, propertyHolder, flat))
return NS_ERROR_FAILURE;
- // At this point, both |flat| and |newobj| point to the same wrapped
- // native, which is bad, because one of them will end up finalizing
- // a wrapped native it does not own. |cloneGuard| ensures that if we
- // exit before calling clearing |flat|'s private the private of
- // |newobj| will be set to NULL. |flat| will go away soon, because
- // we swap it with another object during the transplant and let that
- // object die.
- RootedObject propertyHolder(cx);
- {
- AutoClonePrivateGuard cloneGuard(cx, flat, newobj);
+ // Expandos from other compartments are attached to the target JS object.
+ // Copy them over, and let the old ones die a natural death.
+ SetWNExpandoChain(newobj, nullptr);
+ if (!XrayUtils::CloneExpandoChain(cx, newobj, flat))
+ return NS_ERROR_FAILURE;
- propertyHolder = JS_NewObjectWithGivenProto(cx, NULL, NULL, aNewParent);
- if (!propertyHolder)
- return NS_ERROR_OUT_OF_MEMORY;
- if (!JS_CopyPropertiesFrom(cx, propertyHolder, flat))
- return NS_ERROR_FAILURE;
-
- // Expandos from other compartments are attached to the target JS object.
- // Copy them over, and let the old ones die a natural death.
- SetWNExpandoChain(newobj, nullptr);
- if (!XrayUtils::CloneExpandoChain(cx, newobj, flat))
- return NS_ERROR_FAILURE;
-
- // We've set up |newobj|, so we make it own the WN by nulling out
- // the private of |flat|.
- //
- // NB: It's important to do this _after_ copying the properties to
- // propertyHolder. Otherwise, an object with |foo.x === foo| will
- // crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
- JS_SetPrivate(flat, nullptr);
- }
-
- // Before proceeding, eagerly create any same-compartment security wrappers
- // that the object might have. This forces us to take the 'WithWrapper' path
- // while transplanting that handles this stuff correctly.
- {
- JSAutoCompartment innerAC(cx, aOldScope->GetGlobalJSObject());
- if (!wrapper->GetSameCompartmentSecurityWrapper(cx))
- return NS_ERROR_FAILURE;
- }
-
- // Update scope maps. This section modifies global state, so from
- // here on out we crash if anything fails.
- { // scoped lock
- Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
- Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
- XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock());
-
- oldMap->Remove(wrapper);
-
- if (wrapper->HasProto())
- wrapper->SetProto(newProto);
-
- // If the wrapper has no scriptable or it has a non-shared
- // scriptable, then we don't need to mess with it.
- // Otherwise...
-
- if (wrapper->mScriptableInfo &&
- wrapper->mScriptableInfo == oldProto->GetScriptableInfo()) {
- // The new proto had better have the same JSClass stuff as
- // the old one! We maintain a runtime wide unique map of
- // this stuff. So, if these don't match then the caller is
- // doing something bad here.
-
- NS_ASSERTION(oldProto->GetScriptableInfo()->GetScriptableShared() ==
- newProto->GetScriptableInfo()->GetScriptableShared(),
- "Changing proto is also changing JSObject Classname or "
- "helper's nsIXPScriptable flags. This is not allowed!");
-
- wrapper->UpdateScriptableInfo(newProto->GetScriptableInfo());
- }
-
- // Crash if the wrapper is already in the new scope.
- if (newMap->Find(wrapper->GetIdentityObject()))
- MOZ_CRASH();
-
- if (!newMap->Add(wrapper))
- MOZ_CRASH();
- }
-
- JSObject *ww = wrapper->GetWrapper();
- if (ww) {
- JSObject *newwrapper;
- MOZ_ASSERT(wrapper->NeedsSOW(), "weird wrapper wrapper");
- newwrapper = xpc::WrapperFactory::WrapSOWObject(cx, newobj);
- if (!newwrapper)
- MOZ_CRASH();
-
- // Ok, now we do the special object-plus-wrapper transplant.
- ww = xpc::TransplantObjectWithWrapper(cx, flat, ww, newobj,
- newwrapper);
- if (!ww)
- MOZ_CRASH();
-
- flat = newobj;
- wrapper->SetWrapper(ww);
- } else {
- flat = xpc::TransplantObject(cx, flat, newobj);
- if (!flat)
- MOZ_CRASH();
- }
-
- wrapper->mFlatJSObject = flat;
- if (cache) {
- bool preserving = cache->PreservingWrapper();
- cache->SetPreservingWrapper(false);
- cache->SetWrapper(flat);
- cache->SetPreservingWrapper(preserving);
- }
- if (!JS_CopyPropertiesFrom(cx, flat, propertyHolder))
- MOZ_CRASH();
- } else {
- SetSlimWrapperProto(flat, newProto.get());
- if (!JS_SetPrototype(cx, flat, newProto->GetJSProtoObject()))
- MOZ_CRASH(); // this is bad, very bad
+ // We've set up |newobj|, so we make it own the WN by nulling out
+ // the private of |flat|.
+ //
+ // NB: It's important to do this _after_ copying the properties to
+ // propertyHolder. Otherwise, an object with |foo.x === foo| will
+ // crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
+ JS_SetPrivate(flat, nullptr);
}
+ // Before proceeding, eagerly create any same-compartment security wrappers
+ // that the object might have. This forces us to take the 'WithWrapper' path
+ // while transplanting that handles this stuff correctly.
+ {
+ JSAutoCompartment innerAC(cx, aOldScope->GetGlobalJSObject());
+ if (!wrapper->GetSameCompartmentSecurityWrapper(cx))
+ return NS_ERROR_FAILURE;
+ }
+
+ // Update scope maps. This section modifies global state, so from
+ // here on out we crash if anything fails.
+ { // scoped lock
+ Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
+ Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap();
+ XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock());
+
+ oldMap->Remove(wrapper);
+
+ if (wrapper->HasProto())
+ wrapper->SetProto(newProto);
+
+ // If the wrapper has no scriptable or it has a non-shared
+ // scriptable, then we don't need to mess with it.
+ // Otherwise...
+
+ if (wrapper->mScriptableInfo &&
+ wrapper->mScriptableInfo == oldProto->GetScriptableInfo()) {
+ // The new proto had better have the same JSClass stuff as
+ // the old one! We maintain a runtime wide unique map of
+ // this stuff. So, if these don't match then the caller is
+ // doing something bad here.
+
+ NS_ASSERTION(oldProto->GetScriptableInfo()->GetScriptableShared() ==
+ newProto->GetScriptableInfo()->GetScriptableShared(),
+ "Changing proto is also changing JSObject Classname or "
+ "helper's nsIXPScriptable flags. This is not allowed!");
+
+ wrapper->UpdateScriptableInfo(newProto->GetScriptableInfo());
+ }
+
+ // Crash if the wrapper is already in the new scope.
+ if (newMap->Find(wrapper->GetIdentityObject()))
+ MOZ_CRASH();
+
+ if (!newMap->Add(wrapper))
+ MOZ_CRASH();
+ }
+
+ JSObject *ww = wrapper->GetWrapper();
+ if (ww) {
+ JSObject *newwrapper;
+ MOZ_ASSERT(wrapper->NeedsSOW(), "weird wrapper wrapper");
+ newwrapper = xpc::WrapperFactory::WrapSOWObject(cx, newobj);
+ if (!newwrapper)
+ MOZ_CRASH();
+
+ // Ok, now we do the special object-plus-wrapper transplant.
+ ww = xpc::TransplantObjectWithWrapper(cx, flat, ww, newobj,
+ newwrapper);
+ if (!ww)
+ MOZ_CRASH();
+
+ flat = newobj;
+ wrapper->SetWrapper(ww);
+ } else {
+ flat = xpc::TransplantObject(cx, flat, newobj);
+ if (!flat)
+ MOZ_CRASH();
+ }
+
+ wrapper->mFlatJSObject = flat;
+ if (cache) {
+ bool preserving = cache->PreservingWrapper();
+ cache->SetPreservingWrapper(false);
+ cache->SetWrapper(flat);
+ cache->SetPreservingWrapper(preserving);
+ }
+ if (!JS_CopyPropertiesFrom(cx, flat, propertyHolder))
+ MOZ_CRASH();
+
// Call the scriptable hook to indicate that we transplanted.
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
if (si->GetFlags().WantPostCreate())
@@ -1619,10 +1508,8 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
if (!JS_SetParent(cx, flat, aNewParent))
MOZ_CRASH();
- JSObject *nw;
- if (wrapper &&
- (nw = wrapper->GetWrapper()) &&
- !JS_SetParent(cx, nw, JS_GetGlobalForObject(cx, aNewParent))) {
+ JSObject *nw = wrapper->GetWrapper();
+ if (nw && !JS_SetParent(cx, nw, JS_GetGlobalForObject(cx, aNewParent))) {
MOZ_CRASH();
}
}
@@ -1670,7 +1557,7 @@ RescueOrphans(HandleObject obj)
// PreCreate may touch dead compartments.
js::AutoMaybeTouchDeadZones agc(parentObj);
- bool isWN = IS_WRAPPER_CLASS(js::GetObjectClass(obj));
+ bool isWN = IS_WN_REFLECTOR(obj);
// There's one little nasty twist here. For reasons described in bug 752764,
// we nuke SOW-ed objects after transplanting them. This means that nodes
@@ -1693,12 +1580,6 @@ RescueOrphans(HandleObject obj)
}
}
- // Morph any slim wrappers, lest they confuse us.
- if (IS_SLIM_WRAPPER(parentObj)) {
- bool ok = MorphSlimWrapper(cx, parentObj);
- NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
- }
-
// Recursively fix up orphans on the parent chain.
rv = RescueOrphans(parentObj);
NS_ENSURE_SUCCESS(rv, rv);
@@ -3553,120 +3434,3 @@ XPCJSObjectHolder::newHolder(JSObject* obj)
}
return new XPCJSObjectHolder(obj);
}
-
-JSBool
-MorphSlimWrapper(JSContext *cx, HandleObject obj)
-{
- SLIM_LOG(("***** morphing from MorphSlimToWrapper (%p, %p)\n",
- obj, static_cast(xpc_GetJSPrivate(obj))));
-
- nsISupports* object = static_cast(xpc_GetJSPrivate(obj));
- nsWrapperCache *cache = nullptr;
- CallQueryInterface(object, &cache);
- nsRefPtr wn;
- nsresult rv = XPCWrappedNative::Morph(obj, nullptr, cache,
- getter_AddRefs(wn));
- return NS_SUCCEEDED(rv);
-}
-
-#ifdef DEBUG_slimwrappers
-static uint32_t sSlimWrappers;
-#endif
-
-JSBool
-ConstructSlimWrapper(xpcObjectHelper &aHelper,
- XPCWrappedNativeScope* xpcScope, MutableHandleValue rval)
-{
- AutoJSContext cx;
- nsISupports *identityObj = aHelper.GetCanonical();
- nsXPCClassInfo *classInfoHelper = aHelper.GetXPCClassInfo();
-
- if (!classInfoHelper) {
- SLIM_LOG_NOT_CREATED(cx, identityObj, "No classinfo helper");
- return false;
- }
-
- XPCNativeScriptableFlags flags(classInfoHelper->GetScriptableFlags());
-
- NS_ASSERTION(flags.DontAskInstanceForScriptable(),
- "Not supported for cached wrappers!");
-
- RootedObject parent(cx, xpcScope->GetGlobalJSObject());
- if (!flags.WantPreCreate()) {
- SLIM_LOG_NOT_CREATED(cx, identityObj,
- "scriptable helper has no PreCreate hook");
-
- return false;
- }
-
- // PreCreate may touch dead compartments.
- js::AutoMaybeTouchDeadZones agc(parent);
-
- RootedObject plannedParent(cx, parent);
- nsresult rv = classInfoHelper->PreCreate(identityObj, cx, parent, parent.address());
- if (rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS) {
- SLIM_LOG_NOT_CREATED(cx, identityObj, "PreCreate hook refused");
-
- return false;
- }
-
- if (!js::IsObjectInContextCompartment(parent, cx)) {
- SLIM_LOG_NOT_CREATED(cx, identityObj, "wrong compartment");
-
- return false;
- }
-
- JSAutoCompartment ac(cx, parent);
-
- if (parent != plannedParent) {
- XPCWrappedNativeScope *newXpcScope = GetObjectScope(parent);
- if (newXpcScope != xpcScope) {
- SLIM_LOG_NOT_CREATED(cx, identityObj, "crossing origins");
-
- return false;
- }
- }
-
- // The PreCreate hook could have forced the creation of a wrapper, need
- // to check for that here and return early.
- nsWrapperCache *cache = aHelper.GetWrapperCache();
- JSObject* wrapper = cache->GetWrapper();
- if (wrapper) {
- rval.setObject(*wrapper);
-
- return true;
- }
-
- uint32_t interfacesBitmap = classInfoHelper->GetInterfacesBitmap();
- XPCNativeScriptableCreateInfo
- sciProto(aHelper.forgetXPCClassInfo(), flags, interfacesBitmap);
-
- AutoMarkingWrappedNativeProtoPtr xpcproto(cx);
- xpcproto = XPCWrappedNativeProto::GetNewOrUsed(xpcScope, classInfoHelper, &sciProto);
- if (!xpcproto)
- return false;
-
- XPCNativeScriptableInfo* si = xpcproto->GetScriptableInfo();
- JSClass* jsclazz = si->GetSlimJSClass();
- if (!jsclazz)
- return false;
-
- wrapper = JS_NewObject(cx, jsclazz, xpcproto->GetJSProtoObject(), parent);
- if (!wrapper)
- return false;
-
- JS_SetPrivate(wrapper, identityObj);
- SetSlimWrapperProto(wrapper, xpcproto.get());
-
- // Transfer ownership to the wrapper's private.
- aHelper.forgetCanonical();
-
- cache->SetWrapper(wrapper);
-
- SLIM_LOG(("+++++ %i created slim wrapper (%p, %p, %p)\n", ++sSlimWrappers,
- wrapper, p, xpcScope));
-
- rval.setObject(*wrapper);
-
- return true;
-}
diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
index 5ad652d65421..f038a9677ea9 100644
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -30,13 +30,6 @@ static JSBool Throw(nsresult errNum, JSContext* cx)
// Handy macro used in many callback stub below.
-#define MORPH_SLIM_WRAPPER(cx, obj) \
- PR_BEGIN_MACRO \
- SLIM_LOG_WILL_MORPH(cx, obj); \
- if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj)) \
- return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
- PR_END_MACRO
-
#define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper) \
PR_BEGIN_MACRO \
if (!wrapper) \
@@ -81,32 +74,6 @@ XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
if (!obj)
return false;
- if (IS_SLIM_WRAPPER(obj)) {
- XPCNativeScriptableInfo *si =
- GetSlimWrapperProto(obj)->GetScriptableInfo();
-#ifdef DEBUG
-# define FMT_ADDR " @ 0x%p"
-# define FMT_STR(str) str
-# define PARAM_ADDR(w) , w
-#else
-# define FMT_ADDR ""
-# define FMT_STR(str)
-# define PARAM_ADDR(w)
-#endif
- char *sz = JS_smprintf("[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]", si->GetJSClass()->name PARAM_ADDR(obj.get()) PARAM_ADDR(xpc_GetJSPrivate(obj)));
- if (!sz)
- return false;
-
- JSString* str = JS_NewStringCopyZ(cx, sz);
- JS_smprintf_free(sz);
- if (!str)
- return false;
-
- *vp = STRING_TO_JSVAL(str);
-
- return true;
- }
-
XPCCallContext ccx(JS_CALLER, cx, obj);
if (!ccx.IsValid())
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
@@ -173,7 +140,6 @@ XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
if (!obj)
return false;
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -513,7 +479,6 @@ XPC_WN_Shared_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableH
return true;
}
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -566,7 +531,6 @@ XPC_WN_Shared_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableH
static JSBool
XPC_WN_Shared_Enumerate(JSContext *cx, JSHandleObject obj)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -603,10 +567,6 @@ XPC_WN_Shared_Enumerate(JSContext *cx, JSHandleObject obj)
/***************************************************************************/
-#ifdef DEBUG_slimwrappers
-static uint32_t sFinalizedSlimWrappers;
-#endif
-
enum WNHelperType {
WN_NOHELPER,
WN_HELPER
@@ -623,20 +583,6 @@ WrappedNativeFinalize(js::FreeOp *fop, JSObject *obj, WNHelperType helperType)
if (!p)
return;
- if (IS_SLIM_WRAPPER_OBJECT(obj)) {
- SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
- ++sFinalizedSlimWrappers, obj, p));
-
- nsWrapperCache* cache;
- CallQueryInterface(p, &cache);
- cache->ClearWrapper();
-
- XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
- MOZ_ASSERT(rt, "XPCJSRuntime should exist during a GC.");
- rt->DeferredRelease(p);
- return;
- }
-
XPCWrappedNative* wrapper = static_cast(p);
if (helperType == WN_HELPER)
wrapper->GetScriptableCallback()->Finalize(wrapper, js::CastToJSFreeOp(fop), obj);
@@ -649,12 +595,6 @@ XPC_WN_NoHelper_Finalize(js::FreeOp *fop, JSObject *obj)
WrappedNativeFinalize(fop, obj, WN_NOHELPER);
}
-static void
-TraceInsideSlimWrapper(JSTracer *trc, JSObject *obj)
-{
- GetSlimWrapperProto(obj)->TraceSelf(trc);
-}
-
/*
* General comment about XPConnect tracing: Given a C++ object |wrapper| and its
* corresponding JS object |obj|, calling |wrapper->TraceSelf| will ask the JS
@@ -670,18 +610,11 @@ MarkWrappedNative(JSTracer *trc, JSObject *obj)
if (clazz->flags & JSCLASS_DOM_GLOBAL) {
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
}
- MOZ_ASSERT(IS_WRAPPER_CLASS(clazz));
+ MOZ_ASSERT(IS_WN_CLASS(clazz));
- if (IS_WN_WRAPPER_OBJECT(obj)) {
- XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
- if (wrapper) {
- if (wrapper->IsValid())
- wrapper->TraceInside(trc);
- }
- } else {
- MOZ_ASSERT(IS_SLIM_WRAPPER_OBJECT(obj));
- TraceInsideSlimWrapper(trc, obj);
- }
+ XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
+ if (wrapper && wrapper->IsValid())
+ wrapper->TraceInside(trc);
}
static void
@@ -693,7 +626,6 @@ XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj)
static JSBool
XPC_WN_NoHelper_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), id);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -826,7 +758,6 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
static JSBool
XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -846,7 +777,6 @@ XPC_WN_MaybeResolvingStrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHan
static JSBool
XPC_WN_MaybeResolvingDeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -859,36 +789,19 @@ XPC_WN_MaybeResolvingDeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHan
}
// macro fun!
-#define PRE_HELPER_STUB_NO_SLIM \
- XPCWrappedNative* wrapper = \
- XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj); \
- THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
- bool retval = true; \
- nsresult rv = wrapper->GetScriptableCallback()->
-
#define PRE_HELPER_STUB \
- XPCWrappedNative* wrapper; \
- nsIXPCScriptable* si; \
- JSObject *unwrapped = js::CheckedUnwrap(obj, false); \
+ JSObject *unwrapped = js::CheckedUnwrap(obj, false); \
if (!unwrapped) { \
JS_ReportError(cx, "Permission denied to operate on object."); \
return false; \
} \
- if (!IS_WRAPPER_CLASS(js::GetObjectClass(unwrapped))) { \
+ if (!IS_WN_REFLECTOR(unwrapped)) { \
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
} \
- if (IS_SLIM_WRAPPER_OBJECT(unwrapped)) { \
- wrapper = nullptr; \
- si = GetSlimWrapperProto(unwrapped)->GetScriptableInfo() \
- ->GetCallback(); \
- } else { \
- MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(unwrapped)); \
- wrapper = XPCWrappedNative::Get(unwrapped); \
- THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
- si = wrapper->GetScriptableCallback(); \
- } \
+ XPCWrappedNative *wrapper = XPCWrappedNative::Get(unwrapped); \
+ THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
bool retval = true; \
- nsresult rv = si->
+ nsresult rv = wrapper->GetScriptableCallback()->
#define POST_HELPER_STUB \
if (NS_FAILED(rv)) \
@@ -934,8 +847,7 @@ XPC_WN_Helper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBo
static JSBool
XPC_WN_Helper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
{
- SLIM_LOG_WILL_MORPH(cx, obj);
- PRE_HELPER_STUB_NO_SLIM
+ PRE_HELPER_STUB
Convert(wrapper, cx, obj, type, vp.address(), &retval);
POST_HELPER_STUB
}
@@ -963,8 +875,7 @@ XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
- SLIM_LOG_WILL_MORPH(cx, obj);
- PRE_HELPER_STUB_NO_SLIM
+ PRE_HELPER_STUB
Call(wrapper, cx, obj, args, &retval);
POST_HELPER_STUB
}
@@ -984,8 +895,7 @@ XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
- SLIM_LOG_WILL_MORPH(cx, obj);
- PRE_HELPER_STUB_NO_SLIM
+ PRE_HELPER_STUB
Construct(wrapper, cx, obj, args, &retval);
POST_HELPER_STUB
}
@@ -993,9 +903,8 @@ XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
static JSBool
XPC_WN_Helper_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue valp, JSBool *bp)
{
- SLIM_LOG_WILL_MORPH(cx, obj);
bool retval2;
- PRE_HELPER_STUB_NO_SLIM
+ PRE_HELPER_STUB
HasInstance(wrapper, cx, obj, valp, &retval2, &retval);
*bp = retval2;
POST_HELPER_STUB
@@ -1014,27 +923,6 @@ XPC_WN_Helper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsig
nsresult rv = NS_OK;
bool retval = true;
RootedObject obj2FromScriptable(cx);
- if (IS_SLIM_WRAPPER(obj)) {
- XPCNativeScriptableInfo *si =
- GetSlimWrapperProto(obj)->GetScriptableInfo();
- if (!si->GetFlags().WantNewResolve())
- return retval;
-
- NS_ASSERTION(si->GetFlags().AllowPropModsToPrototype() &&
- !si->GetFlags().AllowPropModsDuringResolve(),
- "We don't support these flags for slim wrappers!");
-
- rv = si->GetCallback()->NewResolve(nullptr, cx, obj, id, flags,
- obj2FromScriptable.address(), &retval);
- if (NS_FAILED(rv))
- return Throw(rv, cx);
-
- if (obj2FromScriptable)
- objp.set(obj2FromScriptable);
-
- return retval;
- }
-
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -1150,7 +1038,7 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
JSMutableHandleValue statep, MutableHandleId idp)
{
js::Class *clazz = js::GetObjectClass(obj);
- if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
+ if (!IS_WN_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
// obj must be a prototype object or a wrapper w/o a
// helper. Short circuit this call to the default
// implementation.
@@ -1158,8 +1046,6 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
return JS_EnumerateState(cx, obj, enum_op, statep, idp);
}
- MORPH_SLIM_WRAPPER(cx, obj);
-
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -1397,9 +1283,6 @@ XPCNativeScriptableShared::PopulateJSClass()
if (mFlags.WantOuterObject())
mJSClass.base.ext.outerObject = XPC_WN_OuterObject;
- if (!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT))
- mCanBeSlim = true;
-
mJSClass.base.ext.isWrappedNative = true;
}
@@ -1453,18 +1336,6 @@ XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
if (!obj)
return false;
-#ifdef DEBUG_slimwrappers
- {
- JSFunction* fun = funobj->getFunctionPrivate();
- JSString *funid = JS_GetFunctionDisplayId(fun);
- JSAutoByteString bytes;
- const char *funname = !funid ? "" : bytes.encodeLatin1(cx, funid) ? bytes.ptr() : "";
- SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
- }
-#endif
- if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
- return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
-
obj = FixUpThisIfBroken(obj, funobj);
XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
JS_ARGV(cx, vp), vp);
@@ -1490,21 +1361,6 @@ XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
if (!obj)
return false;
-#ifdef DEBUG_slimwrappers
- {
- const char* funname = nullptr;
- JSAutoByteString bytes;
- if (JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
- JSString *funid = JS_GetFunctionDisplayId(funobj->getFunctionPrivate());
- funname = !funid ? "" : bytes.encodeLatin1(cx, funid) ? bytes.ptr() : "";
- }
- SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
- }
-#endif
- if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
- return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
-
-
obj = FixUpThisIfBroken(obj, funobj);
XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
JS_ARGV(cx, vp), vp);
@@ -1787,7 +1643,6 @@ js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
static JSBool
XPC_WN_TearOff_Enumerate(JSContext *cx, JSHandleObject obj)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -1810,7 +1665,6 @@ XPC_WN_TearOff_Enumerate(JSContext *cx, JSHandleObject obj)
static JSBool
XPC_WN_TearOff_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
{
- MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp
index ecbf68b9185c..393f37c6bd45 100644
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1080,21 +1080,6 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
return NS_OK;
}
-nsresult
-xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph)
-{
- nsWrapperCache *cache;
- CallQueryInterface(tomorph, &cache);
- if (!cache)
- return NS_OK;
-
- RootedObject obj(cx, cache->GetWrapper());
- if (!obj || !IS_SLIM_WRAPPER(obj))
- return NS_OK;
- NS_ENSURE_STATE(MorphSlimWrapper(cx, obj));
- return NS_OK;
-}
-
static nsresult
NativeInterface2JSObject(HandleObject aScope,
nsISupports *aCOMObj,
@@ -1236,12 +1221,9 @@ nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
NS_ASSERTION(_retval, "bad param");
RootedObject aJSObj(aJSContext, aJSObjArg);
- SLIM_LOG_WILL_MORPH(aJSContext, aJSObj);
- nsIXPConnectWrappedNative* wrapper =
- XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(aJSContext, aJSObj);
- if (wrapper) {
- NS_ADDREF(wrapper);
- *_retval = wrapper;
+ aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtOuter = */ false);
+ if (aJSObj && IS_WN_REFLECTOR(aJSObj)) {
+ NS_IF_ADDREF(*_retval = XPCWrappedNative::Get(aJSObj));
return NS_OK;
}
@@ -1263,10 +1245,8 @@ nsXPConnect::GetNativeOfWrapper(JSContext * aJSContext,
JS_ReportError(aJSContext, "Permission denied to get native of security wrapper");
return nullptr;
}
- if (IS_WRAPPER_CLASS(js::GetObjectClass(aJSObj))) {
- if (IS_SLIM_WRAPPER_OBJECT(aJSObj))
- return (nsISupports*)xpc_GetJSPrivate(aJSObj);
- else if (XPCWrappedNative *wn = XPCWrappedNative::Get(aJSObj))
+ if (IS_WN_REFLECTOR(aJSObj)) {
+ if (XPCWrappedNative *wn = XPCWrappedNative::Get(aJSObj))
return wn->Native();
return nullptr;
}
@@ -1938,41 +1918,21 @@ IsJSContextOnStack(JSContext *aCx)
nsIPrincipal*
nsXPConnect::GetPrincipal(JSObject* obj, bool allowShortCircuit) const
{
- NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(obj)),
- "What kind of wrapper is this?");
+ NS_ASSERTION(IS_WN_REFLECTOR(obj), "What kind of wrapper is this?");
- if (IS_WN_WRAPPER_OBJECT(obj)) {
- XPCWrappedNative *xpcWrapper =
- (XPCWrappedNative *)xpc_GetJSPrivate(obj);
- if (xpcWrapper) {
- if (allowShortCircuit) {
- nsIPrincipal *result = xpcWrapper->GetObjectPrincipal();
- if (result) {
- return result;
- }
- }
-
- // If not, check if it points to an nsIScriptObjectPrincipal
- nsCOMPtr objPrin =
- do_QueryInterface(xpcWrapper->Native());
- if (objPrin) {
- nsIPrincipal *result = objPrin->GetPrincipal();
- if (result) {
- return result;
- }
- }
- }
- } else {
+ XPCWrappedNative *xpcWrapper =
+ (XPCWrappedNative *)xpc_GetJSPrivate(obj);
+ if (xpcWrapper) {
if (allowShortCircuit) {
- nsIPrincipal *result =
- GetSlimWrapperProto(obj)->GetScope()->GetPrincipal();
+ nsIPrincipal *result = xpcWrapper->GetObjectPrincipal();
if (result) {
return result;
}
}
+ // If not, check if it points to an nsIScriptObjectPrincipal
nsCOMPtr objPrin =
- do_QueryInterface((nsISupports*)xpc_GetJSPrivate(obj));
+ do_QueryInterface(xpcWrapper->Native());
if (objPrin) {
nsIPrincipal *result = objPrin->GetPrincipal();
if (result) {
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index 0354be0b7840..8651cce43af5 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -15,13 +15,6 @@
* additional C++ object involved of type XPCWrappedNative. The XPCWrappedNative
* holds pointers to the C++ object and the flat JS object.
*
- * As an optimization, some C++ objects don't have XPCWrappedNatives, although
- * they still have a corresponding flattened JS object. These are called "slim
- * wrappers": all the wrapping information is stored in extra fields of the C++
- * object and the JS object. Slim wrappers are only used for DOM objects. As a
- * deoptimization, slim wrappers can be "morphed" into XPCWrappedNatives if the
- * extra fields of the XPCWrappedNative become necessary.
- *
* All XPCWrappedNative objects belong to an XPCWrappedNativeScope. These scopes
* are essentially in 1:1 correspondence with JS global objects. The
* XPCWrappedNativeScope has a pointer to the JS global object. The parent of a
@@ -49,10 +42,6 @@
* pointers are smooshed together in a tagged union.) Either way it can reach
* its scope.
*
- * In the case of slim wrappers (where there is no XPCWrappedNative), the
- * flattened JS object has a pointer to the XPCWrappedNativeProto stored in a
- * reserved slot.
- *
* An XPCWrappedNativeProto keeps track of the set of interfaces implemented by
* the C++ object in an XPCNativeSet. (The list of interfaces is obtained by
* calling a method on the nsIClassInfo.) An XPCNativeSet is a collection of
@@ -288,42 +277,24 @@ extern const char XPC_XPCONNECT_CONTRACTID[];
#define WRAPPER_SLOTS (JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | \
JSCLASS_HAS_RESERVED_SLOTS(1))
-// WRAPPER_MULTISLOT is defined in xpcpublic.h
-
#define INVALID_OBJECT ((JSObject *)1)
-inline void SetSlimWrapperProto(JSObject *obj, XPCWrappedNativeProto *proto)
-{
- JS_SetReservedSlot(obj, WRAPPER_MULTISLOT, PRIVATE_TO_JSVAL(proto));
-}
-
-inline XPCWrappedNativeProto* GetSlimWrapperProto(JSObject *obj)
-{
- MOZ_ASSERT(IS_SLIM_WRAPPER(obj));
- const JS::Value &v = js::GetReservedSlot(obj, WRAPPER_MULTISLOT);
- return static_cast(v.toPrivate());
-}
-
-// A slim wrapper is identified by having a native pointer in its reserved slot.
-// This function, therefore, does the official transition from a slim wrapper to
-// a non-slim wrapper.
-inline void MorphMultiSlot(JSObject *obj)
-{
- MOZ_ASSERT(IS_SLIM_WRAPPER(obj));
- JS_SetReservedSlot(obj, WRAPPER_MULTISLOT, JSVAL_NULL);
- MOZ_ASSERT(!IS_SLIM_WRAPPER(obj));
-}
+// NB: This slot isn't actually reserved for us on globals, because SpiderMonkey
+// uses the first N slots on globals internally. The fact that we use it for
+// wrapped global objects is totally broken. But due to a happy coincidence, the
+// JS engine never uses that slot. This still needs fixing though. See bug 760095.
+#define WN_XRAYEXPANDOCHAIN_SLOT 0
inline void SetWNExpandoChain(JSObject *obj, JSObject *chain)
{
- MOZ_ASSERT(IS_WN_WRAPPER(obj));
- JS_SetReservedSlot(obj, WRAPPER_MULTISLOT, JS::ObjectOrNullValue(chain));
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
+ JS_SetReservedSlot(obj, WN_XRAYEXPANDOCHAIN_SLOT, JS::ObjectOrNullValue(chain));
}
inline JSObject* GetWNExpandoChain(JSObject *obj)
{
- MOZ_ASSERT(IS_WN_WRAPPER(obj));
- return JS_GetReservedSlot(obj, WRAPPER_MULTISLOT).toObjectOrNull();
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
+ return JS_GetReservedSlot(obj, WN_XRAYEXPANDOCHAIN_SLOT).toObjectOrNull();
}
/***************************************************************************/
@@ -1966,13 +1937,10 @@ public:
{return mJSClass.interfacesBitmap;}
JSClass* GetJSClass()
{return Jsvalify(&mJSClass.base);}
- JSClass* GetSlimJSClass()
- {if (mCanBeSlim) return GetJSClass(); return nullptr;}
XPCNativeScriptableShared(uint32_t aFlags, char* aName,
uint32_t interfacesBitmap)
- : mFlags(aFlags),
- mCanBeSlim(false)
+ : mFlags(aFlags)
{memset(&mJSClass, 0, sizeof(mJSClass));
mJSClass.base.name = aName; // take ownership
mJSClass.interfacesBitmap = interfacesBitmap;
@@ -1995,7 +1963,6 @@ public:
private:
XPCNativeScriptableFlags mFlags;
XPCWrappedNativeJSClass mJSClass;
- JSBool mCanBeSlim;
};
/***************************************************************************/
@@ -2020,9 +1987,6 @@ public:
JSClass*
GetJSClass() {return mShared->GetJSClass();}
- JSClass*
- GetSlimJSClass() {return mShared->GetSlimJSClass();}
-
XPCNativeScriptableShared*
GetScriptableShared() {return mShared;}
@@ -2241,12 +2205,6 @@ private:
XPCNativeScriptableInfo* mScriptableInfo;
};
-class xpcObjectHelper;
-extern JSBool ConstructSlimWrapper(xpcObjectHelper &aHelper,
- XPCWrappedNativeScope* xpcScope,
- JS::MutableHandleValue rval);
-extern JSBool MorphSlimWrapper(JSContext *cx, JS::HandleObject obj);
-
/***********************************************/
// XPCWrappedNativeTearOff represents the info needed to make calls to one
// interface on the underlying native object of a XPCWrappedNative.
@@ -2433,7 +2391,7 @@ public:
SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
static XPCWrappedNative* Get(JSObject *obj) {
- MOZ_ASSERT(IS_WN_WRAPPER(obj));
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
return (XPCWrappedNative*)js::GetObjectPrivate(obj);
}
@@ -2493,22 +2451,6 @@ public:
XPCNativeInterface* Interface,
XPCWrappedNative** wrapper);
- static XPCWrappedNative*
- GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj_)
- {
- JS::RootedObject obj(cx, obj_);
- obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
- if (!obj)
- return nullptr;
- if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
- return nullptr;
-
- if (IS_SLIM_WRAPPER_OBJECT(obj) && !MorphSlimWrapper(cx, obj))
- return nullptr;
- MOZ_ASSERT(IS_WN_WRAPPER(obj));
- return XPCWrappedNative::Get(obj);
- }
-
static nsresult
ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
XPCWrappedNativeScope* aNewScope,
@@ -2672,7 +2614,6 @@ private:
private:
JSBool Init(JS::HandleObject parent, const XPCNativeScriptableCreateInfo* sci);
- JSBool Init(JSObject *existingJSObject);
JSBool FinishInit();
JSBool ExtendSet(XPCNativeInterface* aInterface);
diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h
index 1ce3db287c84..6d3e5e6cc7ea 100644
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -82,48 +82,16 @@ xpc_LocalizeRuntime(JSRuntime *rt);
NS_EXPORT_(void)
xpc_DelocalizeRuntime(JSRuntime *rt);
-nsresult
-xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph);
+// If IS_WN_CLASS for the JSClass of an object is true, the object is a
+// wrappednative wrapper, holding the XPCWrappedNative in its private slot.
-static inline bool IS_WRAPPER_CLASS(js::Class* clazz)
+static inline bool IS_WN_CLASS(js::Class* clazz)
{
return clazz->ext.isWrappedNative;
}
-
-// If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
-// a slim wrapper, holding a native in its private slot, or a wrappednative
-// wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
-// also holds a pointer to its XPCWrappedNativeProto in a reserved slot, we can
-// check that slot for a private value (i.e. a double) to distinguish between
-// the two. This allows us to store a JSObject in that slot for non-slim wrappers
-// while still being able to distinguish the two cases.
-
-// NB: This slot isn't actually reserved for us on globals, because SpiderMonkey
-// uses the first N slots on globals internally. The fact that we use it for
-// wrapped global objects is totally broken. But due to a happy coincidence, the
-// JS engine never uses that slot. This still needs fixing though. See bug 760095.
-#define WRAPPER_MULTISLOT 0
-
-static inline bool IS_WN_WRAPPER_OBJECT(JSObject *obj)
+static inline bool IS_WN_REFLECTOR(JSObject *obj)
{
- MOZ_ASSERT(IS_WRAPPER_CLASS(js::GetObjectClass(obj)));
- return !js::GetReservedSlot(obj, WRAPPER_MULTISLOT).isDouble();
-}
-static inline bool IS_SLIM_WRAPPER_OBJECT(JSObject *obj)
-{
- return !IS_WN_WRAPPER_OBJECT(obj);
-}
-
-// Use these functions if IS_WRAPPER_CLASS(GetObjectClass(obj)) might be false.
-// Avoid calling them if IS_WRAPPER_CLASS(GetObjectClass(obj)) can only be
-// true, as we'd do a redundant call to IS_WRAPPER_CLASS.
-static inline bool IS_WN_WRAPPER(JSObject *obj)
-{
- return IS_WRAPPER_CLASS(js::GetObjectClass(obj)) && IS_WN_WRAPPER_OBJECT(obj);
-}
-static inline bool IS_SLIM_WRAPPER(JSObject *obj)
-{
- return IS_WRAPPER_CLASS(js::GetObjectClass(obj)) && IS_SLIM_WRAPPER_OBJECT(obj);
+ return IS_WN_CLASS(js::GetObjectClass(obj));
}
extern bool
@@ -134,14 +102,10 @@ xpc_FastGetCachedWrapper(nsWrapperCache *cache, JSObject *scope, jsval *vp)
{
if (cache) {
JSObject* wrapper = cache->GetWrapper();
- NS_ASSERTION(!wrapper ||
- !cache->IsDOMBinding() ||
- !IS_SLIM_WRAPPER(wrapper),
- "Should never have a slim wrapper when IsDOMBinding()");
if (wrapper &&
js::GetObjectCompartment(wrapper) == js::GetObjectCompartment(scope) &&
(cache->IsDOMBinding() ? !cache->HasSystemOnlyWrapper() :
- (IS_SLIM_WRAPPER(wrapper) || xpc_OkToHandOutWrapper(cache)))) {
+ xpc_OkToHandOutWrapper(cache))) {
*vp = OBJECT_TO_JSVAL(wrapper);
return wrapper;
}
diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp
index be79dc31365a..0467e86a5fbd 100644
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -179,8 +179,8 @@ IsFrameId(JSContext *cx, JSObject *objArg, jsid idArg)
obj = JS_ObjectToInnerObject(cx, obj);
MOZ_ASSERT(!js::IsWrapper(obj));
- XPCWrappedNative *wn = IS_WN_WRAPPER(obj) ? XPCWrappedNative::Get(obj)
- : nullptr;
+ XPCWrappedNative *wn = IS_WN_REFLECTOR(obj) ? XPCWrappedNative::Get(obj)
+ : nullptr;
if (!wn) {
return false;
}
@@ -272,7 +272,7 @@ AccessCheck::needsSystemOnlyWrapper(JSObject *obj)
if (dom::GetSameCompartmentWrapperForDOMBinding(wrapper))
return wrapper != obj;
- if (!IS_WN_WRAPPER(obj))
+ if (!IS_WN_REFLECTOR(obj))
return false;
XPCWrappedNative *wn = static_cast(js::GetObjectPrivate(obj));
diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp
index 1edeb8e67847..1a0a9406754a 100644
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -152,11 +152,6 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
// We should never get a proxy here (the JS engine unwraps those for us).
MOZ_ASSERT(!IsWrapper(obj));
- // As soon as an object is wrapped in a security wrapper, it morphs to be
- // a fat wrapper. (see also: bug XXX).
- if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
- return nullptr;
-
// If the object being wrapped is a prototype for a standard class and the
// wrapper does not subsumes the wrappee, use the one from the content
// compartment. This is generally safer all-around, and in the COW case this
@@ -201,7 +196,7 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
// those objects in a security wrapper, then we need to hand back the
// wrapper for the new scope instead. Also, global objects don't move
// between scopes so for those we also want to return the wrapper. So...
- if (!IS_WN_WRAPPER(obj) || !js::GetObjectParent(obj))
+ if (!IS_WN_REFLECTOR(obj) || !js::GetObjectParent(obj))
return DoubleWrap(cx, obj, flags);
XPCWrappedNative *wn = static_cast(xpc_GetJSPrivate(obj));
@@ -300,7 +295,7 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
NS_ENSURE_SUCCESS(rv, nullptr);
obj = JSVAL_TO_OBJECT(v);
- NS_ASSERTION(IS_WN_WRAPPER(obj), "bad object");
+ NS_ASSERTION(IS_WN_REFLECTOR(obj), "bad object");
// Because the underlying native didn't have a PreCreate hook, we had
// to a new (or possibly pre-existing) XPCWN in our compartment.
@@ -522,7 +517,7 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, HandleObject objArg)
MOZ_ASSERT(!dom::IsDOMObject(obj));
- if (!IS_WN_WRAPPER(obj))
+ if (!IS_WN_REFLECTOR(obj))
return obj;
// Extract the WN. It should exist.
diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp
index 548a8fd98477..5efceda74bb5 100644
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -61,11 +61,9 @@ GetXrayType(JSObject *obj)
return XrayForDOMObject;
js::Class* clasp = js::GetObjectClass(obj);
- if (IS_WRAPPER_CLASS(clasp) || clasp->ext.innerObject) {
- NS_ASSERTION(clasp->ext.innerObject || IS_WN_WRAPPER_OBJECT(obj),
- "We forgot to Morph a slim wrapper!");
+ if (IS_WN_CLASS(clasp) || clasp->ext.innerObject)
return XrayForWrappedNative;
- }
+
return NotXray;
}
@@ -511,7 +509,7 @@ GetHolder(JSObject *obj)
static XPCWrappedNative *
GetWrappedNative(JSObject *obj)
{
- MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(obj));
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
return static_cast(js::GetObjectPrivate(obj));
}
diff --git a/layout/base/Units.h b/layout/base/Units.h
index 516a8eee9fdc..1d20677f95d2 100644
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -8,69 +8,95 @@
#define MOZ_UNITS_H_
#include "mozilla/gfx/Point.h"
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/gfx/ScaleFactor.h"
#include "nsDeviceContext.h"
namespace mozilla {
+struct CSSPixel;
+struct LayerPixel;
+struct ScreenPixel;
+
+typedef gfx::PointTyped CSSPoint;
+typedef gfx::IntPointTyped CSSIntPoint;
+typedef gfx::SizeTyped CSSSize;
+typedef gfx::IntSizeTyped CSSIntSize;
+typedef gfx::RectTyped CSSRect;
+typedef gfx::IntRectTyped CSSIntRect;
+
+typedef gfx::PointTyped LayerPoint;
+typedef gfx::IntPointTyped LayerIntPoint;
+typedef gfx::SizeTyped LayerSize;
+typedef gfx::IntSizeTyped LayerIntSize;
+typedef gfx::RectTyped LayerRect;
+typedef gfx::IntRectTyped LayerIntRect;
+
+typedef gfx::PointTyped ScreenPoint;
+typedef gfx::IntPointTyped ScreenIntPoint;
+typedef gfx::SizeTyped ScreenSize;
+typedef gfx::IntSizeTyped ScreenIntSize;
+typedef gfx::RectTyped ScreenRect;
+typedef gfx::IntRectTyped ScreenIntRect;
+
+typedef gfx::ScaleFactor CSSToLayerScale;
+typedef gfx::ScaleFactor LayerToCSSScale;
+typedef gfx::ScaleFactor CSSToScreenScale;
+typedef gfx::ScaleFactor ScreenToCSSScale;
+typedef gfx::ScaleFactor LayerToScreenScale;
+typedef gfx::ScaleFactor ScreenToLayerScale;
+
/*
* The pixels that content authors use to specify sizes in.
*/
struct CSSPixel {
- static gfx::IntPointTyped RoundToInt(const gfx::PointTyped& aPoint) {
- return gfx::IntPointTyped(NS_lround(aPoint.x),
- NS_lround(aPoint.y));
+
+ // Conversions from app units
+
+ static CSSPoint FromAppUnits(const nsPoint& aPoint) {
+ return CSSPoint(NSAppUnitsToFloatPixels(aPoint.x, float(nsDeviceContext::AppUnitsPerCSSPixel())),
+ NSAppUnitsToFloatPixels(aPoint.y, float(nsDeviceContext::AppUnitsPerCSSPixel())));
}
- static gfx::PointTyped FromAppUnits(const nsPoint& aPoint) {
- return gfx::PointTyped(NSAppUnitsToFloatPixels(aPoint.x, float(nsDeviceContext::AppUnitsPerCSSPixel())),
- NSAppUnitsToFloatPixels(aPoint.y, float(nsDeviceContext::AppUnitsPerCSSPixel())));
+ static CSSRect FromAppUnits(const nsRect& aRect) {
+ return CSSRect(NSAppUnitsToFloatPixels(aRect.x, float(nsDeviceContext::AppUnitsPerCSSPixel())),
+ NSAppUnitsToFloatPixels(aRect.y, float(nsDeviceContext::AppUnitsPerCSSPixel())),
+ NSAppUnitsToFloatPixels(aRect.width, float(nsDeviceContext::AppUnitsPerCSSPixel())),
+ NSAppUnitsToFloatPixels(aRect.height, float(nsDeviceContext::AppUnitsPerCSSPixel())));
}
- static gfx::IntPointTyped FromAppUnitsRounded(const nsPoint& aPoint) {
- return gfx::IntPointTyped