mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Merge m-c to fx-team.
This commit is contained in:
commit
7fe0b0251b
3
CLOBBER
3
CLOBBER
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
});
|
||||
|
@ -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};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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: " +
|
||||
|
@ -298,6 +298,8 @@ let Content = {
|
||||
xPos: aEvent.clientX + offsetX,
|
||||
yPos: aEvent.clientY + offsetY
|
||||
});
|
||||
} else {
|
||||
SelectionHandler.closeSelection();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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": {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
@ -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();
|
||||
}
|
@ -68,7 +68,8 @@ flyoutpanel[visible] {
|
||||
}
|
||||
|
||||
.flyoutpanel-contents[input="precise"] {
|
||||
overflow: scroll;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.flyout-close-button {
|
||||
|
@ -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), \
|
||||
)) \
|
||||
) \
|
||||
)
|
||||
|
34
config/makefiles/precompile/Makefile.in
Normal file
34
config/makefiles/precompile/Makefile.in
Normal 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)
|
5
config/makefiles/precompile/moz.build
Normal file
5
config/makefiles/precompile/moz.build
Normal 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/.
|
@ -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>
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -631,8 +631,6 @@ public:
|
||||
|
||||
virtual nsresult SetArguments(nsIArray *aArguments);
|
||||
|
||||
static bool DOMWindowDumpEnabled();
|
||||
|
||||
void MaybeForgiveSpamCount();
|
||||
bool IsClosedOrClosing() {
|
||||
return (mIsClosed ||
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -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.")
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -8,11 +8,7 @@ DIRS += ['ipc']
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIIDBCursor.idl',
|
||||
'nsIIDBCursorWithValue.idl',
|
||||
'nsIIDBKeyRange.idl',
|
||||
'nsIIDBOpenDBRequest.idl',
|
||||
'nsIIDBRequest.idl',
|
||||
'nsIIndexedDatabaseManager.idl',
|
||||
]
|
||||
|
||||
|
@ -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);
|
||||
};
|
@ -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;
|
||||
};
|
@ -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;
|
||||
};
|
@ -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;
|
||||
};
|
@ -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 + "\")");
|
||||
|
@ -16,6 +16,7 @@ XPIDL_SOURCES += [
|
||||
'nsIDOMClientRect.idl',
|
||||
'nsIDOMClientRectList.idl',
|
||||
'nsIDOMConstructor.idl',
|
||||
'nsIDOMGlobalObjectConstructor.idl',
|
||||
'nsIDOMGlobalPropertyInitializer.idl',
|
||||
'nsIDOMHistory.idl',
|
||||
'nsIDOMJSWindow.idl',
|
||||
|
19
dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl
Normal file
19
dom/interfaces/base/nsIDOMGlobalObjectConstructor.idl
Normal 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();
|
||||
};
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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().
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -10,7 +10,6 @@
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
interface IDBOpenDBRequest;
|
||||
interface Principal;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
16
dom/webidl/IDBOpenDBRequest.webidl
Normal file
16
dom/webidl/IDBOpenDBRequest.webidl
Normal 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;
|
||||
};
|
32
dom/webidl/IDBRequest.webidl
Normal file
32
dom/webidl/IDBRequest.webidl
Normal 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;
|
||||
};
|
@ -170,6 +170,8 @@ webidl_files = \
|
||||
IDBFileHandle.webidl \
|
||||
IDBIndex.webidl \
|
||||
IDBObjectStore.webidl \
|
||||
IDBOpenDBRequest.webidl \
|
||||
IDBRequest.webidl \
|
||||
IDBTransaction.webidl \
|
||||
IDBVersionChangeEvent.webidl \
|
||||
ImageData.webidl \
|
||||
|
@ -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());
|
||||
|
3102
gfx/gl/GLContext.h
3102
gfx/gl/GLContext.h
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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?");
|
||||
|
@ -177,9 +177,10 @@ public:
|
||||
PlatformThreadId aThreadID);
|
||||
|
||||
struct LayerTreeState {
|
||||
LayerTreeState();
|
||||
nsRefPtr<Layer> mRoot;
|
||||
nsRefPtr<GeckoContentController> mController;
|
||||
CompositorParent *mParent;
|
||||
CompositorParent* mParent;
|
||||
TargetConfig mTargetConfig;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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), \
|
||||
)) \
|
||||
) \
|
||||
)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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? */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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> {
|
||||
|
@ -18,6 +18,8 @@
|
||||
_(Value) \
|
||||
_(Parameter) \
|
||||
_(Callee) \
|
||||
_(ForceUseV) \
|
||||
_(ForceUseT) \
|
||||
_(TableSwitch) \
|
||||
_(TableSwitchV) \
|
||||
_(Goto) \
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -14,6 +14,7 @@ namespace ion {
|
||||
_(Constant) \
|
||||
_(Parameter) \
|
||||
_(Callee) \
|
||||
_(ForceUse) \
|
||||
_(TableSwitch) \
|
||||
_(Goto) \
|
||||
_(Test) \
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
6
js/src/jit-test/tests/ion/bug898857.js
Normal file
6
js/src/jit-test/tests/ion/bug898857.js
Normal file
@ -0,0 +1,6 @@
|
||||
function fillHeap() {
|
||||
var x = 1, tmp;
|
||||
for (var i = 0; i < 50000; ++i)
|
||||
tmp <<= x / 3;
|
||||
}
|
||||
RegExp({ toString: fillHeap });
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user