зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c and birch.
This commit is contained in:
Коммит
978c564339
1
CLOBBER
1
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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 @@
|
|||
|
||||
<p>Image:
|
||||
<img id="img_eq" role="math" src="foo" alt="x^2 + y^2 + z^2">
|
||||
<input type="image" id="input_img_eq" src="foo" alt="x^2 + y^2 + z^2">
|
||||
</p>
|
||||
|
||||
<p>Text:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>invalid html img</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
|
||||
<script>
|
||||
<![CDATA[
|
||||
function doTest()
|
||||
{
|
||||
document.getElementsByTagName("img")[0].firstChild.data = "2";
|
||||
|
||||
var accTree = {
|
||||
role: ROLE_TEXT_CONTAINER,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
};
|
||||
testAccessibleTree("the_img", accTree);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="use HyperTextAccessible for invalid img"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=852129">
|
||||
Mozilla Bug 852129
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<img id="the_img">1</img>
|
||||
</body>
|
||||
</html>
|
|
@ -51,7 +51,6 @@ STL_FLAGS=
|
|||
LIBS += $(JEMALLOC_LIBS)
|
||||
|
||||
LIBS += \
|
||||
$(EXTRA_DSO_LIBS) \
|
||||
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
|
|
@ -54,7 +54,6 @@ DEFINES += -DXPCOM_GLUE
|
|||
STL_FLAGS=
|
||||
|
||||
LIBS += \
|
||||
$(EXTRA_DSO_LIBS) \
|
||||
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
BrowserComponents.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
DISABLED_EXTRA_PP_COMPONENTS = \
|
||||
nsBrowserContentHandler.js \
|
||||
nsBrowserGlue.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -25,7 +25,7 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
WebContentConverter.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
DISABLED_EXTRA_PP_COMPONENTS = \
|
||||
FeedWriter.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -15,3 +15,7 @@ EXTRA_COMPONENTS += [
|
|||
'FeedConverter.js',
|
||||
'WebContentConverter.js',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'FeedWriter.js',
|
||||
]
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
|
|
@ -39,3 +39,7 @@ MODULE = 'browsercomps'
|
|||
EXTRA_COMPONENTS += [
|
||||
'BrowserComponents.manifest',
|
||||
]
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'nsBrowserContentHandler.js',
|
||||
'nsBrowserGlue.js',
|
||||
]
|
||||
|
|
|
@ -66,7 +66,7 @@ function test() {
|
|||
}
|
||||
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
executeSoon(afterSearch);
|
||||
executeSoon(() => executeSoon(afterSearch));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,3 +9,7 @@ MODULE = 'fuel'
|
|||
EXTRA_COMPONENTS += [
|
||||
'fuelApplication.manifest',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'fuelApplication.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;
|
||||
},
|
||||
|
||||
/*******************************************
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
|
|
@ -2090,7 +2090,7 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JS::Handle<JSObject*> 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) {
|
||||
|
|
|
@ -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 --------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
################################################################################
|
||||
|
|
|
@ -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<mozilla::css::Loader> mCSSLoader;
|
||||
nsRefPtr<mozilla::css::ImageLoader> mStyleImageLoader;
|
||||
nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
|
||||
nsRefPtr<nsHTMLCSSStyleSheet> 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.)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ EXTRA_COMPONENTS = \
|
|||
messageWakeupService.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
DISABLED_EXTRA_PP_COMPONENTS = \
|
||||
contentSecurityPolicy.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -153,3 +153,6 @@ CPP_SOURCES += [
|
|||
'nsXMLNameSpaceMap.cpp',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'contentSecurityPolicy.js',
|
||||
]
|
||||
|
|
|
@ -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<nsIPresShell> 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<nsIPresShell> 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<nsIPresShell> 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<ElementRegistrationOptions> options(aCx);
|
||||
if (aOptionalArgc > 0) {
|
||||
JSAutoCompartment ac(aCx, GetWrapper());
|
||||
JS::Rooted<JS::Value> 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,
|
||||
|
|
|
@ -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<nsIChannel> mChannel;
|
||||
nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
|
||||
|
||||
// A document "without a browsing context" that owns the content of
|
||||
// HTMLTemplateElement.
|
||||
|
|
|
@ -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<JSObject*> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1167,8 +1167,12 @@ nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
|
|||
CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&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<nsEventListenerInfo> info =
|
||||
|
|
|
@ -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 }));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<const void*>& aChannelData,
|
||||
AudioSampleFormat aSourceFormat, int32_t aDuration,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<script>
|
||||
o1 = new window.AudioContext(1, 2048, 44100);
|
||||
o2 = o1.createBufferSource();
|
||||
o1.destination.channelCountMode = 'max';
|
||||
o2.connect(o1.destination);
|
||||
o2.buffer = function(){
|
||||
var buffer = o1.createBuffer(30, 442, 94933);
|
||||
for(var c=0; c<30; c++) {
|
||||
for(var i=0; i<442; i++) {
|
||||
buffer.getChannelData(c)[i] = 1;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}();
|
||||
</script>
|
|
@ -46,3 +46,4 @@ load 880384.html
|
|||
load 880404.html
|
||||
load 880724.html
|
||||
load 881775.html
|
||||
load 882956.html
|
||||
|
|
|
@ -15,7 +15,7 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
Webapps.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
DISABLED_EXTRA_PP_COMPONENTS = \
|
||||
Webapps.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ EXTRA_COMPONENTS += [
|
|||
'Webapps.manifest',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'Webapps.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AppDownloadManager.jsm',
|
||||
'AppsServiceChild.jsm',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -535,29 +535,24 @@ MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> 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<JSObject*> 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
|
||||
|
|
|
@ -25,7 +25,6 @@ XPIDL_SOURCES += [
|
|||
'nsIDOMText.idl',
|
||||
'nsIDOMUserDataHandler.idl',
|
||||
'nsIDOMXMLDocument.idl',
|
||||
'nsIDocumentRegister.idl',
|
||||
'nsIInlineEventHandlers.idl',
|
||||
]
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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<nsIDOMDocument> domDoc;
|
||||
nsCOMPtr<nsIDOMElement> docElement;
|
||||
|
|
|
@ -441,7 +441,7 @@ private:
|
|||
nsRefPtr<TabChildGlobal> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<nsIEditorSpellCheck> spellCheck = mSpellCheck ? mSpellCheck :
|
||||
mPendingSpellCheck;
|
||||
if (!spellCheck) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_FAILED(mSpellCheck->GetCurrentDictionary(mPreviousDictionary))) {
|
||||
if (NS_FAILED(spellCheck->GetCurrentDictionary(mPreviousDictionary))) {
|
||||
mPreviousDictionary.Truncate();
|
||||
}
|
||||
|
||||
nsRefPtr<UpdateCurrentDictionaryCallback> 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);
|
||||
|
|
|
@ -61,6 +61,12 @@ struct PointTyped :
|
|||
};
|
||||
typedef PointTyped<UnknownUnits> Point;
|
||||
|
||||
template<class units>
|
||||
IntPointTyped<units> RoundedToInt(const PointTyped<units>& aPoint) {
|
||||
return IntPointTyped<units>(NS_lround(aPoint.x),
|
||||
NS_lround(aPoint.y));
|
||||
}
|
||||
|
||||
template<class units>
|
||||
struct IntSizeTyped :
|
||||
public BaseSize< int32_t, IntSizeTyped<units> >,
|
||||
|
|
|
@ -100,6 +100,26 @@ struct RectTyped :
|
|||
};
|
||||
typedef RectTyped<UnknownUnits> Rect;
|
||||
|
||||
template<class units>
|
||||
IntRectTyped<units> RoundedToInt(const RectTyped<units>& aRect)
|
||||
{
|
||||
return IntRectTyped<units>(NS_lround(aRect.x),
|
||||
NS_lround(aRect.y),
|
||||
NS_lround(aRect.width),
|
||||
NS_lround(aRect.height));
|
||||
}
|
||||
|
||||
template<class units>
|
||||
IntRectTyped<units> RoundedIn(const RectTyped<units>& aRect)
|
||||
{
|
||||
RectTyped<units> copy(aRect);
|
||||
copy.RoundIn();
|
||||
return IntRectTyped<units>(int32_t(copy.x),
|
||||
int32_t(copy.y),
|
||||
int32_t(copy.width),
|
||||
int32_t(copy.height));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<class src, class dst>
|
||||
struct ScaleFactor {
|
||||
float scale;
|
||||
|
||||
ScaleFactor() : scale(1.0) {}
|
||||
ScaleFactor(const ScaleFactor<src, dst>& 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<dst, src> Inverse() {
|
||||
return ScaleFactor<dst, src>(1 / scale);
|
||||
}
|
||||
|
||||
bool operator==(const ScaleFactor<src, dst>& aOther) const {
|
||||
return scale == aOther.scale;
|
||||
}
|
||||
|
||||
bool operator!=(const ScaleFactor<src, dst>& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
template<class other>
|
||||
ScaleFactor<other, dst> operator/(const ScaleFactor<src, other>& aOther) const {
|
||||
return ScaleFactor<other, dst>(scale / aOther.scale);
|
||||
}
|
||||
|
||||
template<class other>
|
||||
ScaleFactor<src, other> operator*(const ScaleFactor<dst, other>& aOther) const {
|
||||
return ScaleFactor<src, other>(scale * aOther.scale);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_GFX_SCALEFACTOR_H_ */
|
|
@ -20,6 +20,7 @@ EXPORTS.mozilla.gfx += [
|
|||
'Point.h',
|
||||
'Rect.h',
|
||||
'Scale.h',
|
||||
'ScaleFactor.h',
|
||||
'Tools.h',
|
||||
'Types.h',
|
||||
'UserData.h',
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<uint16>(--o_action);
|
||||
rc_begin = *--o_constraint ? rc_data + be::peek<uint16>(o_constraint) : rc_end;
|
||||
--o_constraint;
|
||||
rc_begin = be::peek<uint16>(o_constraint) ? rc_data + be::peek<uint16>(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)
|
||||
|
|
|
@ -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()]);
|
||||
}
|
||||
|
|
|
@ -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<const uint16 *>(pMid) - reinterpret_cast<const uint16 *>(pTable));
|
||||
if (offset * 2 >= pTable->length)
|
||||
const ptrdiff_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) +
|
||||
(pMid - reinterpret_cast<const uint16 *>(pTable));
|
||||
if (offset * 2 >= be::swap<uint16>(pTable->length))
|
||||
return 0;
|
||||
gid16 nGlyphId = be::peek<uint16>(pMid + (nUnicodeId - chStart) + (idRangeOffset >> 1));
|
||||
gid16 nGlyphId = be::peek<uint16>(reinterpret_cast<const uint16 *>(pTable)+offset);
|
||||
// If this value is 0, return 0. Else add the idDelta
|
||||
return nGlyphId ? nGlyphId + idDelta : 0;
|
||||
}
|
||||
|
|
|
@ -106,9 +106,9 @@ sparse::sparse(I attr, const I last)
|
|||
}
|
||||
if (m_nchunks == 0) return;
|
||||
|
||||
m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)/2)
|
||||
m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
|
||||
/ sizeof(mapped_type)
|
||||
+ n_values*sizeof(mapped_type));
|
||||
+ n_values);
|
||||
|
||||
if (m_array.values == 0)
|
||||
{
|
||||
|
|
|
@ -89,9 +89,9 @@ public:
|
|||
return mResolution * mDevPixelsPerCSSPixel;
|
||||
}
|
||||
|
||||
gfxPoint GetScrollOffsetInLayerPixels() const
|
||||
gfx::Point GetScrollOffsetInLayerPixels() const
|
||||
{
|
||||
return gfxPoint(
|
||||
return gfx::Point(
|
||||
static_cast<gfx::Float>(
|
||||
mScrollOffset.x * LayersPixelsPerCSSPixel().width),
|
||||
static_cast<gfx::Float>(
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -12,3 +12,6 @@ CPP_SOURCES += [
|
|||
'nsIconChannel.cpp',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'gtkqticonsconverter.js',
|
||||
]
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define Iterator_inl_h_
|
||||
|
||||
#include "jsiter.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
inline bool
|
||||
JSObject::isPropertyIterator() const
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include "vm/String.h"
|
||||
#include "vm/ThreadPool.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/Interpreter-inl.h"
|
||||
|
||||
using namespace 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() {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "builtin/RegExp.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/RegExpObject-inl.h"
|
||||
#include "vm/RegExpStatics-inl.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 --------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
################################################################################
|
||||
|
|
|
@ -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 <limits>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
@ -32,7 +30,12 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsprf.h"
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#include "ctypes/Library.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -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<FullParseHandler> &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<Parser<SyntaxParseHandler> > syntaxParser;
|
||||
if (options.canLazilyParse) {
|
||||
if (canLazilyParse) {
|
||||
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
|
||||
(Parser<SyntaxParseHandler> *) NULL,
|
||||
(LazyScript *) NULL);
|
||||
}
|
||||
|
||||
Parser<FullParseHandler> 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<ParseContext<FullParseHandler> > 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<ParseContext<FullParseHandler> > 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<FullParseHandler> 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<JSScript*> 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<Parser<SyntaxParseHandler> > syntaxParser;
|
||||
if (options.canLazilyParse) {
|
||||
if (canLazilyParse) {
|
||||
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
|
||||
(Parser<SyntaxParseHandler> *) NULL,
|
||||
(LazyScript *) NULL);
|
||||
|
@ -395,7 +412,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
|||
JS_ASSERT(!options.forEval);
|
||||
|
||||
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true,
|
||||
options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
|
||||
canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
|
||||
parser.sct = &sct;
|
||||
|
||||
JS_ASSERT(fun);
|
||||
|
|
|
@ -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<LabeledStatement>());
|
||||
break;
|
||||
|
||||
case PNK_COMMA:
|
||||
|
|
|
@ -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_<NullaryNode>(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_<NullaryNode>(PNK_NUMBER, pos());
|
||||
if (!pn)
|
||||
return NULL;
|
||||
pn->initNumber(value, decimalPoint);
|
||||
|
@ -130,8 +134,8 @@ class FullParseHandler
|
|||
return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
|
||||
}
|
||||
|
||||
ParseNode *newNullary(ParseNodeKind kind) {
|
||||
return NullaryNode::create(kind, this);
|
||||
ParseNode *newElision() {
|
||||
return new_<NullaryNode>(PNK_ELISION, pos());
|
||||
}
|
||||
|
||||
ParseNode *newUnary(ParseNodeKind kind, ParseNode *kid, JSOp op = JSOP_NOP) {
|
||||
|
@ -162,11 +166,6 @@ class FullParseHandler
|
|||
ParseContext<FullParseHandler> *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_<TernaryNode>(kind, op, first, second, third);
|
||||
}
|
||||
|
||||
ParseNode *newLabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) {
|
||||
return new_<LabeledStatement>(label, stmt, begin);
|
||||
}
|
||||
|
||||
ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) {
|
||||
TokenPos pos = TokenPos::make(begin, body->pn_pos.end);
|
||||
return new_<BinaryNode>(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);
|
||||
}
|
||||
|
||||
ParseNode *newBreak(PropertyName *label, uint32_t begin, uint32_t end) {
|
||||
return new_<BreakStatement>(label, begin, end);
|
||||
}
|
||||
ParseNode *newContinue(PropertyName *label, uint32_t begin, uint32_t end) {
|
||||
return new_<ContinueStatement>(label, begin, end);
|
||||
}
|
||||
|
||||
ParseNode *newDebuggerStatement(const TokenPos &pos) {
|
||||
return new_<DebuggerStatement>(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;
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -530,7 +530,7 @@ Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn)
|
|||
|
||||
pn2 = handler.new_<BinaryNode>(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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* <Expressions>
|
||||
* 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<FullParseHandler> *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,
|
||||
|
|
|
@ -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<ParseHandler>::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<FullParseHandler>::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<SyntaxParseHandler>::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<ParseHandler>::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<FullParseHandler>::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<SyntaxParseHandler>::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<SyntaxParseHandler>::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<SyntaxParseHandler>::functionArgsAndBody(Node pn, HandleFunction fun,
|
|||
*becameStrict = false;
|
||||
ParseContext<SyntaxParseHandler> *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<ParseHandler>::maybeParseDirective(Node pn, bool *cont)
|
|||
|
||||
template <>
|
||||
void
|
||||
Parser<FullParseHandler>::addStatementToList(ParseNode *pn, ParseNode *kid, bool *hasFunctionStmt)
|
||||
Parser<FullParseHandler>::addStatementToList(ParseNode *pn, ParseNode *kid)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
|
@ -2512,21 +2495,12 @@ Parser<FullParseHandler>::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<FullParseHandler>::addStatementToList(ParseNode *pn, ParseNode *kid, bool
|
|||
|
||||
template <>
|
||||
void
|
||||
Parser<SyntaxParseHandler>::addStatementToList(Node pn, Node kid, bool *hasFunctionStmt)
|
||||
Parser<SyntaxParseHandler>::addStatementToList(Node pn, Node kid)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2547,11 +2521,9 @@ Parser<SyntaxParseHandler>::addStatementToList(Node pn, Node kid, bool *hasFunct
|
|||
*/
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::statements(bool *hasFunctionStmt)
|
||||
Parser<ParseHandler>::statements()
|
||||
{
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
if (hasFunctionStmt)
|
||||
*hasFunctionStmt = false;
|
||||
|
||||
Node pn = handler.newList(PNK_STATEMENTLIST);
|
||||
if (!pn)
|
||||
|
@ -2584,7 +2556,7 @@ Parser<ParseHandler>::statements(bool *hasFunctionStmt)
|
|||
return null();
|
||||
}
|
||||
|
||||
addStatementToList(pn, next, hasFunctionStmt);
|
||||
addStatementToList(pn, next);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2993,7 +2965,7 @@ Parser<FullParseHandler>::bindDestructuringVar(BindData<FullParseHandler> *data,
|
|||
if (data->op == JSOP_DEFCONST)
|
||||
pn->pn_dflags |= PND_CONST;
|
||||
|
||||
handler.noteLValue(pn);
|
||||
pn->markAsAssigned();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3021,7 +2993,7 @@ Parser<FullParseHandler>::bindDestructuringLHS(ParseNode *pn)
|
|||
{
|
||||
switch (pn->getKind()) {
|
||||
case PNK_NAME:
|
||||
handler.noteLValue(pn);
|
||||
pn->markAsAssigned();
|
||||
/* FALL THROUGH */
|
||||
|
||||
case PNK_DOT:
|
||||
|
@ -3105,8 +3077,7 @@ Parser<FullParseHandler>::checkDestructuring(BindData<FullParseHandler> *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<ParseHandler>::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<ParseHandler>::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<ParseHandler>::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<ParseHandler>::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<FullParseHandler>::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<SyntaxParseHandler>::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<ParseHandler>::tryStatement()
|
|||
return pn;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::withStatement()
|
||||
template <>
|
||||
ParseNode *
|
||||
Parser<FullParseHandler>::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<ParseHandler>::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<ParseHandler>();
|
||||
DefinitionNode defn = r.front().value().get<FullParseHandler>();
|
||||
DefinitionNode lexdep = handler.resolve(defn);
|
||||
handler.deoptimizeUsesWithin(lexdep,
|
||||
TokenPos::make(begin, tokenStream.currentToken().pos.begin));
|
||||
|
@ -4369,6 +4343,14 @@ Parser<ParseHandler>::withStatement()
|
|||
return pn;
|
||||
}
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::Node
|
||||
Parser<SyntaxParseHandler>::withStatement()
|
||||
{
|
||||
JS_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return null();
|
||||
}
|
||||
|
||||
#if JS_HAS_BLOCK_SCOPE
|
||||
template <>
|
||||
ParseNode *
|
||||
|
@ -4499,6 +4481,35 @@ Parser<SyntaxParseHandler>::letStatement()
|
|||
|
||||
#endif // JS_HAS_BLOCK_SCOPE
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::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>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::expressionStatement()
|
||||
|
@ -4508,37 +4519,6 @@ Parser<ParseHandler>::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<ParseHandler>::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<ParseHandler>::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<ParseHandler>::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<FullParseHandler>::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<SyntaxParseHandler>::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<FullParseHandler>::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<SyntaxParseHandler>::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<ParseHandler>::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<SyntaxParseHandler>::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 <typename ParseHandler>
|
||||
|
@ -6601,9 +6606,8 @@ Parser<ParseHandler>::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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <typename ParseHandler>
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче