Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2013-08-01 16:35:13 -04:00
commit 7fe0b0251b
166 changed files with 3617 additions and 2844 deletions

View File

@ -17,4 +17,5 @@
#
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 878600 requires a clobber on Windows due to bug 890744
Multiple WebIDL changes requiring a clobber on Windows due to bug 890744

View File

@ -366,7 +366,7 @@ static void
MapTokenType(dom::Element* aElement, uint64_t* aState,
const TokenTypeData& aData)
{
if (aElement->HasAttr(kNameSpaceID_None, aData.mAttrName)) {
if (nsAccUtils::HasDefinedARIAToken(aElement, aData.mAttrName)) {
if ((aData.mType & eMixedType) &&
aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::mixed, eCaseMatters)) {
@ -380,12 +380,7 @@ MapTokenType(dom::Element* aElement, uint64_t* aState,
return;
}
if (!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::_undefined, eCaseMatters) &&
!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::_empty, eCaseMatters)) {
*aState |= aData.mPermanentState | aData.mTrueState;
}
*aState |= aData.mPermanentState | aData.mTrueState;
return;
}

View File

@ -37,8 +37,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (checkbox) checkable and checked states
testStates("checkbox_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("checkbox_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_empty", 0 , 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("checkbox_checked_undefined", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("checkbox_checked_empty", STATE_CHECKABLE , 0, STATE_CHECKED);
testStates("checkbox_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test native checkbox checked state and aria-checked state (if conflict, native wins)
@ -106,29 +106,29 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (menuitemradio) checkable and checked states
testStates("menuitemradio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (radio) checkable and checked states
testStates("radio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (textbox) multiline states
testStates("textbox_multiline_true", 0, EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_false", 0, EXT_STATE_SINGLE_LINE);
testStates("textbox_multiline_empty", 0, 0, 0, EXT_STATE_SINGLE_LINE | EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_undefined", 0, 0, 0, EXT_STATE_SINGLE_LINE | EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_empty", 0, EXT_STATE_SINGLE_LINE);
testStates("textbox_multiline_undefined", 0, EXT_STATE_SINGLE_LINE);
testStates("textbox_multiline_absent", 0, EXT_STATE_SINGLE_LINE);
// test (textbox) readonly states
testStates("textbox_readonly_true", STATE_READONLY);
testStates("textbox_readonly_false", 0, EXT_STATE_EDITABLE, STATE_READONLY);
testStates("textbox_readonly_empty", 0, 0, STATE_READONLY, EXT_STATE_EDITABLE);
testStates("textbox_readonly_undefined", 0, 0, STATE_READONLY, EXT_STATE_EDITABLE);
testStates("textbox_readonly_empty", 0, EXT_STATE_EDITABLE, STATE_READONLY);
testStates("textbox_readonly_undefined", 0, EXT_STATE_EDITABLE, STATE_READONLY);
testStates("textbox_readonly_absent", 0, EXT_STATE_EDITABLE, STATE_READONLY);
// test native textbox readonly state and aria-readonly state (if conflict, native wins)
@ -147,8 +147,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (treeitem) selectable and selected states
testStates("treeitem_selected_true", (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_false", STATE_SELECTABLE, 0, STATE_SELECTED);
testStates("treeitem_selected_empty", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_undefined", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_empty", STATE_SELECTABLE, 0, STATE_SELECTED);
testStates("treeitem_selected_undefined", STATE_SELECTABLE, 0, STATE_SELECTED);
testStates("treeitem_selected_absent", STATE_SELECTABLE, 0, STATE_SELECTED);
// test (treeitem) haspopup states

View File

@ -53,6 +53,3 @@ exports.indexedDB = Object.freeze({
exports.IDBKeyRange = IDBKeyRange;
exports.DOMException = Ci.nsIDOMDOMException;
exports.IDBCursor = Ci.nsIIDBCursor;
exports.IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
exports.IDBRequest = Ci.nsIIDBRequest;

View File

@ -8,8 +8,7 @@ let xulApp = require("sdk/system/xul-app");
if (xulApp.versionInRange(xulApp.platformVersion, "16.0a1", "*")) {
new function tests() {
const { indexedDB, IDBKeyRange, DOMException, IDBCursor,
IDBOpenDBRequest, IDBRequest
const { indexedDB, IDBKeyRange, DOMException
} = require("sdk/indexed-db");
exports["test indexedDB is frozen"] = function(assert){
@ -22,8 +21,7 @@ exports["test indexedDB is frozen"] = function(assert){
};
exports["test db variables"] = function(assert) {
[ indexedDB, IDBKeyRange, DOMException, IDBCursor,
IDBOpenDBRequest, IDBOpenDBRequest, IDBRequest
[ indexedDB, IDBKeyRange, DOMException
].forEach(function(value) {
assert.notEqual(typeof(value), "undefined", "variable is defined");
});

View File

@ -21,8 +21,8 @@ let Decoder = new TextDecoder();
* {fun:function_name, args:array_of_arguments_or_null, id: custom_id}
*
* Sends messages:
* {ok: result, id: custom_id} / {fail: serialized_form_of_OS.File.Error,
* id: custom_id}
* {ok: result, id: custom_id, telemetry: {}} /
* {fail: serialized_form_of_OS.File.Error, id: custom_id}
*/
self.onmessage = function (msg) {
let data = msg.data;
@ -34,7 +34,7 @@ self.onmessage = function (msg) {
let id = data.id;
try {
result = Agent[data.fun].apply(Agent, data.args);
result = Agent[data.fun].apply(Agent, data.args) || {};
} catch (ex if ex instanceof OS.File.Error) {
// Instances of OS.File.Error know how to serialize themselves
// (deserialization ensures that we end up with OS-specific
@ -46,7 +46,11 @@ self.onmessage = function (msg) {
// Other exceptions do not, and should be propagated through DOM's
// built-in mechanism for uncaught errors, although this mechanism
// may lose interesting information.
self.postMessage({ok: result, id: id});
self.postMessage({
ok: result.result,
id: id,
telemetry: result.telemetry || {}
});
};
let Agent = {
@ -100,24 +104,34 @@ let Agent = {
read: function () {
for (let path of [this.path, this.backupPath]) {
try {
return this.initialState = Decoder.decode(File.read(path));
let durationMs = Date.now();
let bytes = File.read(path);
durationMs = Date.now() - durationMs;
this.initialState = Decoder.decode(bytes);
return {
result: this.initialState,
telemetry: {FX_SESSION_RESTORE_READ_FILE_MS: durationMs}
};
} catch (ex if isNoSuchFileEx(ex)) {
// Ignore exceptions about non-existent files.
}
}
// No sessionstore data files found. Return an empty string.
return "";
return {result: ""};
},
/**
* Write the session to disk.
*/
write: function (stateString, options) {
let telemetry = {};
if (!this.hasWrittenState) {
if (options && options.backupOnFirstWrite) {
try {
let startMs = Date.now();
File.move(this.path, this.backupPath);
telemetry.FX_SESSION_RESTORE_BACKUP_FILE_MS = Date.now() - startMs;
} catch (ex if isNoSuchFileEx(ex)) {
// Ignore exceptions about non-existent files.
}
@ -126,8 +140,7 @@ let Agent = {
this.hasWrittenState = true;
}
let bytes = Encoder.encode(stateString);
return File.writeAtomic(this.path, bytes, {tmpPath: this.path + ".tmp"});
return this._write(stateString, telemetry);
},
/**
@ -158,8 +171,18 @@ let Agent = {
state.session = state.session || {};
state.session.state = loadState;
let bytes = Encoder.encode(JSON.stringify(state));
return File.writeAtomic(this.path, bytes, {tmpPath: this.path + ".tmp"});
return this._write(JSON.stringify(state));
},
/**
* Write a stateString to disk
*/
_write: function (stateString, telemetry = {}) {
let bytes = Encoder.encode(stateString);
let startMs = Date.now();
let result = File.writeAtomic(this.path, bytes, {tmpPath: this.path + ".tmp"});
telemetry.FX_SESSION_RESTORE_WRITE_FILE_MS = Date.now() - startMs;
return {result: result, telemetry: telemetry};
},
/**
@ -167,10 +190,10 @@ let Agent = {
*/
createBackupCopy: function (ext) {
try {
return File.copy(this.path, this.backupPath + ext);
return {result: File.copy(this.path, this.backupPath + ext)};
} catch (ex if isNoSuchFileEx(ex)) {
// Ignore exceptions about non-existent files.
return true;
return {result: true};
}
},
@ -179,10 +202,10 @@ let Agent = {
*/
removeBackupCopy: function (ext) {
try {
return File.remove(this.backupPath + ext);
return {result: File.remove(this.backupPath + ext)};
} catch (ex if isNoSuchFileEx(ex)) {
// Ignore exceptions about non-existent files.
return true;
return {result: true};
}
},
@ -219,7 +242,7 @@ let Agent = {
throw exn;
}
return true;
return {result: true};
}
};

View File

@ -203,13 +203,15 @@ let SessionFileInternal = {
},
read: function () {
return SessionWorker.post("read").then(msg => msg.ok);
return SessionWorker.post("read").then(msg => {
this._recordTelemetry(msg.telemetry);
return msg.ok;
});
},
write: function (aData, aOptions) {
let refObj = {};
return TaskUtils.spawn(function task() {
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj);
try {
@ -217,12 +219,11 @@ let SessionFileInternal = {
// At this point, we measure how long we stop the main thread
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj);
// Now wait for the result and measure how long we had to wait for the result
yield promise;
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
// Now wait for the result and record how long the write took
let msg = yield promise;
this._recordTelemetry(msg.telemetry);
} catch (ex) {
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_LONGEST_OP_MS", refObj);
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
Cu.reportError("Could not write session state file " + this.path
+ ": " + ex);
}
@ -230,7 +231,10 @@ let SessionFileInternal = {
},
writeLoadStateOnceAfterStartup: function (aLoadState) {
return SessionWorker.post("writeLoadStateOnceAfterStartup", [aLoadState]);
return SessionWorker.post("writeLoadStateOnceAfterStartup", [aLoadState]).then(msg => {
this._recordTelemetry(msg.telemetry);
return msg;
});
},
createBackupCopy: function (ext) {
@ -243,6 +247,12 @@ let SessionFileInternal = {
wipe: function () {
return SessionWorker.post("wipe");
},
_recordTelemetry: function(telemetry) {
for (let histogramId in telemetry){
Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]);
}
}
};

View File

@ -100,15 +100,19 @@ var Appbar = {
},
onMenuButton: function(aEvent) {
var typesArray = ["find-in-page"];
let typesArray = [];
if (ConsolePanelView.enabled) typesArray.push("open-error-console");
if (!MetroUtils.immersive) typesArray.push("open-jsshell");
if (!StartUI.isVisible)
typesArray.push("find-in-page");
if (ConsolePanelView.enabled)
typesArray.push("open-error-console");
if (!MetroUtils.immersive)
typesArray.push("open-jsshell");
try {
// If we have a valid http or https URI then show the view on desktop
// menu item.
var uri = Services.io.newURI(Browser.selectedBrowser.currentURI.spec,
let uri = Services.io.newURI(Browser.selectedBrowser.currentURI.spec,
null, null);
if (uri.schemeIs('http') || uri.schemeIs('https')) {
typesArray.push("view-on-desktop");

View File

@ -35,7 +35,13 @@ var APZCObserver = {
switch (aEvent.type) {
case 'pageshow':
case 'TabSelect':
Services.obs.notifyObservers(null, "viewport-needs-updating", null);
const ROOT_ID = 1;
let windowUtils = Browser.selectedBrowser.contentWindow.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
windowUtils.setDisplayPortForElement(0, 0, ContentAreaObserver.width,
ContentAreaObserver.height,
windowUtils.findElementWithViewId(ROOT_ID));
break;
case 'TabOpen': {
let browser = aEvent.originalTarget.linkedBrowser;
@ -65,6 +71,7 @@ var APZCObserver = {
observe: function ao_observe(aSubject, aTopic, aData) {
if (aTopic == "apzc-request-content-repaint") {
let frameMetrics = JSON.parse(aData);
let scrollId = frameMetrics.scrollId;
let scrollTo = frameMetrics.scrollTo;
let displayPort = frameMetrics.displayPort;
let resolution = frameMetrics.resolution;
@ -93,10 +100,11 @@ var APZCObserver = {
w: displayPort.width,
h: displayPort.height,
scale: resolution,
id: 1
id: scrollId
});
}
Util.dumpLn("APZC scrollId: " + scrollId);
Util.dumpLn("APZC scrollTo.x: " + scrollTo.x + ", scrollTo.y: " + scrollTo.y);
Util.dumpLn("APZC setResolution: " + resolution);
Util.dumpLn("APZC setDisplayPortForElement: displayPort.x: " +

View File

@ -298,6 +298,8 @@ let Content = {
xPos: aEvent.clientX + offsetX,
yPos: aEvent.clientY + offsetY
});
} else {
SelectionHandler.closeSelection();
}
},

View File

@ -80,8 +80,9 @@ FormAssistant.prototype = {
// Sometimes the element inner frame get destroyed while the element
// receive the focus because the display is turned to 'none' for
// example, in this "fun" case just do nothing if the element is hidden
if (self._isVisibleElement(gFocusManager.focusedElement))
sendAsyncMessage("FormAssist:Show", self._getJSON());
if (self._isVisibleElement(gFocusManager.focusedElement)) {
self._sendJsonMsgWrapper("FormAssist:Show");
}
});
return this._currentElement;
},
@ -204,7 +205,7 @@ FormAssistant.prototype = {
break;
case "FormAssist:Update":
sendAsyncMessage("FormAssist:Show", this._getJSON());
this._sendJsonMsgWrapper("FormAssist:Show");
break;
}
},
@ -281,8 +282,9 @@ FormAssistant.prototype = {
break;
case "text":
if (this._isAutocomplete(aEvent.target))
sendAsyncMessage("FormAssist:AutoComplete", this._getJSON());
if (this._isAutocomplete(aEvent.target)) {
this._sendJsonMsgWrapper("FormAssist:AutoComplete");
}
break;
case "keyup":
@ -292,7 +294,7 @@ FormAssistant.prototype = {
return;
if (this._isAutocomplete(aEvent.target)) {
sendAsyncMessage("FormAssist:AutoComplete", this._getJSON());
this._sendJsonMsgWrapper("FormAssist:AutoComplete");
}
let caretRect = this._getCaretRect();
@ -426,7 +428,10 @@ FormAssistant.prototype = {
},
_isVisibleElement: function formHelperIsVisibleElement(aElement) {
let style = aElement ? aElement.ownerDocument.defaultView.getComputedStyle(aElement, null) : null;
if (!aElement || !aElement.ownerDocument) {
return false;
}
let style = aElement.ownerDocument.defaultView.getComputedStyle(aElement, null);
if (!style)
return false;
@ -504,8 +509,18 @@ FormAssistant.prototype = {
return associatedLabels;
},
_sendJsonMsgWrapper: function (aMsg) {
let json = this._getJSON();
if (json) {
sendAsyncMessage(aMsg, json);
}
},
_getJSON: function() {
let element = this.currentElement;
if (!element) {
return null;
}
let choices = getListForElement(element);
let editable = (element instanceof HTMLInputElement && element.mozIsTextField(false)) || this._isEditable(element);

View File

@ -225,14 +225,14 @@ var SelectionHandler = {
// This should never happen, but we check to make sure
if (!this._targetIsEditable) {
this._onFail("Unexpected, coordiates didn't find a text input element.");
this._onFail("Coordiates didn't find a text input element.");
return;
}
// Locate and sanity check the caret position
let selection = this._getSelection();
if (!selection || !selection.isCollapsed) {
this._onFail("Unexpected, No selection or selection is not collapsed.");
this._onFail("No selection or selection is not collapsed.");
return;
}
@ -281,7 +281,7 @@ var SelectionHandler = {
if (aClearSelection) {
this._clearSelection();
}
this._closeSelection();
this.closeSelection();
},
/*
@ -307,7 +307,7 @@ var SelectionHandler = {
Util.dumpLn(aDbgMessage);
this.sendAsync("Content:SelectionFail");
this._clearSelection();
this._closeSelection();
this.closeSelection();
},
/*
@ -368,11 +368,11 @@ var SelectionHandler = {
},
/*
* _closeSelection
* closeSelection
*
* Shuts SelectionHandler down.
*/
_closeSelection: function _closeSelection() {
closeSelection: function closeSelection() {
this._clearTimers();
this._cache = null;
this._contentWindow = null;

View File

@ -639,38 +639,6 @@ var SelectionHelperUI = {
});
},
/*
* _transitionFromSelectionToCaret
*
* Transitions from text selection mode to caret mode.
*
* @param aClientX, aClientY - client coordinates of the
* tap that initiates the change.
*/
_transitionFromSelectionToCaret: function _transitionFromSelectionToCaret(aClientX, aClientY) {
// Reset some of our state
this._activeSelectionRect = null;
// Reset the monocles
this._shutdownAllMarkers();
this._setupMonocleIdArray();
// Translate to browser relative client coordinates
let coords =
this._msgTarget.ptClientToBrowser(aClientX, aClientY, true);
// Init SelectionHandler and turn on caret selection. Note the focus caret
// will have been removed from the target element due to the shutdown call.
// This won't set the caret position on its own.
this._sendAsyncMessage("Browser:CaretAttach", {
xPos: coords.x,
yPos: coords.y
});
// Set the caret position
this._setCaretPositionAtPoint(coords.x, coords.y);
},
/*
* _setupDebugOptions
*
@ -803,68 +771,14 @@ var SelectionHelperUI = {
*/
/*
* _onTap
*
* Handles taps that move the current caret around in text edits,
* clear active selection and focus when neccessary, or change
* modes.
* Future: changing selection modes by tapping on a monocle.
*/
_onTap: function _onTap(aEvent) {
let clientCoords =
this._msgTarget.ptBrowserToClient(aEvent.clientX, aEvent.clientY, true);
// Check for a tap on a monocle
if (this.startMark.hitTest(clientCoords.x, clientCoords.y) ||
this.endMark.hitTest(clientCoords.x, clientCoords.y)) {
aEvent.stopPropagation();
aEvent.preventDefault();
return;
}
// Is the tap point within the bound of the target element? This
// is useful if we are dealing with some sort of input control.
// Not so much if the target is a page or div.
let pointInTargetElement =
Util.pointWithinRect(clientCoords.x, clientCoords.y,
this._targetElementRect);
// If the tap is within an editable element and the caret monocle is
// active, update the caret.
if (this.caretMark.visible && pointInTargetElement) {
// setCaretPositionAtPoint takes browser relative coords.
this._setCaretPositionAtPoint(aEvent.clientX, aEvent.clientY);
return;
}
// if the target is editable, we have selection or a caret, and the
// user clicks off the target clear selection and remove focus from
// the input.
if (this._targetIsEditable && !pointInTargetElement) {
// shutdown but leave focus alone. the event will fall through
// and the dom will update focus for us. If the user tapped on
// another input, we'll get a attachToCaret call soonish on the
// new input.
this.closeEditSession(false);
return;
}
if (this._hitTestSelection(aEvent) && this._targetIsEditable) {
// Attach to the newly placed caret position
_onClick: function(aEvent) {
if (this.layerMode == kChromeLayer && this._targetIsEditable) {
this.attachToCaret(this._msgTarget, aEvent.clientX, aEvent.clientY);
return;
}
// A tap within an editable but outside active selection, clear the
// selection and flip back to caret mode.
if (this.startMark.visible && pointInTargetElement &&
this._targetIsEditable) {
this._transitionFromSelectionToCaret(clientCoords.x, clientCoords.y);
return;
}
// Close when we get a single tap in content.
this.closeEditSession(false);
},
_onKeypress: function _onKeypress() {
@ -1019,7 +933,7 @@ var SelectionHelperUI = {
}
switch (aEvent.type) {
case "click":
this._onTap(aEvent);
this._onClick(aEvent);
break;
case "touchstart": {

View File

@ -56,6 +56,8 @@ MOCHITEST_METRO_FILES += \
browser_selection_urlbar.js \
browser_selection_contenteditable.js \
browser_selection_contenteditable.html \
browser_selection_caretfocus.js \
browser_selection_caretfocus.html \
$(NULL)
endif

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id="Text1" style="width:300px;" value="text input text input text input" type="text">
<input id="Text2" style="width:300px;" value="text input text input text input" type="text">
<input id="Text3" style="width:300px;" value="text input text input text input" type="text">
<iframe id="Text4" frameborder="0" style="overflow: hidden; border: 1px solid lightgray;" height="50" src="./res/textarea01.html" width="300"></iframe>
<textarea id="Text5" style="overflow: hidden;" name="textarea" rows="2" cols="36">text area text area text area text area text area</textarea>
<div id="Text6" style="width:300px; border: 1px solid lightgray;">text div text div text div text div</div>
</body>
</html>

View File

@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let gWindow = null;
///////////////////////////////////////////////////
// form input tests
///////////////////////////////////////////////////
function setUpAndTearDown() {
emptyClipboard();
if (gWindow)
clearSelection(gWindow);
yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible;
});
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
}
gTests.push({
desc: "normalize browser",
setUp: setUpAndTearDown,
tearDown: setUpAndTearDown,
run: function test() {
info(chromeRoot + "browser_selection_caretfocus.html");
yield addTab(chromeRoot + "browser_selection_caretfocus.html");
yield waitForCondition(function () {
return !StartUI.isStartPageVisible;
});
yield hideContextUI();
gWindow = Browser.selectedTab.browser.contentWindow;
},
});
function tapText(aIndex) {
gWindow = Browser.selectedTab.browser.contentWindow;
let id = "Text" + aIndex;
info("tapping " + id);
let element = gWindow.document.getElementById(id);
if (element.contentDocument) {
element = element.contentDocument.getElementById("textarea");
gWindow = element.ownerDocument.defaultView;
}
sendElementTap(gWindow, element, 100, 10);
return element;
}
gTests.push({
desc: "focus navigation",
setUp: setUpAndTearDown,
tearDown: setUpAndTearDown,
run: function test() {
for (let iteration = 0; iteration < 3; iteration++) {
for (let input = 1; input <= 6; input++) {
let element = tapText(input);
if (input == 6) {
// div
yield waitForCondition(function () {
return !SelectionHelperUI.isActive;
});
} else {
// input
yield SelectionHelperUI.pingSelectionHandler();
yield waitForCondition(function () {
return SelectionHelperUI.isCaretUIVisible;
});
ok(element == gWindow.document.activeElement, "element has focus");
}
}
}
},
});
function test() {
if (!isLandscapeMode()) {
todo(false, "browser_selection_tests need landscape mode to run.");
return;
}
// XXX need this until bugs 886624 and 859742 are fully resolved
setDevPixelEqualToPx();
runTests();
}

View File

@ -68,7 +68,8 @@ flyoutpanel[visible] {
}
.flyoutpanel-contents[input="precise"] {
overflow: scroll;
overflow-y: scroll;
overflow-x: hidden;
}
.flyout-close-button {

View File

@ -19,9 +19,14 @@
#
# Targets are defined by the following variables:
#
# FILE - The make file to evaluate.
# FILE - The make file to evaluate. This is equivalent to
# |make -f <FILE>|
# DIRECTORY - The directory whose Makefile to evaluate. This is
# equivalent to |make -C <DIRECTORY>|.
# TARGETS - Targets to evaluate in that make file.
#
# Only 1 of FILE or DIRECTORY may be defined.
#
# For example:
#
# NONRECURSIVE_TARGETS = export libs
@ -29,30 +34,31 @@
# NONRECURSIVE_TARGETS_export_headers_FILE = /path/to/exports.mk
# NONRECURSIVE_TARGETS_export_headers_TARGETS = $(DIST)/include/foo.h $(DIST)/include/bar.h
# NONRECURSIVE_TARGETS_libs = cppsrcs
# NONRECURSIVE_TARGETS_libs_cppsrcs_FILE = /path/to/compilation.mk
# NONRECURSIVE_TARGETS_libs_cppsrcs_DIRECTORY = $(DEPTH)/foo
# NONRECURSIVE_TARGETS_libs_cppsrcs_TARGETS = /path/to/foo.o /path/to/bar.o
#
# Will get turned into the following:
#
# exports::
# $(MAKE) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
# $(MAKE) -C $(DEPTH) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
#
# libs::
# $(MAKE) -f /path/to/compilation.mk /path/to/foo.o /path/to/bar.o
# $(MAKE) -C $(DEPTH)/foo /path/to/foo.o /path/to/bar.o
ifndef INCLUDED_NONRECURSIVE_MK
define define_nonrecursive_target
$(1)::
cd $$(DEPTH) && $$(MAKE) -f $(2) $(3)
$$(MAKE) -C $(or $(4),$$(DEPTH)) $(addprefix -f ,$(3)) $(2)
endef
$(foreach target,$(NONRECURSIVE_TARGETS), \
$(foreach entry,$(NONRECURSIVE_TARGETS_$(target)), \
$(eval $(call define_nonrecursive_target, \
$(target), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_FILE), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS) \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_DIRECTORY), \
)) \
) \
)

View File

@ -0,0 +1,34 @@
# 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/.
# This make file defines the precompile tier. This tier effectively fans out
# to other make files and specialized targets.
DEPTH := @DEPTH@
topsrcdir := @top_srcdir@
srcdir := @srcdir@
include $(DEPTH)/config/autoconf.mk
SUPPRESS_DEFAULT_RULES := 1
include $(topsrcdir)/config/rules.mk
define make_subtier_dir
@echo "BUILDSTATUS SUBTIER_START precompile $(1)"
$(MAKE) -C $(2) $(3)
@echo "BUILDSTATUS SUBTIER_FINISH precompile $(1)"
endef
export::
@echo "BUILDSTATUS SUBTIERS IPDL WebIDL"
export:: ipdl webidl
ipdl:
$(call make_subtier_dir,IPDL,$(DEPTH)/ipc/ipdl,ipdl)
webidl:
$(call make_subtier_dir,WebIDL,$(DEPTH)/dom/bindings,webidl)

View File

@ -0,0 +1,5 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.

View File

@ -2116,6 +2116,11 @@ public:
const nsAString& aFeature,
const nsAString& aVersion);
/**
* Return true if the browser.dom.window.dump.enabled pref is set.
*/
static bool DOMWindowDumpEnabled();
private:
static bool InitializeEventTable();
@ -2225,6 +2230,10 @@ private:
static nsString* sOSText;
static nsString* sAltText;
static nsString* sModifierSeparator;
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
static bool sDOMWindowDumpEnabled;
#endif
};
typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>

View File

@ -208,6 +208,7 @@
#include "nsINode.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/Element.h"
#include "nsIDOMHTMLDocument.h"
#include "nsUnicodeProperties.h"
@ -535,7 +536,7 @@ public:
void EnsureMapIsClear(nsINode* aTextNode)
{
uint32_t clearedEntries =
DebugOnly<uint32_t> clearedEntries =
mElements.EnumerateEntries(ClearEntry, aTextNode);
MOZ_ASSERT(clearedEntries == 0, "Map should be empty already");
}

View File

@ -1966,7 +1966,8 @@ Element::List(FILE* out, int32_t aIndent,
ListAttributes(out);
fprintf(out, " state=[%llx]", State().GetInternalValue());
fprintf(out, " state=[%llx]",
static_cast<unsigned long long>(State().GetInternalValue()));
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
if (IsCommonAncestorForRangeInSelection()) {
nsRange::RangeHashTable* ranges =

View File

@ -242,6 +242,10 @@ nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
bool nsContentUtils::sFragmentParsingActive = false;
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
bool nsContentUtils::sDOMWindowDumpEnabled;
#endif
namespace {
static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
@ -434,6 +438,11 @@ nsContentUtils::Init()
"dom.event.handling-user-input-time-limit",
1000);
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
"browser.dom.window.dump.enabled");
#endif
Element::InitCCCallbacks();
sInitialized = true;
@ -6423,3 +6432,16 @@ nsContentUtils::InternalIsSupported(nsISupports* aObject,
// Otherwise, we claim to support everything
return true;
}
bool
nsContentUtils::DOMWindowDumpEnabled()
{
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
// In optimized builds we check a pref that controls if we should
// enable output from dump() or not, in debug builds it's always
// enabled.
return nsContentUtils::sDOMWindowDumpEnabled;
#else
return true;
#endif
}

View File

@ -545,7 +545,7 @@ protected:
/**
* Check if the target is valid after calling EnsureTarget.
*/
bool IsTargetValid() { return mTarget != sErrorTarget; }
bool IsTargetValid() { return mTarget != sErrorTarget && mTarget != nullptr; }
/**
* Returns the surface format this canvas should be allocated using. Takes

View File

@ -145,6 +145,15 @@ static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
// ==================================================================
// =
// ==================================================================
static void
ReportUseOfDeprecatedMethod(nsHTMLDocument* aDoc, const char* aWarning)
{
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
"DOM Events", aDoc,
nsContentUtils::eDOM_PROPERTIES,
aWarning);
}
static nsresult
RemoveFromAgentSheets(nsCOMArray<nsIStyleSheet> &aAgentSheets, const nsAString& url)
{
@ -2238,6 +2247,20 @@ nsHTMLDocument::GetSelection(ErrorResult& rv)
return sel.forget();
}
NS_IMETHODIMP
nsHTMLDocument::CaptureEvents(int32_t aEventFlags)
{
ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
return NS_OK;
}
NS_IMETHODIMP
nsHTMLDocument::ReleaseEvents(int32_t aEventFlags)
{
ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
return NS_OK;
}
// Mapped to document.embeds for NS4 compatibility
NS_IMETHODIMP
nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins)

View File

@ -242,6 +242,8 @@ public:
// Deprecated
}
already_AddRefed<nsISelection> GetSelection(mozilla::ErrorResult& rv);
// The XPCOM CaptureEvents works fine for us.
// The XPCOM ReleaseEvents works fine for us.
// We're picking up GetLocation from Document
already_AddRefed<nsIDOMLocation> GetLocation() const {
return nsIDocument::GetLocation();

View File

@ -202,8 +202,6 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/IDBCursor.h"
#include "mozilla/dom/indexedDB/IDBKeyRange.h"
using mozilla::dom::indexedDB::IDBWrapperCache;
@ -253,6 +251,7 @@ using mozilla::dom::workers::ResolveWorkerClasses;
#include "DOMCameraCapabilities.h"
#include "nsIOpenWindowEventDetail.h"
#include "nsIAsyncScrollEventDetail.h"
#include "nsIDOMGlobalObjectConstructor.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "LockedFile.h"
#include "nsDebug.h"
@ -631,16 +630,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBRequest, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBCursor, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBCursorWithValue, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBKeyRange, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBOpenDBRequest, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
@ -1527,30 +1518,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(IDBRequest, nsIIDBRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(IDBCursor, nsIIDBCursor)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursor)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(IDBCursorWithValue, nsIIDBCursorWithValue)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursor)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursorWithValue)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(IDBKeyRange, nsIIDBKeyRange)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBKeyRange)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(IDBOpenDBRequest, nsIIDBOpenDBRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBOpenDBRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIIDBRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
DOM_CLASSINFO_MAP_END
@ -2706,7 +2677,8 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
}
nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native));
if (initializer) {
nsCOMPtr<nsIDOMGlobalObjectConstructor> constructor(do_QueryInterface(native));
if (initializer || constructor) {
// Initialize object using the current inner window, but only if
// the caller can access it.
nsCOMPtr<nsPIDOMWindow> owner = do_QueryReferent(aWeakOwner);
@ -2719,9 +2691,62 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
return NS_ERROR_DOM_SECURITY_ERR;
}
rv = initializer->Initialize(currentInner, cx, obj, args);
if (NS_FAILED(rv)) {
return rv;
if (initializer) {
rv = initializer->Initialize(currentInner, cx, obj, args);
if (NS_FAILED(rv)) {
return rv;
}
} else {
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native);
JS::Rooted<JSObject*> thisObject(cx, wrappedJS->GetJSObject());
if (!thisObject) {
return NS_ERROR_UNEXPECTED;
}
nsCxPusher pusher;
pusher.Push(cx);
JSAutoCompartment ac(cx, thisObject);
JS::Rooted<JS::Value> funval(cx);
if (!JS_GetProperty(cx, thisObject, "constructor", &funval) ||
!funval.isObject()) {
return NS_ERROR_UNEXPECTED;
}
// Check if the object is even callable.
NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject()));
{
// wrap parameters in the target compartment
// we also pass in the calling window as the first argument
unsigned argc = args.length() + 1;
nsAutoArrayPtr<JS::Value> argv(new JS::Value[argc]);
JS::AutoArrayRooter rooter(cx, 0, argv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner));
rv = WrapNative(cx, obj, currentWin, &NS_GET_IID(nsIDOMWindow),
true, &argv[0], getter_AddRefs(holder));
if (!JS_WrapValue(cx, &argv[0]))
return NS_ERROR_FAILURE;
rooter.changeLength(1);
for (size_t i = 1; i < argc; ++i) {
argv[i] = args[i - 1];
if (!JS_WrapValue(cx, &argv[i]))
return NS_ERROR_FAILURE;
rooter.changeLength(i + 1);
}
JS::Rooted<JS::Value> frval(cx);
bool ret = JS_CallFunctionValue(cx, thisObject, funval, argc, argv,
frval.address());
if (!ret) {
return NS_ERROR_FAILURE;
}
}
}
}
@ -2808,142 +2833,6 @@ DefineInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *
return NS_OK;
}
// This code is temporary until we remove support for the constants defined
// on IDBCursor/IDBRequest
struct IDBConstant
{
const char* interface;
const char* name;
const char* value;
static const char* IDBCursor;
static const char* IDBRequest;
};
const char* IDBConstant::IDBCursor = "IDBCursor";
const char* IDBConstant::IDBRequest = "IDBRequest";
static const IDBConstant sIDBConstants[] = {
{ IDBConstant::IDBCursor, "NEXT", "next" },
{ IDBConstant::IDBCursor, "NEXT_NO_DUPLICATE", "nextunique" },
{ IDBConstant::IDBCursor, "PREV", "prev" },
{ IDBConstant::IDBCursor, "PREV_NO_DUPLICATE", "prevunique" },
{ IDBConstant::IDBRequest, "LOADING", "pending" },
{ IDBConstant::IDBRequest, "DONE", "done" },
};
static JSBool
IDBConstantGetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp)
{
JSString *idstr = JSID_TO_STRING(id);
unsigned index;
for (index = 0; index < mozilla::ArrayLength(sIDBConstants); index++) {
JSBool match;
if (!JS_StringEqualsAscii(cx, idstr, sIDBConstants[index].name, &match)) {
return JS_FALSE;
}
if (match) {
break;
}
}
MOZ_ASSERT(index < mozilla::ArrayLength(sIDBConstants));
const IDBConstant& c = sIDBConstants[index];
// Put a warning on the console
nsString warnText =
NS_LITERAL_STRING("The constant ") +
NS_ConvertASCIItoUTF16(c.interface) +
NS_LITERAL_STRING(".") +
NS_ConvertASCIItoUTF16(c.name) +
NS_LITERAL_STRING(" has been deprecated. Use the string value \"") +
NS_ConvertASCIItoUTF16(c.value) +
NS_LITERAL_STRING("\" instead.");
uint64_t windowID = 0;
nsIScriptContext* context = GetScriptContextFromJSContext(cx);
if (context) {
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(context->GetGlobalObject());
if (window) {
window = window->GetCurrentInnerWindow();
}
NS_WARN_IF_FALSE(window, "Missing a window, got a door?");
if (window) {
windowID = window->WindowID();
}
}
nsCOMPtr<nsIScriptError> errorObject =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
NS_WARN_IF_FALSE(errorObject, "Failed to create error object");
if (errorObject) {
nsresult rv = errorObject->InitWithWindowID(warnText,
EmptyString(), // file name
EmptyString(), // source line
0, 0, // Line/col number
nsIScriptError::warningFlag,
"DOM Core", windowID);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to init error object");
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIConsoleService> consoleServ =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleServ) {
consoleServ->LogMessage(errorObject);
}
}
}
// Redefine property to remove getter
NS_ConvertASCIItoUTF16 valStr(c.value);
JS::Rooted<JS::Value> value(cx);
if (!xpc::StringToJsval(cx, valStr, value.address())) {
return JS_FALSE;
}
if (!::JS_DefineProperty(cx, obj, c.name, value,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE)) {
return JS_FALSE;
}
// Return value
vp.set(value);
return JS_TRUE;
}
static nsresult
DefineIDBInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID)
{
const char* interface;
if (aIID->Equals(NS_GET_IID(nsIIDBCursor))) {
interface = IDBConstant::IDBCursor;
}
else if (aIID->Equals(NS_GET_IID(nsIIDBRequest))) {
interface = IDBConstant::IDBRequest;
}
else {
MOZ_CRASH("unexpected IID");
}
for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
const IDBConstant& c = sIDBConstants[i];
if (c.interface != interface) {
continue;
}
if (!JS_DefineProperty(cx, obj, c.name, JSVAL_VOID,
IDBConstantGetter, JS_StrictPropertyStub,
JSPROP_ENUMERATE)) {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
class nsDOMConstructor MOZ_FINAL : public nsIDOMDOMConstructor
{
protected:
@ -3343,14 +3232,6 @@ nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*>
return NS_ERROR_FAILURE;
}
// Special case a few IDB interfaces which for now are getting transitional
// constants.
if (class_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
class_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
rv = DefineIDBInterfaceConstants(cx, obj, class_iid);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -3481,14 +3362,6 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
return NS_ERROR_FAILURE;
}
// Special case a few IDB interfaces which for now are getting transitional
// constants.
if (primary_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
primary_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
rv = DefineIDBInterfaceConstants(cx, class_obj, primary_iid);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIInterfaceInfoManager>
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);

View File

@ -119,12 +119,7 @@ DOMCI_CLASS(ContentFrameMessageManager)
DOMCI_CLASS(ChromeMessageBroadcaster)
DOMCI_CLASS(ChromeMessageSender)
DOMCI_CLASS(IDBRequest)
DOMCI_CLASS(IDBCursor)
DOMCI_CLASS(IDBCursorWithValue)
DOMCI_CLASS(IDBKeyRange)
DOMCI_CLASS(IDBOpenDBRequest)
DOMCI_CLASS(MozCSSKeyframeRule)
DOMCI_CLASS(MozCSSKeyframesRule)

View File

@ -283,10 +283,6 @@ static TimeStamp gLastRecordedRecentTimeouts;
int32_t gTimeoutCnt = 0;
#endif
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
static bool gDOMWindowDumpEnabled = false;
#endif
#if defined(DEBUG_bryner) || defined(DEBUG_chb)
#define DEBUG_PAGE_CACHE
#endif
@ -1085,10 +1081,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
gRefCnt++;
if (gRefCnt == 1) {
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
Preferences::AddBoolVarCache(&gDOMWindowDumpEnabled,
"browser.dom.window.dump.enabled");
#endif
Preferences::AddIntVarCache(&gMinTimeoutValue,
"dom.min_timeout_value",
DEFAULT_MIN_TIMEOUT_VALUE);
@ -5160,23 +5152,10 @@ nsGlobalWindow::GetFullScreen(bool* aFullScreen)
return NS_OK;
}
bool
nsGlobalWindow::DOMWindowDumpEnabled()
{
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
// In optimized builds we check a pref that controls if we should
// enable output from dump() or not, in debug builds it's always
// enabled.
return gDOMWindowDumpEnabled;
#else
return true;
#endif
}
NS_IMETHODIMP
nsGlobalWindow::Dump(const nsAString& aStr)
{
if (!DOMWindowDumpEnabled()) {
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return NS_OK;
}
@ -6232,6 +6211,30 @@ nsGlobalWindow::SetResizable(bool aResizable)
return NS_OK;
}
static void
ReportUseOfDeprecatedMethod(nsGlobalWindow* aWindow, const char* aWarning)
{
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
"DOM Events", doc,
nsContentUtils::eDOM_PROPERTIES,
aWarning);
}
NS_IMETHODIMP
nsGlobalWindow::CaptureEvents(int32_t aEventFlags)
{
ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
return NS_OK;
}
NS_IMETHODIMP
nsGlobalWindow::ReleaseEvents(int32_t aEventFlags)
{
ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
return NS_OK;
}
static
bool IsPopupBlocked(nsIDocument* aDoc)
{

View File

@ -631,8 +631,6 @@ public:
virtual nsresult SetArguments(nsIArray *aArguments);
static bool DOMWindowDumpEnabled();
void MaybeForgiveSpamCount();
bool IsClosedOrClosing() {
return (mIsClosed ||

View File

@ -555,31 +555,31 @@ NS_ScriptErrorReporter(JSContext *cx,
}
}
#ifdef DEBUG
// Print it to stderr as well, for the benefit of those invoking
// mozilla with -console.
nsAutoCString error;
error.Assign("JavaScript ");
if (JSREPORT_IS_STRICT(report->flags))
error.Append("strict ");
if (JSREPORT_IS_WARNING(report->flags))
error.Append("warning: ");
else
error.Append("error: ");
error.Append(report->filename);
error.Append(", line ");
error.AppendInt(report->lineno, 10);
error.Append(": ");
if (report->ucmessage) {
AppendUTF16toUTF8(reinterpret_cast<const PRUnichar*>(report->ucmessage),
error);
} else {
error.Append(message);
}
if (nsContentUtils::DOMWindowDumpEnabled()) {
// Print it to stderr as well, for the benefit of those invoking
// mozilla with -console.
nsAutoCString error;
error.Assign("JavaScript ");
if (JSREPORT_IS_STRICT(report->flags))
error.Append("strict ");
if (JSREPORT_IS_WARNING(report->flags))
error.Append("warning: ");
else
error.Append("error: ");
error.Append(report->filename);
error.Append(", line ");
error.AppendInt(report->lineno, 10);
error.Append(": ");
if (report->ucmessage) {
AppendUTF16toUTF8(reinterpret_cast<const PRUnichar*>(report->ucmessage),
error);
} else {
error.Append(message);
}
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
#endif
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
}
#ifdef PR_LOGGING
if (!gJSDiagnostics)

View File

@ -538,6 +538,18 @@ DOMInterfaces = {
'nativeType' : 'mozilla::dom::HTMLSharedListElement'
},
'IDBCursor': {
'nativeType': 'mozilla::dom::indexedDB::IDBCursor',
'implicitJSContext': [ 'delete' ],
'binaryNames': {
'direction': 'getDirection'
}
},
'IDBCursorWithValue': {
'nativeType': 'mozilla::dom::indexedDB::IDBCursor',
},
'IDBDatabase': {
'nativeType': 'mozilla::dom::indexedDB::IDBDatabase',
},
@ -566,6 +578,15 @@ DOMInterfaces = {
}
},
'IDBOpenDBRequest': {
'nativeType': 'mozilla::dom::indexedDB::IDBOpenDBRequest',
'headerFile': 'IDBRequest.h'
},
'IDBRequest': {
'nativeType': 'mozilla::dom::indexedDB::IDBRequest',
},
'IDBTransaction': {
'nativeType': 'mozilla::dom::indexedDB::IDBTransaction',
},
@ -1679,8 +1700,6 @@ addExternalIface('File')
addExternalIface('FileCallback', nativeType='nsIFileCallback',
headerFile='nsIDOMHTMLCanvasElement.h')
addExternalIface('HitRegionOptions', nativeType='nsISupports')
addExternalIface('IDBOpenDBRequest', nativeType='nsIIDBOpenDBRequest')
addExternalIface('IDBRequest', nativeType='nsIIDBRequest')
addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
addExternalIface('LockedFile')

View File

@ -44,3 +44,4 @@ MSG_DEF(MSG_INVALID_VERSION, 0, "0 (Zero) is not a valid database version.")
MSG_DEF(MSG_INVALID_BYTESTRING, 2, "Cannot convert string to ByteString because the character"
" at index {0} has value {1} which is greater than 255.")
MSG_DEF(MSG_NOT_DATE, 1, "{0} is not a date.")
MSG_DEF(MSG_INVALID_ADVANCE_COUNT, 0, "0 (Zero) is not a valid advance count.")

View File

@ -242,7 +242,9 @@ GARBAGE += \
# headers they depend on. This is really only needed for the test files, since
# the non-test headers are all exported above anyway. Note that this means that
# we do all of our codegen during export.
export:: $(binding_header_files)
webidl: $(binding_header_files)
.PHONY: webidl
distclean::
-$(RM) \
@ -252,3 +254,9 @@ distclean::
$(globalgen_targets) \
ParserResults.pkl \
$(NULL)
# This is only needed to support |make| from this leaf directory/Makefile.
NONRECURSIVE_TARGETS := export
NONRECURSIVE_TARGETS_export := webidl
NONRECURSIVE_TARGETS_export_webidl_DIRECTORY := .
NONRECURSIVE_TARGETS_export_webidl_TARGETS := webidl

View File

@ -119,7 +119,8 @@ HelperBase::WrapNative(JSContext* aCx,
NS_ASSERTION(aResult.address(), "Null pointer!");
NS_ASSERTION(mRequest, "Null request!");
JS::Rooted<JSObject*> global(aCx, mRequest->GetParentObject());
nsRefPtr<IDBWrapperCache> wrapper = static_cast<IDBWrapperCache*>(mRequest);
JS::Rooted<JSObject*> global(aCx, wrapper->GetParentObject());
NS_ASSERTION(global, "This should never be null!");
nsresult rv =

View File

@ -28,9 +28,12 @@
#include "ipc/IndexedDBParent.h"
#include "IndexedDatabaseInlines.h"
#include "mozilla/dom/BindingDeclarations.h"
USING_INDEXEDDB_NAMESPACE
using namespace mozilla::dom::indexedDB::ipc;
using mozilla::dom::Optional;
using mozilla::ErrorResult;
static_assert(sizeof(size_t) >= sizeof(IDBCursor::Direction),
"Relying on conversion between size_t and "
@ -353,6 +356,8 @@ IDBCursor::IDBCursor()
mHaveValue(true)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
SetIsDOMBinding();
}
IDBCursor::~IDBCursor()
@ -388,31 +393,27 @@ IDBCursor::DropJSObjects()
NS_DROP_JS_OBJECTS(this, IDBCursor);
}
nsresult
IDBCursor::ContinueInternal(const Key& aKey,
int32_t aCount)
void
IDBCursor::ContinueInternal(const Key& aKey, int32_t aCount, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aCount > 0, "Must have a count!");
if (!mTransaction->IsOpen()) {
return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
if (!mHaveValue || mContinueCalled) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return;
}
mContinueToKey = aKey;
#ifdef DEBUG
{
nsAutoString readyState;
if (NS_FAILED(mRequest->GetReadyState(readyState))) {
NS_ERROR("This should never fail!");
}
NS_ASSERTION(readyState.EqualsLiteral("done"), "Should be DONE!");
}
NS_ASSERTION(mRequest->ReadyState() == IDBRequestReadyState::Done,
"Should be DONE!");
#endif
mRequest->Reset();
@ -436,10 +437,13 @@ IDBCursor::ContinueInternal(const Key& aKey,
}
nsresult rv = helper->DispatchToTransactionPool();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch!");
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return;
}
mContinueCalled = true;
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
@ -451,6 +455,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_ASSERTION(tmp->mHaveCachedKey || JSVAL_IS_VOID(tmp->mCachedKey),
"Should have a cached key");
NS_ASSERTION(tmp->mHaveCachedPrimaryKey ||
@ -465,76 +470,79 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
// Don't unlink mObjectStore, mIndex, or mTransaction!
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
NS_INTERFACE_MAP_ENTRY(nsIIDBCursor)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIDBCursorWithValue, mType != INDEXKEY)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursorWithValue,
mType != INDEXKEY)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursor,
mType == INDEXKEY)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
DOMCI_DATA(IDBCursor, IDBCursor)
DOMCI_DATA(IDBCursorWithValue, IDBCursor)
JSObject*
IDBCursor::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return mType != INDEXKEY
? IDBCursorWithValueBinding::Wrap(aCx, aScope, this)
: IDBCursorBinding::Wrap(aCx, aScope, this);
}
NS_IMETHODIMP
IDBCursor::GetDirection(nsAString& aDirection)
mozilla::dom::IDBCursorDirection
IDBCursor::GetDirection() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
switch (mDirection) {
case NEXT:
aDirection.AssignLiteral("next");
break;
return mozilla::dom::IDBCursorDirection::Next;
case NEXT_UNIQUE:
aDirection.AssignLiteral("nextunique");
break;
return mozilla::dom::IDBCursorDirection::Nextunique;
case PREV:
aDirection.AssignLiteral("prev");
break;
return mozilla::dom::IDBCursorDirection::Prev;
case PREV_UNIQUE:
aDirection.AssignLiteral("prevunique");
break;
return mozilla::dom::IDBCursorDirection::Prevunique;
case DIRECTION_INVALID:
default:
NS_NOTREACHED("Bad direction value!");
return NS_ERROR_UNEXPECTED;
MOZ_CRASH("Unknown direction!");
return mozilla::dom::IDBCursorDirection::Next;
}
return NS_OK;
}
NS_IMETHODIMP
IDBCursor::GetSource(nsISupports** aSource)
already_AddRefed<nsISupports>
IDBCursor::Source() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mType == OBJECTSTORE ?
CallQueryInterface(mObjectStore, aSource) :
CallQueryInterface(mIndex, aSource);
nsCOMPtr<nsISupports> source;
if (mType == OBJECTSTORE) {
source = do_QueryInterface(mObjectStore);
}
else {
source = do_QueryInterface(mIndex);
}
return source.forget();
}
NS_IMETHODIMP
IDBCursor::GetKey(JSContext* aCx,
jsval* aKey)
JS::Value
IDBCursor::GetKey(JSContext* aCx, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!");
if (!mHaveValue) {
*aKey = JSVAL_VOID;
return NS_OK;
return JSVAL_VOID;
}
if (!mHaveCachedKey) {
@ -543,25 +551,22 @@ IDBCursor::GetKey(JSContext* aCx,
mRooted = true;
}
nsresult rv = mKey.ToJSVal(aCx, mCachedKey);
NS_ENSURE_SUCCESS(rv, rv);
aRv = mKey.ToJSVal(aCx, mCachedKey);
ENSURE_SUCCESS(aRv, JSVAL_VOID);
mHaveCachedKey = true;
}
*aKey = mCachedKey;
return NS_OK;
return mCachedKey;
}
NS_IMETHODIMP
IDBCursor::GetPrimaryKey(JSContext* aCx,
jsval* aValue)
JS::Value
IDBCursor::GetPrimaryKey(JSContext* aCx, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mHaveValue) {
*aValue = JSVAL_VOID;
return NS_OK;
return JSVAL_VOID;
}
if (!mHaveCachedPrimaryKey) {
@ -577,26 +582,23 @@ IDBCursor::GetPrimaryKey(JSContext* aCx,
const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey;
nsresult rv = key.ToJSVal(aCx, mCachedPrimaryKey);
NS_ENSURE_SUCCESS(rv, rv);
aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
ENSURE_SUCCESS(aRv, JSVAL_VOID);
mHaveCachedPrimaryKey = true;
}
*aValue = mCachedPrimaryKey;
return NS_OK;
return mCachedPrimaryKey;
}
NS_IMETHODIMP
IDBCursor::GetValue(JSContext* aCx,
jsval* aValue)
JS::Value
IDBCursor::GetValue(JSContext* aCx, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mType != INDEXKEY, "GetValue shouldn't exist on index keys");
if (!mHaveValue) {
*aValue = JSVAL_VOID;
return NS_OK;
return JSVAL_VOID;
}
if (!mHaveCachedValue) {
@ -607,7 +609,8 @@ IDBCursor::GetValue(JSContext* aCx,
JS::Rooted<JS::Value> val(aCx);
if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, &val)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return JSVAL_VOID;
}
mCloneReadInfo.mCloneBuffer.clear();
@ -616,33 +619,37 @@ IDBCursor::GetValue(JSContext* aCx,
mHaveCachedValue = true;
}
*aValue = mCachedValue;
return NS_OK;
return mCachedValue;
}
NS_IMETHODIMP
IDBCursor::Continue(const jsval& aKey,
JSContext* aCx)
void
IDBCursor::Continue(JSContext* aCx,
const Optional<JS::Handle<JS::Value> >& aKey,
ErrorResult &aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
Key key;
nsresult rv = key.SetFromJSVal(aCx, aKey);
NS_ENSURE_SUCCESS(rv, rv);
if (aKey.WasPassed()) {
aRv = key.SetFromJSVal(aCx, aKey.Value());
ENSURE_SUCCESS_VOID(aRv);
}
if (!key.IsUnset()) {
switch (mDirection) {
case IDBCursor::NEXT:
case IDBCursor::NEXT_UNIQUE:
if (key <= mKey) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
case IDBCursor::PREV:
case IDBCursor::PREV_UNIQUE:
if (key >= mKey) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
@ -651,9 +658,9 @@ IDBCursor::Continue(const jsval& aKey,
}
}
rv = ContinueInternal(key, 1);
if (NS_FAILED(rv)) {
return rv;
ContinueInternal(key, 1, aRv);
if (aRv.Failed()) {
return;
}
#ifdef IDB_PROFILER_USE_MARKS
@ -683,73 +690,70 @@ IDBCursor::Continue(const jsval& aKey,
key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
}
#endif
return NS_OK;
}
NS_IMETHODIMP
IDBCursor::Update(const jsval& aValue,
JSContext* aCx,
nsIIDBRequest** _retval)
already_AddRefed<IDBRequest>
IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mTransaction->IsOpen()) {
return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return nullptr;
}
if (!mTransaction->IsWriteAllowed()) {
return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
return nullptr;
}
if (!mHaveValue || mType == INDEXKEY) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return nullptr;
}
NS_ASSERTION(mObjectStore, "This cannot be null!");
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!");
nsresult rv;
JSAutoRequest ar(aCx);
Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
nsCOMPtr<nsIIDBRequest> request;
nsRefPtr<IDBRequest> request;
if (mObjectStore->HasValidKeyPath()) {
// Make sure the object given has the correct keyPath value set on it.
const KeyPath& keyPath = mObjectStore->GetKeyPath();
Key key;
rv = keyPath.ExtractKey(aCx, aValue, key);
if (NS_FAILED(rv)) {
return rv;
aRv = keyPath.ExtractKey(aCx, aValue, key);
if (aRv.Failed()) {
return nullptr;
}
if (key != objectKey) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return nullptr;
}
ErrorResult error;
JS::Rooted<JS::Value> value(aCx, aValue);
Optional<JS::Handle<JS::Value> > keyValue(aCx);
request = mObjectStore->Put(aCx, value, keyValue, error);
if (error.Failed()) {
return error.ErrorCode();
request = mObjectStore->Put(aCx, value, keyValue, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
else {
JS::Rooted<JS::Value> keyVal(aCx);
rv = objectKey.ToJSVal(aCx, &keyVal);
NS_ENSURE_SUCCESS(rv, rv);
aRv = objectKey.ToJSVal(aCx, &keyVal);
ENSURE_SUCCESS(aRv, nullptr);
ErrorResult error;
JS::Rooted<JS::Value> value(aCx, aValue);
Optional<JS::Handle<JS::Value> > keyValue(aCx, keyVal);
request = mObjectStore->Put(aCx, value, keyValue, error);
if (error.Failed()) {
return error.ErrorCode();
request = mObjectStore->Put(aCx, value, keyValue, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
@ -787,26 +791,27 @@ IDBCursor::Update(const jsval& aValue,
}
#endif
request.forget(_retval);
return NS_OK;
return request.forget();
}
NS_IMETHODIMP
IDBCursor::Delete(JSContext* aCx,
nsIIDBRequest** _retval)
already_AddRefed<IDBRequest>
IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mTransaction->IsOpen()) {
return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return nullptr;
}
if (!mTransaction->IsWriteAllowed()) {
return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
return nullptr;
}
if (!mHaveValue || mType == INDEXKEY) {
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return nullptr;
}
NS_ASSERTION(mObjectStore, "This cannot be null!");
@ -815,19 +820,17 @@ IDBCursor::Delete(JSContext* aCx,
Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
JS::Rooted<JS::Value> key(aCx);
nsresult rv = objectKey.ToJSVal(aCx, &key);
NS_ENSURE_SUCCESS(rv, rv);
aRv = objectKey.ToJSVal(aCx, &key);
ENSURE_SUCCESS(aRv, nullptr);
ErrorResult error;
nsCOMPtr<nsIIDBRequest> request = mObjectStore->Delete(aCx, key, error);
if (error.Failed()) {
return error.ErrorCode();
nsRefPtr<IDBRequest> request = mObjectStore->Delete(aCx, key, aRv);
if (aRv.Failed()) {
return nullptr;
}
#ifdef IDB_PROFILER_USE_MARKS
{
uint64_t requestSerial =
static_cast<IDBRequest*>(request.get())->GetSerialNumber();
uint64_t requestSerial = request->GetSerialNumber();
if (mType == OBJECTSTORE) {
IDB_PROFILER_MARK("IndexedDB Request %llu: "
"database(%s).transaction(%s).objectStore(%s)."
@ -858,24 +861,22 @@ IDBCursor::Delete(JSContext* aCx,
}
#endif
request.forget(_retval);
return NS_OK;
return request.forget();
}
NS_IMETHODIMP
IDBCursor::Advance(int64_t aCount)
void
IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (aCount < 1 || aCount > UINT32_MAX) {
return NS_ERROR_TYPE_ERR;
if (aCount < 1) {
aRv.ThrowTypeError(MSG_INVALID_ADVANCE_COUNT);
return;
}
Key key;
nsresult rv = ContinueInternal(key, int32_t(aCount));
if (NS_FAILED(rv)) {
return rv;
}
ContinueInternal(key, int32_t(aCount), aRv);
ENSURE_SUCCESS_VOID(aRv);
#ifdef IDB_PROFILER_USE_MARKS
{
@ -904,8 +905,6 @@ IDBCursor::Advance(int64_t aCount)
}
}
#endif
return NS_OK;
}
void

View File

@ -9,15 +9,15 @@
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsIIDBCursorWithValue.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/IDBCursorBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/Key.h"
class nsIRunnable;
class nsIScriptContext;
class nsPIDOMWindow;
@ -34,7 +34,8 @@ class IDBTransaction;
class IndexedDBCursorChild;
class IndexedDBCursorParent;
class IDBCursor MOZ_FINAL : public nsIIDBCursorWithValue
class IDBCursor MOZ_FINAL : public nsISupports,
public nsWrapperCache
{
friend class ContinueHelper;
friend class ContinueObjectStoreHelper;
@ -43,9 +44,6 @@ class IDBCursor MOZ_FINAL : public nsIIDBCursorWithValue
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIIDBCURSOR
NS_DECL_NSIIDBCURSORWITHVALUE
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
enum Type
@ -146,9 +144,48 @@ public:
return mActorParent;
}
nsresult
ContinueInternal(const Key& aKey,
int32_t aCount);
void
ContinueInternal(const Key& aKey, int32_t aCount,
ErrorResult& aRv);
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// WebIDL
IDBTransaction*
GetParentObject() const
{
return mTransaction;
}
already_AddRefed<nsISupports>
Source() const;
IDBCursorDirection
GetDirection() const;
JS::Value
GetKey(JSContext* aCx, ErrorResult& aRv);
JS::Value
GetPrimaryKey(JSContext* aCx, ErrorResult& aRv);
already_AddRefed<IDBRequest>
Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
void
Advance(uint32_t aCount, ErrorResult& aRv);
void
Continue(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
ErrorResult& aRv);
already_AddRefed<IDBRequest>
Delete(JSContext* aCx, ErrorResult& aRv);
JS::Value
GetValue(JSContext* aCx, ErrorResult& aRv);
protected:
IDBCursor();

View File

@ -645,7 +645,7 @@ IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
return Key::CompareKeys(first, second);
}
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aName,
const Optional<uint64_t>& aVersion,
@ -659,7 +659,7 @@ IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
return Open(aPrincipal, aName, aVersion, false, aRv);
}
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aName,
ErrorResult& aRv)
@ -672,7 +672,7 @@ IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
return Open(aPrincipal, aName, Optional<uint64_t>(), true, aRv);
}
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
IDBFactory::Open(nsIPrincipal* aPrincipal,
const nsAString& aName, const Optional<uint64_t>& aVersion,
bool aDelete, ErrorResult& aRv)

View File

@ -18,7 +18,6 @@
class nsIAtom;
class nsIFile;
class nsIFileURL;
class nsIIDBOpenDBRequest;
class nsPIDOMWindow;
namespace mozilla {
@ -140,14 +139,14 @@ public:
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// WebIDL
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
Open(const nsAString& aName, const Optional<uint64_t>& aVersion,
ErrorResult& aRv)
{
return Open(nullptr, aName, aVersion, false, aRv);
}
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
DeleteDatabase(const nsAString& aName, ErrorResult& aRv)
{
return Open(nullptr, aName, Optional<uint64_t>(), true, aRv);
@ -157,11 +156,11 @@ public:
Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
JS::Handle<JS::Value> aSecond, ErrorResult& aRv);
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
const Optional<uint64_t>& aVersion, ErrorResult& aRv);
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
ErrorResult& aRv);
@ -169,7 +168,7 @@ private:
IDBFactory();
~IDBFactory();
already_AddRefed<nsIIDBOpenDBRequest>
already_AddRefed<IDBOpenDBRequest>
Open(nsIPrincipal* aPrincipal, const nsAString& aName,
const Optional<uint64_t>& aVersion, bool aDelete, ErrorResult& aRv);

View File

@ -8,6 +8,7 @@
#include "nsIScriptContext.h"
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
#include "nsComponentManagerUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMJSUtils.h"
@ -46,6 +47,8 @@ IDBRequest::IDBRequest()
mHaveResultOrErrorCode(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
SetIsDOMBinding();
}
IDBRequest::~IDBRequest()
@ -113,7 +116,7 @@ IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
return rv;
}
JS::Rooted<JSObject*> global(cx, GetParentObject());
JS::Rooted<JSObject*> global(cx, IDBWrapperCache::GetParentObject());
NS_ASSERTION(global, "This should never be null!");
JSAutoCompartment ac(cx, global);
@ -229,53 +232,35 @@ IDBRequest::FillScriptErrorEvent(nsScriptErrorEvent* aEvent) const
aEvent->fileName = mFilename.get();
}
NS_IMETHODIMP
IDBRequest::GetReadyState(nsAString& aReadyState)
mozilla::dom::IDBRequestReadyState
IDBRequest::ReadyState() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (IsPending()) {
aReadyState.AssignLiteral("pending");
}
else {
aReadyState.AssignLiteral("done");
return IDBRequestReadyState::Pending;
}
return NS_OK;
return IDBRequestReadyState::Done;
}
NS_IMETHODIMP
IDBRequest::GetSource(nsISupports** aSource)
JSObject*
IDBRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsISupports> source(mSource);
source.forget(aSource);
return NS_OK;
return IDBRequestBinding::Wrap(aCx, aScope, this);
}
NS_IMETHODIMP
IDBRequest::GetTransaction(nsISupports** aTransaction)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<IDBWrapperCache> transaction(mTransaction);
transaction.forget(aTransaction);
return NS_OK;
}
NS_IMETHODIMP
IDBRequest::GetResult(jsval* aResult)
JS::Value
IDBRequest::GetResult(JSContext* aCx, mozilla::ErrorResult& aRv) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (!mHaveResultOrErrorCode) {
// XXX Need a real error code here.
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
}
*aResult = mResultVal;
return NS_OK;
return mResultVal;
}
mozilla::dom::DOMError*
@ -291,15 +276,6 @@ IDBRequest::GetError(mozilla::ErrorResult& aRv)
return mError;
}
NS_IMETHODIMP
IDBRequest::GetError(nsISupports** aError)
{
ErrorResult rv;
*aError = GetError(rv);
NS_IF_ADDREF(*aError);
return rv.ErrorCode();
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
// Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because
// nsDOMEventTargetHelper does it for us.
@ -322,18 +298,11 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBRequest)
NS_INTERFACE_MAP_ENTRY(nsIIDBRequest)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBRequest)
NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
NS_IMPL_ADDREF_INHERITED(IDBRequest, IDBWrapperCache)
NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
DOMCI_DATA(IDBRequest, IDBRequest)
NS_IMPL_EVENT_HANDLER(IDBRequest, success)
NS_IMPL_EVENT_HANDLER(IDBRequest, error)
nsresult
IDBRequest::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
@ -344,6 +313,13 @@ IDBRequest::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
return NS_OK;
}
IDBOpenDBRequest::IDBOpenDBRequest()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
SetIsDOMBinding();
}
IDBOpenDBRequest::~IDBOpenDBRequest()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -390,20 +366,19 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBOpenDBRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBOpenDBRequest)
NS_INTERFACE_MAP_ENTRY(nsIIDBOpenDBRequest)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBOpenDBRequest)
NS_INTERFACE_MAP_END_INHERITING(IDBRequest)
NS_IMPL_ADDREF_INHERITED(IDBOpenDBRequest, IDBRequest)
NS_IMPL_RELEASE_INHERITED(IDBOpenDBRequest, IDBRequest)
DOMCI_DATA(IDBOpenDBRequest, IDBOpenDBRequest)
NS_IMPL_EVENT_HANDLER(IDBOpenDBRequest, blocked)
NS_IMPL_EVENT_HANDLER(IDBOpenDBRequest, upgradeneeded)
nsresult
IDBOpenDBRequest::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
return IndexedDatabaseManager::FireWindowOnError(GetOwner(), aVisitor);
}
JSObject*
IDBOpenDBRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return IDBOpenDBRequestBinding::Wrap(aCx, aScope, this);
}

View File

@ -7,14 +7,16 @@
#ifndef mozilla_dom_indexeddb_idbrequest_h__
#define mozilla_dom_indexeddb_idbrequest_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "nsIIDBRequest.h"
#include "nsIIDBOpenDBRequest.h"
#include "nsDOMEventTargetHelper.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/IDBRequestBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
class nsIScriptContext;
class nsPIDOMWindow;
@ -26,12 +28,10 @@ class IDBFactory;
class IDBTransaction;
class IndexedDBRequestParentBase;
class IDBRequest : public IDBWrapperCache,
public nsIIDBRequest
class IDBRequest : public IDBWrapperCache
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIIDBREQUEST
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(IDBRequest,
IDBWrapperCache)
@ -101,6 +101,40 @@ public:
}
#endif
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// WebIDL
nsPIDOMWindow*
GetParentObject() const
{
return GetOwner();
}
JS::Value
GetResult(JSContext* aCx, ErrorResult& aRv) const;
nsISupports*
GetSource() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mSource;
}
IDBTransaction*
GetTransaction() const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mTransaction;
}
IDBRequestReadyState
ReadyState() const;
IMPL_EVENT_HANDLER(success);
IMPL_EVENT_HANDLER(error);
protected:
IDBRequest();
~IDBRequest();
@ -120,13 +154,10 @@ protected:
bool mHaveResultOrErrorCode;
};
class IDBOpenDBRequest : public IDBRequest,
public nsIIDBOpenDBRequest
class IDBOpenDBRequest : public IDBRequest
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_NSIIDBREQUEST(IDBRequest::)
NS_DECL_NSIIDBOPENDBREQUEST
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
static
@ -151,7 +182,16 @@ public:
return mFactory;
}
// nsWrapperCache
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// WebIDL
IMPL_EVENT_HANDLER(blocked);
IMPL_EVENT_HANDLER(upgradeneeded);
protected:
IDBOpenDBRequest();
~IDBOpenDBRequest();
// Only touched on the main thread.

View File

@ -276,8 +276,7 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
nsCOMPtr<EventTarget> eventTarget =
aVisitor.mDOMEvent->InternalDOMEvent()->GetTarget();
nsCOMPtr<nsIIDBRequest> strongRequest = do_QueryInterface(eventTarget);
IDBRequest* request = static_cast<IDBRequest*>(strongRequest.get());
IDBRequest* request = static_cast<IDBRequest*>(eventTarget.get());
NS_ENSURE_TRUE(request, NS_ERROR_UNEXPECTED);
ErrorResult ret;

View File

@ -383,9 +383,9 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
AutoSafeJSContext cx;
JS::Rooted<JS::Value> result(cx);
rv = mOpenRequest->GetResult(result.address());
NS_ENSURE_SUCCESS(rv, rv);
ErrorResult error;
JS::Rooted<JS::Value> result(cx, mOpenRequest->GetResult(cx, error));
ENSURE_SUCCESS(error, error.ErrorCode());
MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(result));
@ -2044,8 +2044,9 @@ IndexedDBCursorRequestParent::Continue(const ContinueParams& aParams)
{
AutoSetCurrentTransaction asct(mCursor->Transaction());
nsresult rv = mCursor->ContinueInternal(aParams.key(), aParams.count());
NS_ENSURE_SUCCESS(rv, false);
ErrorResult rv;
mCursor->ContinueInternal(aParams.key(), aParams.count(), rv);
ENSURE_SUCCESS(rv, false);
}
mRequest = mCursor->Request();

View File

@ -8,11 +8,7 @@ DIRS += ['ipc']
TEST_DIRS += ['test']
XPIDL_SOURCES += [
'nsIIDBCursor.idl',
'nsIIDBCursorWithValue.idl',
'nsIIDBKeyRange.idl',
'nsIIDBOpenDBRequest.idl',
'nsIIDBRequest.idl',
'nsIIndexedDatabaseManager.idl',
]

View File

@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIIDBRequest;
/**
* IDBCursor interface. See
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
* information.
*/
[scriptable, builtinclass, uuid(148579a3-6b28-4b2a-92c3-ff5719e8e03e)]
interface nsIIDBCursor : nsISupports
{
// "next", "nextunique", "prev" or "prevunique"
readonly attribute DOMString direction;
readonly attribute nsISupports source;
[implicit_jscontext]
readonly attribute jsval key;
[implicit_jscontext]
readonly attribute jsval primaryKey;
// Calling continue means that the same onsuccess function will be called
// again with the new key/value (or null if no more matches).
[implicit_jscontext]
void continue([optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == key
[implicit_jscontext]
nsIIDBRequest update(in jsval value);
// Success fires IDBTransactionEvent, result == null
[implicit_jscontext]
nsIIDBRequest delete();
void
advance(in long long count);
};

View File

@ -1,19 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIIDBCursor.idl"
/**
* IDBCursor interface. See
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
* information.
*/
[scriptable, builtinclass, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)]
interface nsIIDBCursorWithValue : nsIIDBCursor
{
[implicit_jscontext]
readonly attribute jsval value;
};

View File

@ -1,21 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIDOMEventListener;
/**
* IDBOpenDBRequest interface. See
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBOpenDBRequest
* for more information.
*/
[scriptable, builtinclass, uuid(2d6c5ef4-b84a-45ae-9030-eb6cfc65bb26)]
interface nsIIDBOpenDBRequest : nsISupports
{
[implicit_jscontext] attribute jsval onblocked;
[implicit_jscontext] attribute jsval onupgradeneeded;
};

View File

@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIDOMEventListener;
/**
* IDBRequest interface. See
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBRequest for more
* information.
*/
[scriptable, builtinclass, uuid(4d1e9ee3-4bd0-4c99-9e6a-19cb536ab6d4)]
interface nsIIDBRequest : nsISupports
{
readonly attribute jsval result;
// This is a DOMError
readonly attribute nsISupports error;
readonly attribute nsISupports source;
// This is a nsIIDBTransaction
readonly attribute nsISupports transaction;
// "pending" or "done"
readonly attribute DOMString readyState;
[implicit_jscontext] attribute jsval onsuccess;
[implicit_jscontext] attribute jsval onerror;
};

View File

@ -6,9 +6,6 @@
const { 'classes': Cc, 'interfaces': Ci } = Components;
const DOMException = Ci.nsIDOMDOMException;
const IDBCursor = Ci.nsIIDBCursor;
const IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
const IDBRequest = Ci.nsIIDBRequest
function is(a, b, msg) {
dump("is(" + a + ", " + b + ", \"" + msg + "\")");

View File

@ -16,6 +16,7 @@ XPIDL_SOURCES += [
'nsIDOMClientRect.idl',
'nsIDOMClientRectList.idl',
'nsIDOMConstructor.idl',
'nsIDOMGlobalObjectConstructor.idl',
'nsIDOMGlobalPropertyInitializer.idl',
'nsIDOMHistory.idl',
'nsIDOMJSWindow.idl',

View File

@ -0,0 +1,19 @@
/* -*- 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 "domstubs.idl"
[scriptable, uuid(cb439c73-0129-4289-a349-c5216e6b912a)]
interface nsIDOMGlobalObjectConstructor : nsISupports
{
/*
* JS use only
*
* The constructor() method will be called with any parameters passed
* to the object constructor.
* If the JS implementation returns a value, it will be ignored.
*/
void constructor();
};

View File

@ -5,7 +5,7 @@
#include "domstubs.idl"
[scriptable, uuid(f28c92a2-302a-4448-b589-46af599de352)]
[scriptable, uuid(5a9689e8-5822-4dd5-b231-609b8d0260ab)]
interface nsIDOMJSWindow : nsISupports
{
void dump(in DOMString str);
@ -33,6 +33,13 @@ interface nsIDOMJSWindow : nsISupports
*/
void setResizable(in boolean resizable);
/**
* @deprecated These are old Netscape 4 methods. Do not use,
* the implementation is no-op.
*/
void captureEvents(in long eventFlags);
void releaseEvents(in long eventFlags);
/**
* This is the scriptable version of nsIDOMWindow::open()
* that takes 3 optional arguments. Its binary name is OpenJS to

View File

@ -13,7 +13,7 @@
*/
interface nsISelection;
[scriptable, uuid(cb0cc619-5862-4e00-86d3-dca3c6ecc34b)]
[scriptable, uuid(a3efb7eb-ae02-447b-99a5-bebca100afbd)]
interface nsIDOMHTMLDocument : nsIDOMDocument
{
attribute DOMString domain;
@ -88,4 +88,13 @@ interface nsIDOMHTMLDocument : nsIDOMDocument
// DOM Range
nsISelection getSelection();
// Mozilla extensions
/**
* @deprecated These are old Netscape 4 methods. Do not use,
* the implementation is no-op.
*/
void captureEvents(in long eventFlags);
void releaseEvents(in long eventFlags);
};

View File

@ -16,6 +16,8 @@ OnBeforeUnloadTitle=Are you sure?
OnBeforeUnloadMessage=This page is asking you to confirm that you want to leave - data you have entered may not be saved.
OnBeforeUnloadStayButton=Stay on Page
OnBeforeUnloadLeaveButton=Leave Page
UseOfCaptureEventsWarning=Use of captureEvents() is deprecated. To upgrade your code, use the DOM 2 addEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.addEventListener
UseOfReleaseEventsWarning=Use of releaseEvents() is deprecated. To upgrade your code, use the DOM 2 removeEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.removeEventListener
UseOfDOM3LoadMethodWarning=Use of Document.load() is deprecated. To upgrade your code, use the DOM XMLHttpRequest object. For more help https://developer.mozilla.org/en/XMLHttpRequest
UnexpectedCanvasVariantStyle=canvas: an attempt to set strokeStyle or fillStyle to a value that is neither a string, a CanvasGradient, or a CanvasPattern was ignored.
EmptyGetElementByIdParam=Empty string passed to getElementById().

View File

@ -71,4 +71,10 @@ interface HTMLDocument : Document {
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
[Throws]
Selection getSelection();
// @deprecated These are old Netscape 4 methods. Do not use,
// the implementation is no-op.
// XXXbz do we actually need these anymore?
void captureEvents(long eventFlags);
void releaseEvents(long eventFlags);
};

View File

@ -13,3 +13,33 @@ enum IDBCursorDirection {
"prev",
"prevunique"
};
interface IDBCursor {
// This should be: readonly attribute (IDBObjectStore or IDBIndex) source;
readonly attribute nsISupports source;
readonly attribute IDBCursorDirection direction;
[Throws]
readonly attribute any key;
[Throws]
readonly attribute any primaryKey;
[Throws]
IDBRequest update (any value);
[Throws]
void advance ([EnforceRange] unsigned long count);
[Throws]
void continue (optional any key);
[Throws]
IDBRequest delete ();
};
interface IDBCursorWithValue : IDBCursor {
[Throws]
readonly attribute any value;
};

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
interface IDBOpenDBRequest;
interface Principal;
/**

View File

@ -7,8 +7,6 @@
* https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBObjectStore
*/
interface IDBRequest;
dictionary IDBObjectStoreParameters {
// TODO (DOMString or sequence<DOMString>)? keyPath = null;
any keyPath = null;

View File

@ -0,0 +1,16 @@
/* -*- 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/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBOpenDBRequest
*/
interface IDBOpenDBRequest : IDBRequest {
[SetterThrows]
attribute EventHandler onblocked;
[SetterThrows]
attribute EventHandler onupgradeneeded;
};

View File

@ -0,0 +1,32 @@
/* -*- 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/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBRequest
* https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBRequestReadyState
*/
enum IDBRequestReadyState {
"pending",
"done"
};
interface IDBRequest : EventTarget {
[Throws]
readonly attribute any result;
[Throws]
readonly attribute DOMError? error;
readonly attribute nsISupports? source;
readonly attribute IDBTransaction? transaction;
readonly attribute IDBRequestReadyState readyState;
[SetterThrows]
attribute EventHandler onsuccess;
[SetterThrows]
attribute EventHandler onerror;
};

View File

@ -170,6 +170,8 @@ webidl_files = \
IDBFileHandle.webidl \
IDBIndex.webidl \
IDBObjectStore.webidl \
IDBOpenDBRequest.webidl \
IDBRequest.webidl \
IDBTransaction.webidl \
IDBVersionChangeEvent.webidl \
ImageData.webidl \

View File

@ -1126,7 +1126,7 @@ public:
}
}
if (!logged) {
if (!logged || nsContentUtils::DOMWindowDumpEnabled()) {
NS_ConvertUTF16toUTF8 msg(aMessage);
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", msg.get());

File diff suppressed because it is too large Load Diff

View File

@ -74,13 +74,8 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
}
if (mGLContext) {
if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
MOZ_ASSERT(false, "Destination surface must be ImageSurface type.");
return;
}
nsRefPtr<gfxImageSurface> readSurf;
nsRefPtr<gfxImageSurface> resultSurf;
nsRefPtr<gfxASurface> resultSurf;
SharedSurface* sharedSurf = mGLContext->RequestFrame();
if (!sharedSurf) {
@ -94,7 +89,7 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
: gfxASurface::ImageFormatARGB32;
if (aDestSurface) {
resultSurf = static_cast<gfxImageSurface*>(aDestSurface);
resultSurf = aDestSurface;
} else {
resultSurf = GetTempSurface(readSize, format);
}
@ -111,11 +106,10 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
readSurf = sharedSurf_Basic->GetData();
} else {
if (resultSurf->Format() == format &&
resultSurf->GetSize() == readSize)
if (resultSurf->GetSize() != readSize ||
!(readSurf = resultSurf->GetAsImageSurface()) ||
readSurf->Format() != format)
{
readSurf = resultSurf;
} else {
readSurf = GetTempSurface(readSize, format);
}
@ -126,28 +120,12 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
if (needsPremult) {
gfxImageSurface* sizedReadSurf = nullptr;
if (readSurf->Format() == resultSurf->Format() &&
readSurf->GetSize() == resultSurf->GetSize())
{
sizedReadSurf = readSurf;
} else {
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(readSurf);
ctx->Paint();
sizedReadSurf = resultSurf;
}
MOZ_ASSERT(sizedReadSurf);
readSurf->Flush();
resultSurf->Flush();
gfxUtils::PremultiplyImageSurface(readSurf, resultSurf);
resultSurf->MarkDirty();
} else if (resultSurf != readSurf) {
// Didn't need premult, but we do need to blit to resultSurf
gfxUtils::PremultiplyImageSurface(readSurf);
readSurf->MarkDirty();
}
if (readSurf != resultSurf) {
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
@ -155,7 +133,8 @@ CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
ctx->Paint();
}
// stick our surface into mSurface, so that the Paint() path is the same
// If !aDestSurface then we will end up painting using mSurface, so
// stick our surface into mSurface, so that the Paint() path is the same.
if (!aDestSurface) {
mSurface = resultSurf;
}

View File

@ -66,7 +66,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
: gfxASurface::CONTENT_COLOR_ALPHA;
mDeprecatedTextureClient->EnsureAllocated(aSize, contentType);
gfxASurface* surface = mDeprecatedTextureClient->LockImageSurface();
gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
aLayer->UpdateSurface(surface);
mDeprecatedTextureClient->Unlock();
}

View File

@ -32,6 +32,11 @@ using namespace std;
namespace mozilla {
namespace layers {
CompositorParent::LayerTreeState::LayerTreeState()
: mParent(nullptr)
{
}
typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
static LayerTreeMap sIndirectLayerTrees;
@ -912,9 +917,9 @@ CrossProcessCompositorParent::AllocPLayerTransactionParent(const LayersBackend&
MOZ_ASSERT(aId != 0);
if (sIndirectLayerTrees[aId].mParent) {
nsRefPtr<LayerManager> lm = sIndirectLayerTrees[aId].mParent->GetLayerManager();
LayerManagerComposite* lm = sIndirectLayerTrees[aId].mParent->GetLayerManager();
*aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier();
return new LayerTransactionParent(lm->AsLayerManagerComposite(), this, aId);
return new LayerTransactionParent(lm, this, aId);
}
NS_WARNING("Created child without a matching parent?");

View File

@ -177,9 +177,10 @@ public:
PlatformThreadId aThreadID);
struct LayerTreeState {
LayerTreeState();
nsRefPtr<Layer> mRoot;
nsRefPtr<GeckoContentController> mController;
CompositorParent *mParent;
CompositorParent* mParent;
TargetConfig mTargetConfig;
};

View File

@ -31,7 +31,7 @@ include $(topsrcdir)/ipc/chromium/chromium-config.mk
# NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
# which is why we don't have explicit .h/.cpp targets here
export:: $(ALL_IPDLSRCS)
ipdl: $(ALL_IPDLSRCS)
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) \
$(srcdir)/ipdl.py \
@ -40,6 +40,14 @@ export:: $(ALL_IPDLSRCS)
$(IPDLDIRS:%=-I%) \
$^
.PHONY: ipdl
# We #include some things in the dom/plugins/ directory that rely on
# toolkit libraries.
CXXFLAGS += $(TK_CFLAGS)
# This is only needed to support |make| from this leaf directory/Makefile.
NONRECURSIVE_TARGETS := export
NONRECURSIVE_TARGETS_export := ipdl
NONRECURSIVE_TARGETS_export_ipdl_DIRECTORY := .
NONRECURSIVE_TARGETS_export_ipdl_TARGETS := ipdl

View File

@ -91,7 +91,7 @@ JavaScriptChild::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
if (!objects_.add(id, obj))
return false;
if (!ids_.add(obj, id))
if (!ids_.add(cx, obj, id))
return false;
*idp = id;

View File

@ -29,9 +29,9 @@ void
ObjectStore::trace(JSTracer *trc)
{
for (ObjectTable::Range r(table_.all()); !r.empty(); r.popFront()) {
JSObject *obj = r.front().value;
JS_CallObjectTracer(trc, &obj, "ipc-object");
MOZ_ASSERT(obj == r.front().value);
DebugOnly<JSObject *> prior = r.front().value.get();
JS_CallHeapObjectTracer(trc, &r.front().value, "ipc-object");
MOZ_ASSERT(r.front().value == prior);
}
}
@ -87,9 +87,25 @@ ObjectIdCache::find(JSObject *obj)
}
bool
ObjectIdCache::add(JSObject *obj, ObjectId id)
ObjectIdCache::add(JSContext *cx, JSObject *obj, ObjectId id)
{
return table_.put(obj, id);
if (!table_.put(obj, id))
return false;
JS_StoreObjectPostBarrierCallback(cx, keyMarkCallback, obj, this);
return true;
}
/*
* This function is called during minor GCs for each key in the HashMap that has
* been moved.
*/
/* static */ void
ObjectIdCache::keyMarkCallback(JSTracer *trc, void *k, void *d) {
JSObject *key = static_cast<JSObject*>(k);
ObjectIdCache* self = static_cast<ObjectIdCache*>(d);
JSObject *prior = key;
JS_CallObjectTracer(trc, &key, "ObjectIdCache::table_ key");
self->table_.rekey(prior, key);
}
void

View File

@ -44,7 +44,7 @@ class ObjectStore
{
typedef js::DefaultHasher<ObjectId> TableKeyHasher;
typedef js::HashMap<ObjectId, JSObject *, TableKeyHasher, js::SystemAllocPolicy> ObjectTable;
typedef js::HashMap<ObjectId, JS::Heap<JSObject *>, TableKeyHasher, js::SystemAllocPolicy> ObjectTable;
public:
ObjectStore();
@ -72,11 +72,13 @@ class ObjectIdCache
bool init();
void trace(JSTracer *trc);
bool add(JSObject *, ObjectId id);
bool add(JSContext *cx, JSObject *obj, ObjectId id);
ObjectId find(JSObject *obj);
void remove(JSObject *obj);
private:
static void keyMarkCallback(JSTracer *trc, void *key, void *data);
ObjectIdTable table_;
};

View File

@ -19,9 +19,14 @@
#
# Targets are defined by the following variables:
#
# FILE - The make file to evaluate.
# FILE - The make file to evaluate. This is equivalent to
# |make -f <FILE>|
# DIRECTORY - The directory whose Makefile to evaluate. This is
# equivalent to |make -C <DIRECTORY>|.
# TARGETS - Targets to evaluate in that make file.
#
# Only 1 of FILE or DIRECTORY may be defined.
#
# For example:
#
# NONRECURSIVE_TARGETS = export libs
@ -29,30 +34,31 @@
# NONRECURSIVE_TARGETS_export_headers_FILE = /path/to/exports.mk
# NONRECURSIVE_TARGETS_export_headers_TARGETS = $(DIST)/include/foo.h $(DIST)/include/bar.h
# NONRECURSIVE_TARGETS_libs = cppsrcs
# NONRECURSIVE_TARGETS_libs_cppsrcs_FILE = /path/to/compilation.mk
# NONRECURSIVE_TARGETS_libs_cppsrcs_DIRECTORY = $(DEPTH)/foo
# NONRECURSIVE_TARGETS_libs_cppsrcs_TARGETS = /path/to/foo.o /path/to/bar.o
#
# Will get turned into the following:
#
# exports::
# $(MAKE) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
# $(MAKE) -C $(DEPTH) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
#
# libs::
# $(MAKE) -f /path/to/compilation.mk /path/to/foo.o /path/to/bar.o
# $(MAKE) -C $(DEPTH)/foo /path/to/foo.o /path/to/bar.o
ifndef INCLUDED_NONRECURSIVE_MK
define define_nonrecursive_target
$(1)::
cd $$(DEPTH) && $$(MAKE) -f $(2) $(3)
$$(MAKE) -C $(or $(4),$$(DEPTH)) $(addprefix -f ,$(3)) $(2)
endef
$(foreach target,$(NONRECURSIVE_TARGETS), \
$(foreach entry,$(NONRECURSIVE_TARGETS_$(target)), \
$(eval $(call define_nonrecursive_target, \
$(target), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_FILE), \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS) \
$(NONRECURSIVE_TARGETS_$(target)_$(entry)_DIRECTORY), \
)) \
) \
)

View File

@ -66,8 +66,8 @@ CheckArgumentsWithinEval(JSContext *cx, Parser<FullParseHandler> &parser, Handle
return false;
}
// It's an error to use |arguments| in a generator expression.
if (script->isGeneratorExp) {
// It's an error to use |arguments| in a legacy generator expression.
if (script->isGeneratorExp && script->isLegacyGenerator) {
parser.report(ParseError, false, NULL, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
return false;
}

View File

@ -391,7 +391,7 @@ Parser<ParseHandler>::Parser(ExclusiveContext *cx, LifoAlloc *alloc,
: AutoGCRooter(cx, PARSER),
context(cx),
alloc(*alloc),
tokenStream(cx, options, chars, length, thisForCtor(), keepAtoms),
tokenStream(cx, options, chars, length, thisForCtor()),
traceListHead(NULL),
pc(NULL),
sct(NULL),
@ -1068,7 +1068,7 @@ Parser<ParseHandler>::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
if (!pn)
return null();
if (pc->sc->asFunctionBox()->isGenerator()) {
if (pc->sc->asFunctionBox()->isLegacyGenerator()) {
reportBadReturn(pn, ParseError,
JSMSG_BAD_GENERATOR_RETURN,
JSMSG_BAD_ANON_GENERATOR_RETURN);
@ -4407,6 +4407,8 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
return null();
}
// Legacy generators are identified by the presence of "yield" in their
// bodies. We only see "yield" as TOK_YIELD in JS 1.7+.
if (isYield) {
if (!abortIfSyntaxParser())
return null();
@ -4415,7 +4417,7 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
// expression until we see a |for| token, so we have to delay flagging
// the current function.
if (pc->parenDepth == 0) {
pc->sc->asFunctionBox()->setIsGenerator();
pc->sc->asFunctionBox()->setIsLegacyGenerator();
} else {
pc->yieldCount++;
pc->yieldOffset = begin;
@ -4464,7 +4466,7 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
if (!pn)
return null();
if (pc->funHasReturnExpr && pc->sc->asFunctionBox()->isGenerator()) {
if (pc->funHasReturnExpr && pc->sc->asFunctionBox()->isLegacyGenerator()) {
/* As in Python (see PEP-255), disallow return v; in generators. */
reportBadReturn(pn, ParseError, JSMSG_BAD_GENERATOR_RETURN,
JSMSG_BAD_ANON_GENERATOR_RETURN);
@ -5414,21 +5416,24 @@ class CompExprTransplanter
};
/*
* A helper for lazily checking for the presence of illegal |yield| or |arguments|
* tokens inside of generator expressions. This must be done lazily since we don't
* know whether we're in a generator expression until we see the "for" token after
* we've already parsed the body expression.
* A helper for lazily checking for the presence of illegal |yield| or
* |arguments| tokens inside of legacy generator expressions. This must be done
* lazily since we don't know whether we're in a legacy generator expression
* until we see the "for" token after we've already parsed the body expression.
* (For ES6 generator comprehensions, we won't need this lazy check because the
* |for| is at the beginning.)
*
* Use in any context which may turn out to be inside a generator expression. This
* includes parenthesized expressions and argument lists, and it includes the tail
* of generator expressions.
* Use in any context which may turn out to be inside a legacy generator
* expression. This includes parenthesized expressions and argument lists, and
* it includes the tail of legacy generator expressions.
*
* The guard will keep track of any |yield| or |arguments| tokens that occur while
* parsing the body. As soon as the parser reaches the end of the body expression,
* call endBody() to reset the context's state, and then immediately call:
*
* - checkValidBody() if this *did* turn out to be a generator expression
* - maybeNoteGenerator() if this *did not* turn out to be a generator expression
* - checkValidBody() if this *did* turn out to be a legacy generator expression
* - maybeNoteLegacyGenerator() if this *did not* turn out to be a legacy
* generator expression
*/
template <typename ParseHandler>
class GenexpGuard
@ -5453,7 +5458,7 @@ class GenexpGuard
void endBody();
bool checkValidBody(Node pn, unsigned err = JSMSG_BAD_GENEXP_BODY);
bool maybeNoteGenerator(Node pn);
bool maybeNoteLegacyGenerator(Node pn);
};
template <typename ParseHandler>
@ -5497,18 +5502,22 @@ GenexpGuard<ParseHandler>::checkValidBody(Node pn, unsigned err)
*/
template <typename ParseHandler>
bool
GenexpGuard<ParseHandler>::maybeNoteGenerator(Node pn)
GenexpGuard<ParseHandler>::maybeNoteLegacyGenerator(Node pn)
{
ParseContext<ParseHandler> *pc = parser->pc;
// yieldCount is only incremented when we see yield in JS 1.7+ code.
if (pc->yieldCount > 0) {
if (!pc->sc->isFunctionBox()) {
// FIXME: This error should be detected eagerly, when the yield is
// seen.
parser->report(ParseError, false, ParseHandler::null(),
JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
return false;
}
pc->sc->asFunctionBox()->setIsGenerator();
pc->sc->asFunctionBox()->setIsLegacyGenerator();
if (pc->funHasReturnExpr) {
/* At the time we saw the yield, we might not have set isGenerator yet. */
// At the time we saw the yield, we might not have set
// isLegacyGenerator yet.
parser->reportBadReturn(pn, ParseError,
JSMSG_BAD_GENERATOR_RETURN, JSMSG_BAD_ANON_GENERATOR_RETURN);
return false;
@ -5871,7 +5880,7 @@ Parser<FullParseHandler>::comprehensionTail(ParseNode *kid, unsigned blockid, bo
if (!guard.checkValidBody(pn2))
return null();
} else {
if (!guard.maybeNoteGenerator(pn2))
if (!guard.maybeNoteLegacyGenerator(pn2))
return null();
}
@ -6057,7 +6066,7 @@ Parser<FullParseHandler>::generatorExpr(ParseNode *kid)
if (outerpc->sc->isFunctionBox())
genFunbox->funCxFlags = outerpc->sc->asFunctionBox()->funCxFlags;
genFunbox->setIsGenerator();
genFunbox->setIsLegacyGenerator();
genFunbox->inGenexpLambda = true;
genfn->pn_blockid = genpc.bodyid;
@ -6147,7 +6156,7 @@ Parser<ParseHandler>::argumentList(Node listNode)
}
} else
#endif
if (arg0 && !guard.maybeNoteGenerator(argNode))
if (arg0 && !guard.maybeNoteLegacyGenerator(argNode))
return false;
arg0 = false;
@ -6816,7 +6825,7 @@ Parser<ParseHandler>::parenExpr(bool *genexp)
} else
#endif /* JS_HAS_GENERATOR_EXPRS */
if (!guard.maybeNoteGenerator(pn))
if (!guard.maybeNoteLegacyGenerator(pn))
return null();
return pn;

View File

@ -73,8 +73,9 @@ class FunctionContextFlags
// This class's data is all private and so only visible to these friends.
friend class FunctionBox;
// We parsed a yield statement in the function.
bool isGenerator:1;
// We parsed a yield statement in the function, which can happen in JS1.7+
// mode.
bool isLegacyGenerator:1;
// The function or a function that encloses it may define new local names
// at runtime through means other than calling eval.
@ -129,7 +130,7 @@ class FunctionContextFlags
public:
FunctionContextFlags()
: isGenerator(false),
: isLegacyGenerator(false),
mightAliasLocals(false),
hasExtensibleScope(false),
needsDeclEnvObject(false),
@ -284,14 +285,16 @@ class FunctionBox : public ObjectBox, public SharedContext
ObjectBox *toObjectBox() { return this; }
JSFunction *function() const { return &object->as<JSFunction>(); }
bool isGenerator() const { return funCxFlags.isGenerator; }
// In the future, isGenerator will also return true for ES6 generators.
bool isGenerator() const { return isLegacyGenerator(); }
bool isLegacyGenerator() const { return funCxFlags.isLegacyGenerator; }
bool mightAliasLocals() const { return funCxFlags.mightAliasLocals; }
bool hasExtensibleScope() const { return funCxFlags.hasExtensibleScope; }
bool needsDeclEnvObject() const { return funCxFlags.needsDeclEnvObject; }
bool argumentsHasLocalBinding() const { return funCxFlags.argumentsHasLocalBinding; }
bool definitelyNeedsArgsObj() const { return funCxFlags.definitelyNeedsArgsObj; }
void setIsGenerator() { funCxFlags.isGenerator = true; }
void setIsLegacyGenerator() { funCxFlags.isLegacyGenerator = true; }
void setMightAliasLocals() { funCxFlags.mightAliasLocals = true; }
void setHasExtensibleScope() { funCxFlags.hasExtensibleScope = true; }
void setNeedsDeclEnvObject() { funCxFlags.needsDeclEnvObject = true; }

View File

@ -265,8 +265,7 @@ TokenStream::SourceCoords::lineNumAndColumnIndex(uint32_t offset, uint32_t *line
/* Initialize members that aren't initialized in |init|. */
TokenStream::TokenStream(ExclusiveContext *cx, const CompileOptions &options,
const jschar *base, size_t length, StrictModeGetter *smg,
AutoKeepAtoms& keepAtoms)
const jschar *base, size_t length, StrictModeGetter *smg)
: srcCoords(cx, options.lineno),
options_(options),
tokens(),
@ -298,30 +297,9 @@ TokenStream::TokenStream(ExclusiveContext *cx, const CompileOptions &options,
// this line then adjust the next character.
userbuf.setAddressOfNextRawChar(base);
/*
* This table holds all the token kinds that satisfy these properties:
* - A single char long.
* - Cannot be a prefix of any longer token (e.g. '+' is excluded because
* '+=' is a valid token).
*
* The few token kinds satisfying these properties cover roughly 35--45%
* of the tokens seen in practice.
*
* Nb: oneCharTokens, maybeEOL and maybeStrSpecial could be static, but
* initializing them this way is a bit easier. Don't worry, the time to
* initialize them for each TokenStream is trivial. See bug 639420.
*/
memset(oneCharTokens, 0, sizeof(oneCharTokens));
oneCharTokens[unsigned(';')] = TOK_SEMI;
oneCharTokens[unsigned(',')] = TOK_COMMA;
oneCharTokens[unsigned('?')] = TOK_HOOK;
oneCharTokens[unsigned('[')] = TOK_LB;
oneCharTokens[unsigned(']')] = TOK_RB;
oneCharTokens[unsigned('{')] = TOK_LC;
oneCharTokens[unsigned('}')] = TOK_RC;
oneCharTokens[unsigned('(')] = TOK_LP;
oneCharTokens[unsigned(')')] = TOK_RP;
oneCharTokens[unsigned('~')] = TOK_BITNOT;
// Nb: the following tables could be static, but initializing them here is
// much easier. Don't worry, the time to initialize them for each
// TokenStream is trivial. See bug 639420.
/* See getChar() for an explanation of maybeEOL[]. */
memset(maybeEOL, 0, sizeof(maybeEOL));
@ -506,7 +484,7 @@ TokenStream::peekChars(int n, jschar *cp)
ungetCharIgnoreEOL(c);
break;
}
cp[i] = (jschar)c;
cp[i] = jschar(c);
}
for (j = i - 1; j >= 0; j--)
ungetCharIgnoreEOL(cp[j]);
@ -899,7 +877,7 @@ TokenStream::getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated)
return true;
}
Token *
JS_ALWAYS_INLINE Token *
TokenStream::newToken(ptrdiff_t adjust)
{
cursor = (cursor + 1) & ntokensMask;
@ -994,57 +972,74 @@ TokenStream::checkForKeyword(const jschar *s, size_t length, TokenKind *ttp)
}
enum FirstCharKind {
Other,
OneChar,
Ident,
Dot,
Equals,
String,
Dec,
Colon,
Plus,
BasePrefix,
// A jschar has the 'OneChar' kind if it, by itself, constitutes a valid
// token that cannot also be a prefix of a longer token. E.g. ';' has the
// OneChar kind, but '+' does not, because '++' and '+=' are valid longer tokens
// that begin with '+'.
//
// The few token kinds satisfying these properties cover roughly 35--45%
// of the tokens seen in practice.
//
// We represent the 'OneChar' kind with any positive value less than
// TOK_LIMIT. This representation lets us associate each one-char token
// jschar with a TokenKind and thus avoid a subsequent jschar-to-TokenKind
// conversion.
OneChar_Min = 0,
OneChar_Max = TOK_LIMIT - 1,
/* These two must be last, so that |c >= Space| matches both. */
Space,
EOL
Space = TOK_LIMIT,
Ident,
Dec,
String,
EOL,
BasePrefix,
Other,
LastCharKind = Other
};
#define _______ Other
/*
* OneChar: 40, 41, 44, 59, 63, 91, 93, 123, 125, 126:
* '(', ')', ',', ';', '?', '[', ']', '{', '}', '~'
* OneChar: 40, 41, 44, 58, 59, 63, 91, 93, 123, 125, 126:
* '(', ')', ',', ':', ';', '?', '[', ']', '{', '}', '~'
* Ident: 36, 65..90, 95, 97..122: '$', 'A'..'Z', '_', 'a'..'z'
* Dot: 46: '.'
* Equals: 61: '='
* String: 34, 39: '"', '\''
* Dec: 49..57: '1'..'9'
* Colon: 58: ':'
* Plus: 43: '+'
* BasePrefix: 48: '0'
* Space: 9, 11, 12: '\t', '\v', '\f'
* Space: 9, 11, 12, 32: '\t', '\v', '\f', ' '
* EOL: 10, 13: '\n', '\r'
*/
#define T_COMMA TOK_COMMA
#define T_COLON TOK_COLON
#define T_BITNOT TOK_BITNOT
#define _______ Other
static const uint8_t firstCharKinds[] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0+ */ _______, _______, _______, _______, _______, _______, _______, _______, _______, Space,
/* 10+ */ EOL, Space, Space, EOL, _______, _______, _______, _______, _______, _______,
/* 20+ */ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
/* 30+ */ _______, _______, Space, _______, String, _______, Ident, _______, _______, String,
/* 40+ */ OneChar, OneChar, _______, Plus, OneChar, _______, Dot, _______, BasePrefix, Dec,
/* 50+ */ Dec, Dec, Dec, Dec, Dec, Dec, Dec, Dec, Colon, OneChar,
/* 60+ */ _______, Equals, _______, OneChar, _______, Ident, Ident, Ident, Ident, Ident,
/* 40+ */ TOK_LP, TOK_RP, _______, _______, T_COMMA,_______, _______, _______,BasePrefix, Dec,
/* 50+ */ Dec, Dec, Dec, Dec, Dec, Dec, Dec, Dec, T_COLON,TOK_SEMI,
/* 60+ */ _______, _______, _______,TOK_HOOK, _______, Ident, Ident, Ident, Ident, Ident,
/* 70+ */ Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident,
/* 80+ */ Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident,
/* 90+ */ Ident, OneChar, _______, OneChar, _______, Ident, _______, Ident, Ident, Ident,
/* 90+ */ Ident, TOK_LB, _______, TOK_RB, _______, Ident, _______, Ident, Ident, Ident,
/* 100+ */ Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident,
/* 110+ */ Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident,
/* 120+ */ Ident, Ident, Ident, OneChar, _______, OneChar, OneChar, _______
/* 120+ */ Ident, Ident, Ident, TOK_LC, _______, TOK_RC,T_BITNOT, _______
};
#undef T_COMMA
#undef T_COLON
#undef T_BITNOT
#undef _______
static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)),
"Elements of firstCharKinds[] are too small");
TokenKind
TokenStream::getTokenInternal()
{
@ -1098,44 +1093,47 @@ TokenStream::getTokenInternal()
/*
* Get the token kind, based on the first char. The ordering of c1kind
* comparison is based on the frequency of tokens in real code. Minified
* and non-minified code have different characteristics, mostly in that
* whitespace occurs much less in minified code. Token kinds that fall in
* the 'Other' category typically account for less than 2% of all tokens,
* so their order doesn't matter much.
* comparison is based on the frequency of tokens in real code -- Parsemark
* (which represents typical JS code on the web) and the Unreal demo (which
* represents asm.js code).
*
* Parsemark Unreal
* OneChar 32.9% 39.7%
* Space 25.0% 0.6%
* Ident 19.2% 36.4%
* Dec 7.2% 5.1%
* String 7.9% 0.0%
* EOL 1.7% 0.0%
* BasePrefix 0.4% 4.9%
* Other 5.7% 13.3%
*
* The ordering is based mostly only Parsemark frequencies, with Unreal
* frequencies used to break close categories (e.g. |Dec| and |String|).
* |Other| is biggish, but no other token kind is common enough for it to
* be worth adding extra values to FirstCharKind.
*/
c1kind = FirstCharKind(firstCharKinds[c]);
/*
* Skip over whitespace chars; update line state on EOLs. Even though
* whitespace isn't very common in minified code we have to handle it first
* (and jump back to 'retry') before calling newToken().
*/
if (c1kind >= Space) {
if (c1kind == EOL) {
/* If it's a \r\n sequence: treat as a single EOL, skip over the \n. */
if (c == '\r' && userbuf.hasRawChars())
userbuf.matchRawChar('\n');
updateLineInfoForEOL();
updateFlagsForEOL();
}
goto retry;
}
tp = newToken(-1);
/*
* Look for an unambiguous single-char token.
*/
if (c1kind == OneChar) {
tt = (TokenKind)oneCharTokens[c];
if (c1kind < OneChar_Max) {
tp = newToken(-1);
tt = TokenKind(c1kind);
goto out;
}
/*
* Skip over non-EOL whitespace chars.
*/
if (c1kind == Space)
goto retry;
/*
* Look for an identifier.
*/
if (c1kind == Ident) {
tp = newToken(-1);
identStart = userbuf.addressOfNextRawChar() - 1;
hadUnicodeEscape = false;
@ -1152,38 +1150,33 @@ TokenStream::getTokenInternal()
}
ungetCharIgnoreEOL(c);
/* Convert the escapes by putting into tokenbuf. */
if (hadUnicodeEscape && !putIdentInTokenbuf(identStart))
goto error;
/*
* Identifiers containing no Unicode escapes can be processed directly
* from userbuf. The rest must use the escapes converted via tokenbuf
* before atomizing.
*/
const jschar *chars;
size_t length;
if (hadUnicodeEscape) {
if (!putIdentInTokenbuf(identStart))
goto error;
chars = tokenbuf.begin();
length = tokenbuf.length();
} else {
chars = identStart;
length = userbuf.addressOfNextRawChar() - identStart;
}
/* Check for keywords unless parser asks us to ignore keywords. */
if (!(flags & TSF_KEYWORD_IS_NAME)) {
const jschar *chars;
size_t length;
if (hadUnicodeEscape) {
chars = tokenbuf.begin();
length = tokenbuf.length();
} else {
chars = identStart;
length = userbuf.addressOfNextRawChar() - identStart;
}
tt = TOK_NAME;
if (!checkForKeyword(chars, length, &tt))
goto error;
if (tt != TOK_NAME)
goto out;
if (tt != TOK_NAME) goto out;
}
/*
* Identifiers containing no Unicode escapes can be atomized directly
* from userbuf. The rest must use the escapes converted via
* tokenbuf before atomizing.
*/
JSAtom *atom;
if (!hadUnicodeEscape)
atom = AtomizeChars<CanGC>(cx, identStart, userbuf.addressOfNextRawChar() - identStart);
else
atom = atomize(cx, tokenbuf);
JSAtom *atom = AtomizeChars<CanGC>(cx, chars, length);
if (!atom)
goto error;
tp->setName(atom->asPropertyName());
@ -1191,34 +1184,63 @@ TokenStream::getTokenInternal()
goto out;
}
if (c1kind == Dot) {
c = getCharIgnoreEOL();
if (JS7_ISDEC(c)) {
numStart = userbuf.addressOfNextRawChar() - 2;
decimalPoint = HasDecimal;
hasExp = false;
goto decimal_dot;
}
/*
* Look for a decimal number.
*/
if (c1kind == Dec) {
tp = newToken(-1);
numStart = userbuf.addressOfNextRawChar() - 1;
decimal:
decimalPoint = NoDecimal;
hasExp = false;
while (JS7_ISDEC(c))
c = getCharIgnoreEOL();
if (c == '.') {
qc = getCharIgnoreEOL();
if (qc == '.') {
tt = TOK_TRIPLEDOT;
goto out;
decimalPoint = HasDecimal;
decimal_dot:
do {
c = getCharIgnoreEOL();
} while (JS7_ISDEC(c));
}
if (c == 'e' || c == 'E') {
hasExp = true;
c = getCharIgnoreEOL();
if (c == '+' || c == '-')
c = getCharIgnoreEOL();
if (!JS7_ISDEC(c)) {
ungetCharIgnoreEOL(c);
reportError(JSMSG_MISSING_EXPONENT);
goto error;
}
ungetCharIgnoreEOL(qc);
do {
c = getCharIgnoreEOL();
} while (JS7_ISDEC(c));
}
ungetCharIgnoreEOL(c);
tt = TOK_DOT;
goto out;
}
if (c1kind == Equals) {
if (matchChar('='))
tt = matchChar('=') ? TOK_STRICTEQ : TOK_EQ;
else if (matchChar('>'))
tt = TOK_ARROW;
else
tt = TOK_ASSIGN;
if (c != EOF && IsIdentifierStart(c)) {
reportError(JSMSG_IDSTART_AFTER_NUMBER);
goto error;
}
/*
* Unlike identifiers and strings, numbers cannot contain escaped
* chars, so we don't need to use tokenbuf. Instead we can just
* convert the jschars in userbuf directly to the numeric value.
*/
double dval;
if (!((decimalPoint == HasDecimal) || hasExp)) {
if (!GetDecimalInteger(cx, numStart, userbuf.addressOfNextRawChar(), &dval))
goto error;
} else {
const jschar *dummy;
if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
goto error;
}
tp->setNumber(dval, decimalPoint);
tt = TOK_NUMBER;
goto out;
}
@ -1226,6 +1248,7 @@ TokenStream::getTokenInternal()
* Look for a string.
*/
if (c1kind == String) {
tp = newToken(-1);
qc = c;
tokenbuf.clear();
while (true) {
@ -1274,7 +1297,7 @@ TokenStream::getTokenInternal()
}
}
c = (jschar)val;
c = jschar(val);
} else if (c == 'u') {
jschar cp[4];
if (peekChars(4, cp) &&
@ -1326,79 +1349,20 @@ TokenStream::getTokenInternal()
}
/*
* Look for a decimal number.
* Skip over EOL chars, updating line state along the way.
*/
if (c1kind == Dec) {
numStart = userbuf.addressOfNextRawChar() - 1;
decimal:
decimalPoint = NoDecimal;
hasExp = false;
while (JS7_ISDEC(c))
c = getCharIgnoreEOL();
if (c == '.') {
decimalPoint = HasDecimal;
decimal_dot:
do {
c = getCharIgnoreEOL();
} while (JS7_ISDEC(c));
}
if (c == 'e' || c == 'E') {
hasExp = true;
c = getCharIgnoreEOL();
if (c == '+' || c == '-')
c = getCharIgnoreEOL();
if (!JS7_ISDEC(c)) {
ungetCharIgnoreEOL(c);
reportError(JSMSG_MISSING_EXPONENT);
goto error;
}
do {
c = getCharIgnoreEOL();
} while (JS7_ISDEC(c));
}
ungetCharIgnoreEOL(c);
if (c != EOF && IsIdentifierStart(c)) {
reportError(JSMSG_IDSTART_AFTER_NUMBER);
goto error;
}
/*
* Unlike identifiers and strings, numbers cannot contain escaped
* chars, so we don't need to use tokenbuf. Instead we can just
* convert the jschars in userbuf directly to the numeric value.
*/
double dval;
const jschar *dummy;
if (!((decimalPoint == HasDecimal) || hasExp)) {
if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), 10, &dummy, &dval))
goto error;
} else {
if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
goto error;
}
tp->setNumber(dval, decimalPoint);
tt = TOK_NUMBER;
goto out;
}
if (c1kind == Colon) {
tt = TOK_COLON;
goto out;
}
if (c1kind == Plus) {
if (matchChar('+'))
tt = TOK_INC;
else
tt = matchChar('=') ? TOK_ADDASSIGN : TOK_PLUS;
goto out;
if (c1kind == EOL) {
/* If it's a \r\n sequence: treat as a single EOL, skip over the \n. */
if (c == '\r' && userbuf.hasRawChars())
userbuf.matchRawChar('\n');
updateLineInfoForEOL();
updateFlagsForEOL();
goto retry;
}
// Look for a hexadecimal, octal, or binary number.
if (c1kind == BasePrefix) {
tp = newToken(-1);
int radix;
c = getCharIgnoreEOL();
if (c == 'x' || c == 'X') {
@ -1481,7 +1445,42 @@ TokenStream::getTokenInternal()
* This handles everything else.
*/
JS_ASSERT(c1kind == Other);
tp = newToken(-1);
switch (c) {
case '.':
c = getCharIgnoreEOL();
if (JS7_ISDEC(c)) {
numStart = userbuf.addressOfNextRawChar() - 2;
decimalPoint = HasDecimal;
hasExp = false;
goto decimal_dot;
}
if (c == '.') {
if (matchChar('.')) {
tt = TOK_TRIPLEDOT;
goto out;
}
}
ungetCharIgnoreEOL(c);
tt = TOK_DOT;
break;
case '=':
if (matchChar('='))
tt = matchChar('=') ? TOK_STRICTEQ : TOK_EQ;
else if (matchChar('>'))
tt = TOK_ARROW;
else
tt = TOK_ASSIGN;
break;
case '+':
if (matchChar('+'))
tt = TOK_INC;
else
tt = matchChar('=') ? TOK_ADDASSIGN : TOK_PLUS;
break;
case '\\':
hadUnicodeEscape = matchUnicodeEscapeIdStart(&qc);
if (hadUnicodeEscape) {
@ -1519,10 +1518,8 @@ TokenStream::getTokenInternal()
/* NB: treat HTML begin-comment as comment-till-end-of-line */
if (matchChar('!')) {
if (matchChar('-')) {
if (matchChar('-')) {
flags |= TSF_IN_HTML_COMMENT;
if (matchChar('-'))
goto skipline;
}
ungetChar('-');
}
ungetChar('!');
@ -1560,17 +1557,9 @@ TokenStream::getTokenInternal()
goto error;
}
skipline:
/* Optimize line skipping if we are not in an HTML comment. */
if (flags & TSF_IN_HTML_COMMENT) {
while ((c = getChar()) != EOF && c != '\n') {
if (c == '-' && matchChar('-') && matchChar('>'))
flags &= ~TSF_IN_HTML_COMMENT;
}
} else {
while ((c = getChar()) != EOF && c != '\n')
continue;
}
skipline:
while ((c = getChar()) != EOF && c != '\n')
continue;
ungetChar(c);
cursor = (cursor - 1) & ntokensMask;
goto retry;
@ -1669,10 +1658,8 @@ TokenStream::getTokenInternal()
case '-':
if (matchChar('-')) {
if (peekChar() == '>' && !(flags & TSF_DIRTYLINE)) {
flags &= ~TSF_IN_HTML_COMMENT;
if (peekChar() == '>' && !(flags & TSF_DIRTYLINE))
goto skipline;
}
tt = TOK_DEC;
} else {
tt = matchChar('=') ? TOK_SUBASSIGN : TOK_MINUS;

View File

@ -253,7 +253,7 @@ struct Token {
JSAtom *atom; /* potentially-numeric atom */
struct {
double value; /* floating point number */
DecimalPoint decimalPoint; /* literal contains . or exponent */
DecimalPoint decimalPoint; /* literal contains '.' */
} number;
RegExpFlag reflags; /* regexp flags, use tokenbuf to access
regexp chars */
@ -324,28 +324,7 @@ enum TokenStreamFlags
TSF_KEYWORD_IS_NAME = 0x20, /* Ignore keywords and return TOK_NAME instead to the parser. */
TSF_DIRTYLINE = 0x40, /* non-whitespace since start of line */
TSF_OCTAL_CHAR = 0x80, /* observed a octal character escape */
TSF_HAD_ERROR = 0x100, /* returned TOK_ERROR from getToken */
/*
* To handle the hard case of contiguous HTML comments, we want to clear the
* TSF_DIRTYINPUT flag at the end of each such comment. But we'd rather not
* scan for --> within every //-style comment unless we have to. So we set
* TSF_IN_HTML_COMMENT when a <!-- is scanned as an HTML begin-comment, and
* clear it (and TSF_DIRTYINPUT) when we scan --> either on a clean line, or
* only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment.
*
* This still works as before given a malformed comment hiding hack such as:
*
* <script>
* <!-- comment hiding hack #1
* code goes here
* // --> oops, markup for script-unaware browsers goes here!
* </script>
*
* It does not cope with malformed comment hiding hacks where --> is hidden
* by C-style comments, or on a dirty line. Such cases are already broken.
*/
TSF_IN_HTML_COMMENT = 0x200
TSF_HAD_ERROR = 0x100 /* returned TOK_ERROR from getToken */
};
struct CompileError {
@ -431,8 +410,7 @@ class MOZ_STACK_CLASS TokenStream
typedef Vector<jschar, 32> CharBuffer;
TokenStream(ExclusiveContext *cx, const CompileOptions &options,
const jschar *base, size_t length, StrictModeGetter *smg,
AutoKeepAtoms& keepAtoms);
const jschar *base, size_t length, StrictModeGetter *smg);
~TokenStream();
@ -442,10 +420,6 @@ class MOZ_STACK_CLASS TokenStream
bool isCurrentTokenType(TokenKind type) const {
return currentToken().type == type;
}
bool isCurrentTokenType(TokenKind type1, TokenKind type2) const {
TokenKind type = currentToken().type;
return type == type1 || type == type2;
}
const CharBuffer &getTokenbuf() const { return tokenbuf; }
const char *getFilename() const { return filename; }
unsigned getLineno() const { return lineno; }
@ -455,18 +429,6 @@ class MOZ_STACK_CLASS TokenStream
JSVersion versionWithFlags() const { return options().version; }
bool hadError() const { return !!(flags & TSF_HAD_ERROR); }
bool isCurrentTokenEquality() const {
return TokenKindIsEquality(currentToken().type);
}
bool isCurrentTokenRelational() const {
return TokenKindIsRelational(currentToken().type);
}
bool isCurrentTokenShift() const {
return TokenKindIsShift(currentToken().type);
}
bool isCurrentTokenAssignment() const {
return TokenKindIsAssignment(currentToken().type);
}
@ -918,7 +880,6 @@ class MOZ_STACK_CLASS TokenStream
const char *filename; /* input filename or null */
jschar *sourceMap; /* source map's filename or null */
CharBuffer tokenbuf; /* current token string buffer */
int8_t oneCharTokens[128]; /* table of one-char tokens, indexed by 7-bit char */
bool maybeEOL[256]; /* probabilistic EOL lookup table */
bool maybeStrSpecial[256];/* speeds up string scanning */
uint8_t isExprEnding[TOK_LIMIT]; /* which tokens definitely terminate exprs? */

View File

@ -482,10 +482,12 @@ AutoGCRooter::trace(JSTracer *trc)
case OBJOBJHASHMAP: {
AutoObjectObjectHashMap::HashMapImpl &map = static_cast<AutoObjectObjectHashMap *>(this)->map;
for (AutoObjectObjectHashMap::Enum e(map); !e.empty(); e.popFront()) {
mozilla::DebugOnly<JSObject *> key = e.front().key;
MarkObjectRoot(trc, const_cast<JSObject **>(&e.front().key), "AutoObjectObjectHashMap key");
JS_ASSERT(key == e.front().key); // Needs rewriting for moving GC, see bug 726687.
MarkObjectRoot(trc, &e.front().value, "AutoObjectObjectHashMap value");
JS_SET_TRACING_LOCATION(trc, (void *)&e.front().key);
JSObject *key = e.front().key;
MarkObjectRoot(trc, &key, "AutoObjectObjectHashMap key");
if (key != e.front().key)
e.rekeyFront(key);
}
return;
}

View File

@ -842,6 +842,18 @@ CodeGenerator::visitCallee(LCallee *lir)
return true;
}
bool
CodeGenerator::visitForceUseV(LForceUseV *lir)
{
return true;
}
bool
CodeGenerator::visitForceUseT(LForceUseT *lir)
{
return true;
}
bool
CodeGenerator::visitStart(LStart *lir)
{

View File

@ -59,6 +59,8 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitTableSwitchV(LTableSwitchV *ins);
bool visitParameter(LParameter *lir);
bool visitCallee(LCallee *lir);
bool visitForceUseV(LForceUseV *lir);
bool visitForceUseT(LForceUseT *lir);
bool visitStart(LStart *lir);
bool visitReturn(LReturn *ret);
bool visitDefVar(LDefVar *lir);

View File

@ -194,10 +194,6 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
DebugOnly<bool> appendOk = targets.append(obj);
JS_ASSERT(appendOk);
} else {
/* Temporarily disable heavyweight-function inlining. */
targets.clear();
return true;
#if 0
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
JS_ASSERT(typeObj);
if (!typeObj->isFunction() || !typeObj->interpretedFunction) {
@ -210,7 +206,6 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
JS_ASSERT(appendOk);
*gotLambda = true;
#endif
}
}
@ -3527,6 +3522,11 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
returnBlock->inheritSlots(current);
returnBlock->pop();
// If callee is not a constant, add an MForceUse with the callee to make sure that
// it gets kept alive across the inlined body.
if (!callInfo.fun()->isConstant())
returnBlock->add(MForceUse::New(callInfo.fun()));
// Accumulate return values.
MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator();
if (exits.length() == 0) {

View File

@ -219,6 +219,23 @@ class LCallee : public LInstructionHelper<1, 0, 0>
LIR_HEADER(Callee)
};
class LForceUseV : public LInstructionHelper<0, BOX_PIECES, 0>
{
public:
LIR_HEADER(ForceUseV)
};
class LForceUseT : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(ForceUseT)
LForceUseT(const LAllocation &value)
{
setOperand(0, value);
}
};
// Base class for control instructions (goto, branch, etc.)
template <size_t Succs, size_t Operands, size_t Temps>
class LControlInstructionHelper : public LInstructionHelper<0, Operands, Temps> {

View File

@ -18,6 +18,8 @@
_(Value) \
_(Parameter) \
_(Callee) \
_(ForceUseV) \
_(ForceUseT) \
_(TableSwitch) \
_(TableSwitchV) \
_(Goto) \

View File

@ -60,6 +60,20 @@ LIRGenerator::visitCallee(MCallee *ins)
return define(new LCallee(), ins);
}
bool
LIRGenerator::visitForceUse(MForceUse *ins)
{
if (ins->input()->type() == MIRType_Value) {
LForceUseV *lir = new LForceUseV();
if (!useBox(lir, 0, ins->input()));
return false;
return add(lir);
}
LForceUseT *lir = new LForceUseT(useAnyOrConstant(ins->input()));
return add(lir);
}
bool
LIRGenerator::visitGoto(MGoto *ins)
{

View File

@ -80,6 +80,7 @@ class LIRGenerator : public LIRGeneratorSpecific
// intercept without a bunch of explicit gunk in the .cpp.
bool visitParameter(MParameter *param);
bool visitCallee(MCallee *callee);
bool visitForceUse(MForceUse *forceUse);
bool visitGoto(MGoto *ins);
bool visitTableSwitch(MTableSwitch *tableswitch);
bool visitNewSlots(MNewSlots *ins);

View File

@ -996,6 +996,34 @@ class MCallee : public MNullaryInstruction
}
};
// MForceUse exists to force the use of a resumePoint-recorded
// instruction at a later point in time, so that the contents don't get
// discarded when inlining.
class MForceUse : public MUnaryInstruction
{
public:
MForceUse(MDefinition *input)
: MUnaryInstruction(input)
{
setGuard();
setResultType(MIRType_None);
}
public:
INSTRUCTION_HEADER(ForceUse)
bool congruentTo(MDefinition *ins) const {
return false;
}
static MForceUse *New(MDefinition *input) {
return new MForceUse(input);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
};
class MControlInstruction : public MInstruction
{
public:

View File

@ -14,6 +14,7 @@ namespace ion {
_(Constant) \
_(Parameter) \
_(Callee) \
_(ForceUse) \
_(TableSwitch) \
_(Goto) \
_(Test) \

View File

@ -111,6 +111,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
SAFE_OP(Constant)
SAFE_OP(Parameter)
SAFE_OP(Callee)
SAFE_OP(ForceUse)
SAFE_OP(TableSwitch)
SAFE_OP(Goto)
SAFE_OP(Test)

View File

@ -171,6 +171,22 @@ CodeGeneratorARM::generateOutOfLineCode()
bool
CodeGeneratorARM::bailoutIf(Assembler::Condition condition, LSnapshot *snapshot)
{
CompileInfo &info = snapshot->mir()->block()->info();
switch (info.executionMode()) {
case ParallelExecution: {
// in parallel mode, make no attempt to recover, just signal an error.
OutOfLineAbortPar *ool = oolAbortPar(ParallelBailoutUnsupported,
snapshot->mir()->block(),
snapshot->mir()->pc());
masm.ma_b(ool->entry(), condition);
return true;
}
case SequentialExecution:
break;
default:
MOZ_ASSUME_UNREACHABLE("No such execution mode");
}
if (!encode(snapshot))
return false;
@ -205,6 +221,7 @@ CodeGeneratorARM::bailoutFrom(Label *label, LSnapshot *snapshot)
CompileInfo &info = snapshot->mir()->block()->info();
switch (info.executionMode()) {
case ParallelExecution: {
// in parallel mode, make no attempt to recover, just signal an error.
OutOfLineAbortPar *ool = oolAbortPar(ParallelBailoutUnsupported,
@ -1906,8 +1923,9 @@ CodeGeneratorARM::visitSoftUDivOrMod(LSoftUDivOrMod *ins)
JS_ASSERT(lhs == r0);
JS_ASSERT(rhs == r1);
JS_ASSERT(ins->mirRaw()->isAsmJSUDiv() || ins->mirRaw()->isAsmJSUMod());
JS_ASSERT_IF(ins->mirRaw()->isAsmJSUDiv(), output == r0);
JS_ASSERT(ins->mirRaw()->isDiv() || ins->mirRaw()->isAsmJSUDiv() ||
ins->mirRaw()->isAsmJSUMod());
JS_ASSERT_IF(ins->mirRaw()->isDiv() || ins->mirRaw()->isAsmJSUDiv(), output == r0);
JS_ASSERT_IF(ins->mirRaw()->isAsmJSUMod(), output == r1);
Label afterDiv;

View File

@ -463,7 +463,10 @@ LIRGeneratorARM::lowerUDiv(MInstruction *div)
MDefinition *rhs = div->getOperand(1);
if (hasIDIV()) {
return lowerForALU(new LUDiv, div, lhs, rhs);
LUDiv *lir = new LUDiv;
lir->setOperand(0, useRegister(lhs));
lir->setOperand(1, useRegister(rhs));
return define(lir, div);
} else {
LSoftUDivOrMod *lir = new LSoftUDivOrMod(useFixed(lhs, r0), useFixed(rhs, r1),
tempFixed(r2), tempFixed(r3));
@ -484,7 +487,10 @@ LIRGeneratorARM::lowerUMod(MInstruction *mod)
MDefinition *rhs = mod->getOperand(1);
if (hasIDIV()) {
return lowerForALU(new LUMod, mod, lhs, rhs);
LUMod *lir = new LUMod;
lir->setOperand(0, useRegister(lhs));
lir->setOperand(1, useRegister(rhs));
return define(lir, mod);
} else {
LSoftUDivOrMod *lir = new LSoftUDivOrMod(useFixed(lhs, r0), useFixed(rhs, r1),
tempFixed(r2), tempFixed(r3));

View File

@ -2019,8 +2019,8 @@ MacroAssemblerARMCompat::store32(const Register &src, const Address &address)
void
MacroAssemblerARMCompat::store32(const Imm32 &src, const Address &address)
{
move32(src, ScratchRegister);
storePtr(ScratchRegister, address);
move32(src, secondScratchReg_);
storePtr(secondScratchReg_, address);
}
void

View File

@ -0,0 +1,6 @@
function fillHeap() {
var x = 1, tmp;
for (var i = 0; i < 50000; ++i)
tmp <<= x / 3;
}
RegExp({ toString: fillHeap });

View File

@ -1827,6 +1827,8 @@ ScriptAnalysis::needsArgsObj(JSContext *cx)
/*
* Always construct arguments objects when in debug mode and for generator
* scripts (generators can be suspended when speculation fails).
*
* FIXME: Don't build arguments for ES6 generator expressions.
*/
if (cx->compartment()->debugMode() || script_->isGenerator)
return true;

View File

@ -53,6 +53,16 @@ struct JsidHasher
extern const char *
AtomToPrintableString(ExclusiveContext *cx, JSAtom *atom, JSAutoByteString *bytes);
/* Compute a hash function from chars/length. */
inline uint32_t
HashChars(const jschar *chars, size_t length)
{
uint32_t h = 0;
for (; length; chars++, length--)
h = JS_ROTATE_LEFT32(h, 4) ^ *chars;
return h;
}
class AtomStateEntry
{
uintptr_t bits;
@ -95,7 +105,7 @@ struct AtomHasher
inline Lookup(const JSAtom *atom);
};
static HashNumber hash(const Lookup &l) { return mozilla::HashString(l.chars, l.length); }
static HashNumber hash(const Lookup &l) { return HashChars(l.chars, l.length); }
static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
};

View File

@ -519,7 +519,7 @@ FindBody(JSContext *cx, HandleFunction fun, StableCharPtr chars, size_t length,
options.setFileAndLine("internal-findBody", 0)
.setVersion(fun->nonLazyScript()->getVersion());
AutoKeepAtoms keepAtoms(cx->perThreadData);
TokenStream ts(cx, options, chars.get(), length, NULL, keepAtoms);
TokenStream ts(cx, options, chars.get(), length, NULL);
int nest = 0;
bool onward = true;
// Skip arguments list.
@ -1444,7 +1444,7 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
* compile the function body.
*/
TokenStream ts(cx, options, collected_args.get(), args_length,
/* strictModeGetter = */ NULL, keepAtoms);
/* strictModeGetter = */ NULL);
/* The argument string may be empty or contain no tokens. */
TokenKind tt = ts.getToken();

View File

@ -1023,6 +1023,7 @@ js::CloseIterator(JSContext *cx, HandleObject obj)
ni->props_cursor = ni->props_array;
}
} else if (obj->is<GeneratorObject>()) {
// FIXME: Only close legacy generators.
return CloseGenerator(cx, obj);
}
return true;
@ -1625,6 +1626,8 @@ CloseGenerator(JSContext *cx, HandleObject obj)
return true;
}
// FIXME: Assert that gen is a legacy generator.
if (gen->state == JSGEN_CLOSED)
return true;
@ -1640,6 +1643,7 @@ IsGenerator(const Value &v)
JS_ALWAYS_INLINE bool
generator_send_impl(JSContext *cx, CallArgs args)
{
// FIXME: Change assertion to IsLegacyGenerator().
JS_ASSERT(IsGenerator(args.thisv()));
RootedObject thisObj(cx, &args.thisv().toObject());
@ -1657,6 +1661,8 @@ generator_send_impl(JSContext *cx, CallArgs args)
return false;
}
// FIXME: next() takes the send value as an optional argument in ES6
// generator objects.
if (!SendToGenerator(cx, JSGENOP_SEND, thisObj, gen, args.get(0)))
return false;
@ -1667,6 +1673,7 @@ generator_send_impl(JSContext *cx, CallArgs args)
JSBool
generator_send(JSContext *cx, unsigned argc, Value *vp)
{
// FIXME: send() is only a method on legacy generator objects.
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsGenerator, generator_send_impl>(cx, args);
}
@ -1729,6 +1736,7 @@ generator_throw(JSContext *cx, unsigned argc, Value *vp)
JS_ALWAYS_INLINE bool
generator_close_impl(JSContext *cx, CallArgs args)
{
// FIXME: Change assertion to IsLegacyGenerator().
JS_ASSERT(IsGenerator(args.thisv()));
RootedObject thisObj(cx, &args.thisv().toObject());
@ -1756,6 +1764,7 @@ generator_close_impl(JSContext *cx, CallArgs args)
JSBool
generator_close(JSContext *cx, unsigned argc, Value *vp)
{
// FIXME: close() is only a method on legacy generator objects.
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsGenerator, generator_close_impl>(cx, args);
}

View File

@ -50,8 +50,8 @@ using mozilla::RangedPtr;
/*
* If we're accumulating a decimal number and the number is >= 2^53, then the
* fast result from the loop in GetPrefixInteger may be inaccurate. Call
* js_strtod_harder to get the correct answer.
* fast result from the loop in Get{Prefix,Decimal}Integer may be inaccurate.
* Call js_strtod_harder to get the correct answer.
*/
static bool
ComputeAccurateDecimalInteger(ExclusiveContext *cx,
@ -140,7 +140,7 @@ ComputeAccurateBinaryBaseInteger(const jschar *start, const jschar *end, int bas
bit = bdr.nextDigit();
} while (bit == 0);
JS_ASSERT(bit == 1); // guaranteed by GetPrefixInteger
JS_ASSERT(bit == 1); // guaranteed by Get{Prefix,Decimal}Integer
/* Gather the 53 significant bits (including the leading 1). */
double value = 1.0;
@ -232,6 +232,30 @@ js::GetPrefixInteger(ExclusiveContext *cx, const jschar *start, const jschar *en
return true;
}
bool
js::GetDecimalInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, double *dp)
{
JS_ASSERT(start <= end);
const jschar *s = start;
double d = 0.0;
for (; s < end; s++) {
jschar c = *s;
JS_ASSERT('0' <= c && c <= '9');
int digit = c - '0';
d = d * 10 + digit;
}
*dp = d;
// If we haven't reached the limit of integer precision, we're done.
if (d < DOUBLE_INTEGRAL_PRECISION_LIMIT)
return true;
// Otherwise compute the correct integer from the prefix of valid digits.
return ComputeAccurateDecimalInteger(cx, start, s, dp);
}
static JSBool
num_isNaN(JSContext *cx, unsigned argc, Value *vp)
{

View File

@ -131,6 +131,14 @@ extern bool
GetPrefixInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, int base,
const jschar **endp, double *dp);
/*
* This is like GetPrefixInteger, but only deals with base 10, and doesn't have
* and |endp| outparam. It should only be used when the jschars are known to
* only contain digits.
*/
extern bool
GetDecimalInteger(ExclusiveContext *cx, const jschar *start, const jschar *end, double *dp);
extern bool
StringToNumber(ExclusiveContext *cx, JSString *str, double *result);

View File

@ -407,6 +407,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
NeedsArgsObj,
IsGenerator,
IsGeneratorExp,
IsLegacyGenerator,
OwnSource,
ExplicitUseStrict,
SelfHosted
@ -497,6 +498,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
scriptBits |= (1 << IsGenerator);
if (script->isGeneratorExp)
scriptBits |= (1 << IsGeneratorExp);
if (script->isLegacyGenerator)
scriptBits |= (1 << IsLegacyGenerator);
JS_ASSERT(!script->compileAndGo);
JS_ASSERT(!script->hasSingletons);
@ -596,6 +599,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
script->isGenerator = true;
if (scriptBits & (1 << IsGeneratorExp))
script->isGeneratorExp = true;
if (scriptBits & (1 << IsLegacyGenerator))
script->isLegacyGenerator = true;
}
JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
@ -1967,6 +1972,7 @@ JSScript::fullyInitFromEmitter(ExclusiveContext *cx, HandleScript script, Byteco
JS_ASSERT(!bce->script->noScriptRval);
script->isGenerator = funbox->isGenerator();
script->isGeneratorExp = funbox->inGenexpLambda;
script->isLegacyGenerator = funbox->isLegacyGenerator();
script->setFunction(funbox->function());
}

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