Merge m-c to autoland, a=merge

MozReview-Commit-ID: HXFQTGJASw4
This commit is contained in:
Wes Kocher 2017-02-08 16:21:53 -08:00
commit 9576aa1519
225 changed files with 19242 additions and 17296 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Touch clobber because of bug 1336456
Touch clobber again because of bug 1336456

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = (e10s && os == 'win') # Bug 1269369: Document loaded event does not fire in Windows
support-files =
events.js
head.js
@ -16,36 +15,62 @@ support-files =
# Caching tests
[browser_caching_attributes.js]
skip-if = e10s && os == 'win' # Bug 1288839
[browser_caching_description.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_caching_name.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_caching_relations.js]
skip-if = e10s && os == 'win' # Bug 1288839
[browser_caching_states.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_caching_value.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
# Events tests
[browser_events_caretmove.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_events_hide.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_events_show.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_events_statechange.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_events_textchange.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
# Tree update tests
[browser_treeupdate_ariadialog.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_ariaowns.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_canvas.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_cssoverflow.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_doc.js]
skip-if = e10s && os == 'win' # Bug 1288839
[browser_treeupdate_gencontent.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_hidden.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_imagemap.js]
skip-if = e10s # Bug 1318569
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_list.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_list_editabledoc.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_listener.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_optgroup.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_removal.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_table.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_textleaf.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_visibility.js]
skip-if = e10s && os == 'win' && os_version == '5.1'
[browser_treeupdate_whitespace.js]
skip-if = true # Failing due to incorrect index of test container children on document load.

View File

@ -170,7 +170,22 @@ function* testContainer(browser) {
testAccessibleTree(acc, tree);
}
function* waitForImageMap(browser, accDoc) {
const id = 'imgmap';
const acc = findAccessibleChildByID(accDoc, id);
if (acc.firstChild) {
return;
}
const onReorder = waitForEvent(EVENT_REORDER, id);
// Wave over image map
yield BrowserTestUtils.synthesizeMouse(`#${id}`, 10, 10,
{ type: 'mousemove' }, browser);
yield onReorder;
}
addAccessibleTask('doc_treeupdate_imagemap.html', function*(browser, accDoc) {
yield waitForImageMap(browser, accDoc);
yield testImageMap(browser, accDoc);
yield testContainer(browser);
});

View File

@ -6,9 +6,7 @@ support-files =
head.js
[browser_referrer_middle_click.js]
skip-if = true # Bug 1315042
[browser_referrer_middle_click_in_container.js]
skip-if = true # Bug 1315042
[browser_referrer_open_link_in_private.js]
skip-if = os == 'linux' # Bug 1145199
[browser_referrer_open_link_in_tab.js]

View File

@ -5,9 +5,10 @@ function startMiddleClickTestCase(aTestNumber) {
info("browser_referrer_middle_click: " +
getReferrerTestDescription(aTestNumber));
someTabLoaded(gTestWindow).then(function(aNewTab) {
gTestWindow.gBrowser.selectedTab = aNewTab;
checkReferrerAndStartNextTest(aTestNumber, null, aNewTab,
startMiddleClickTestCase);
BrowserTestUtils.switchTab(gTestWindow.gBrowser, aNewTab).then(() => {
checkReferrerAndStartNextTest(aTestNumber, null, aNewTab,
startMiddleClickTestCase);
});
});
clickTheLink(gTestWindow, "testlink", {button: 1});

View File

@ -5,10 +5,11 @@ function startMiddleClickTestCase(aTestNumber) {
info("browser_referrer_middle_click: " +
getReferrerTestDescription(aTestNumber));
someTabLoaded(gTestWindow).then(function(aNewTab) {
gTestWindow.gBrowser.selectedTab = aNewTab;
checkReferrerAndStartNextTest(aTestNumber, null, aNewTab,
startMiddleClickTestCase,
{ userContextId: 3 });
BrowserTestUtils.switchTab(gTestWindow.gBrowser, aNewTab).then(() => {
checkReferrerAndStartNextTest(aTestNumber, null, aNewTab,
startMiddleClickTestCase,
{ userContextId: 3 });
});
});
clickTheLink(gTestWindow, "testlink", {button: 1});

View File

@ -142,6 +142,9 @@ function delayedStartupFinished(aWindow) {
function someTabLoaded(aWindow) {
return new Promise(function(resolve) {
aWindow.gBrowser.addEventListener("load", function onLoad(aEvent) {
if (aWindow.location === "about:blank") {
return;
}
let tab = aWindow.gBrowser._getTabForContentWindow(
aEvent.target.defaultView.top);
if (tab) {

View File

@ -541,28 +541,32 @@ Cookies.prototype = {
},
_readCookieFile(aFile, aCallback) {
let fileReader = new FileReader();
let onLoadEnd = () => {
fileReader.removeEventListener("loadend", onLoadEnd);
File.createFromNsIFile(aFile).then(aFile => {
let fileReader = new FileReader();
let onLoadEnd = () => {
fileReader.removeEventListener("loadend", onLoadEnd);
if (fileReader.readyState != fileReader.DONE) {
Cu.reportError("Could not read cookie contents: " + fileReader.error);
aCallback(false);
return;
}
if (fileReader.readyState != fileReader.DONE) {
Cu.reportError("Could not read cookie contents: " + fileReader.error);
aCallback(false);
return;
}
let success = true;
try {
this._parseCookieBuffer(fileReader.result);
} catch (ex) {
Components.utils.reportError("Unable to migrate cookie: " + ex);
success = false;
} finally {
aCallback(success);
}
};
fileReader.addEventListener("loadend", onLoadEnd);
fileReader.readAsText(File.createFromNsIFile(aFile));
let success = true;
try {
this._parseCookieBuffer(fileReader.result);
} catch (ex) {
Components.utils.reportError("Unable to migrate cookie: " + ex);
success = false;
} finally {
aCallback(success);
}
};
fileReader.addEventListener("loadend", onLoadEnd);
fileReader.readAsText(aFile);
}, () => {
aCallback(false);
});
},
/**

View File

@ -1,10 +0,0 @@
[
{
"version": "clang 3.8.0, libgcc 4.8.5",
"size": 140319580,
"digest": "34e219d7e8eaffa81710631c34d21355563d06335b3c00851e94c1f42f9098788fded8463dd0f67dd699f77b47a0245dd7aff754943a7a03fb5fd145a808254f",
"algorithm": "sha512",
"filename": "clang.tar.xz",
"unpack": true
}
]

View File

@ -1,19 +1,19 @@
[
{
"version": "clang 3.8.0, libgcc 4.8.5",
"size": 140319580,
"digest": "34e219d7e8eaffa81710631c34d21355563d06335b3c00851e94c1f42f9098788fded8463dd0f67dd699f77b47a0245dd7aff754943a7a03fb5fd145a808254f",
"version": "clang 3.9.0",
"size": 168062128,
"digest": "2a5458a25792fcade86a56ff0f4acdfa284d2b62966991a7c34a92c2e8c0b4a162ce00512d4467754e7f74598d64c56e91517e1606ed3fba011f7c10e8ad3288",
"algorithm": "sha512",
"filename": "clang.tar.xz",
"unpack": true
},
{
"size": 3008804,
"size": 6075028,
"visibility": "public",
"digest": "ba6937f14f3d8b26dcb2d39490dee6b0a8afb60f672f5debb71d7b62c1ec52103201b4b1a3d258f945567de531384b36ddb2ce4aa73dc63d72305b11c146847c",
"digest": "0b962ba55a5a2fbae44218683bdf6ea0dfe8165aba436173a065f7190976184586b9acf4c23478bc5b6d81a3e00f681bf16df0536c9c9718ad0570d064f69027",
"algorithm": "sha512",
"unpack": true,
"filename": "cctools.tar.gz"
"filename": "cctools.tar.xz"
},
{
"size": 35215976,

View File

@ -15,6 +15,8 @@
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
"as": "/home/worker/workspace/build/src/gcc/bin/gcc",
"patches": [
"llvm-debug-frame.patch"
"llvm-debug-frame.patch",
"r277806.patch",
"r285657.patch"
]
}

View File

@ -22,14 +22,14 @@ CROSS_CCTOOLS_PATH=$topsrcdir/cctools
# `browser/config/tooltool-manifests/macosx64/cross-releng.manifest`.
CROSS_SYSROOT=$topsrcdir/MacOSX10.7.sdk
CROSS_PRIVATE_FRAMEWORKS=$CROSS_SYSROOT/System/Library/PrivateFrameworks
FLAGS="-target x86_64-apple-darwin10 -mlinker-version=136 -B $CROSS_CCTOOLS_PATH/bin -isysroot $CROSS_SYSROOT"
FLAGS="-target x86_64-apple-darwin11 -B $CROSS_CCTOOLS_PATH/bin -isysroot $CROSS_SYSROOT"
export CC="$topsrcdir/clang/bin/clang $FLAGS"
export CXX="$topsrcdir/clang/bin/clang++ $FLAGS"
export CPP="$topsrcdir/clang/bin/clang $FLAGS -E"
export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
export LDFLAGS="-Wl,-syslibroot,$CROSS_SYSROOT -Wl,-dead_strip"
export TOOLCHAIN_PREFIX=$CROSS_CCTOOLS_PATH/bin/x86_64-apple-darwin10-
export TOOLCHAIN_PREFIX=$CROSS_CCTOOLS_PATH/bin/x86_64-apple-darwin11-
export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
export DMG_TOOL=$topsrcdir/dmg/dmg

View File

@ -28,6 +28,7 @@ const App = createClass({
boxModel: PropTypes.shape(Types.boxModel).isRequired,
grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
showBoxModelProperties: PropTypes.bool.isRequired,
onShowBoxModelEditor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighter: PropTypes.func.isRequired,

View File

@ -9,6 +9,7 @@ const { addons, createClass, createFactory, DOM: dom, PropTypes } =
const BoxModelInfo = createFactory(require("./BoxModelInfo"));
const BoxModelMain = createFactory(require("./BoxModelMain"));
const BoxModelProperties = createFactory(require("./BoxModelProperties"));
const Types = require("../types");
@ -18,6 +19,7 @@ module.exports = createClass({
propTypes: {
boxModel: PropTypes.shape(Types.boxModel).isRequired,
showBoxModelProperties: PropTypes.bool.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelEditor: PropTypes.func.isRequired,
onShowBoxModelHighlighter: PropTypes.func.isRequired,
@ -28,6 +30,7 @@ module.exports = createClass({
render() {
let {
boxModel,
showBoxModelProperties,
onHideBoxModelHighlighter,
onShowBoxModelEditor,
onShowBoxModelHighlighter,
@ -45,7 +48,13 @@ module.exports = createClass({
}),
BoxModelInfo({
boxModel,
})
}),
showBoxModelProperties ?
BoxModelProperties({
boxModel,
})
:
null,
);
},

View File

@ -0,0 +1,89 @@
/* 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/. */
"use strict";
const { addons, createClass, createFactory, DOM: dom, PropTypes } =
require("devtools/client/shared/vendor/react");
const { LocalizationHelper } = require("devtools/shared/l10n");
const ComputedProperty = createFactory(require("./ComputedProperty"));
const Types = require("../types");
const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
module.exports = createClass({
displayName: "BoxModelProperties",
propTypes: {
boxModel: PropTypes.shape(Types.boxModel).isRequired,
},
mixins: [ addons.PureRenderMixin ],
getInitialState() {
return {
isOpen: true,
};
},
onToggleExpander() {
this.setState({
isOpen: !this.state.isOpen,
});
},
render() {
let { boxModel } = this.props;
let { layout } = boxModel;
let layoutInfo = ["box-sizing", "display", "float",
"line-height", "position", "z-index"];
const properties = layoutInfo.map(info => ComputedProperty({
name: info,
key: info,
value: layout[info],
}));
return dom.div(
{
className: "boxmodel-properties",
},
dom.div(
{
className: "boxmodel-properties-header",
onDoubleClick: this.onToggleExpander,
},
dom.div(
{
className: "boxmodel-properties-expander theme-twisty",
open: this.state.isOpen,
onClick: this.onToggleExpander,
},
),
dom.span(
{
className: "boxmodel-properties-label",
title: BOXMODEL_L10N.getStr("boxmodel.propertiesLabel"),
},
BOXMODEL_L10N.getStr("boxmodel.propertiesLabel"),
),
),
dom.div(
{
className: "boxmodel-properties-wrapper",
hidden: !this.state.isOpen,
tabIndex: 0,
},
properties,
),
);
},
});

View File

@ -0,0 +1,67 @@
/* 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/. */
"use strict";
const { addons, createClass, DOM: dom, PropTypes } =
require("devtools/client/shared/vendor/react");
module.exports = createClass({
displayName: "ComputedProperty",
propTypes: {
name: PropTypes.string.isRequired,
value: PropTypes.string,
},
mixins: [ addons.PureRenderMixin ],
onFocus() {
this.container.focus();
},
render() {
const { name, value } = this.props;
return dom.div(
{
className: "property-view",
tabIndex: "0",
ref: container => {
this.container = container;
},
},
dom.div(
{
className: "property-name-container",
},
dom.div(
{
className: "property-name theme-fg-color5",
tabIndex: "",
title: name,
onClick: this.onFocus,
},
name
)
),
dom.div(
{
className: "property-value-container",
},
dom.div(
{
className: "property-value theme-fg-color1",
dir: "ltr",
tabIndex: "",
onClick: this.onFocus,
},
value
)
)
);
},
});

View File

@ -12,6 +12,8 @@ DevToolsModules(
'BoxModelEditable.js',
'BoxModelInfo.js',
'BoxModelMain.js',
'BoxModelProperties.js',
'ComputedProperty.js',
'Grid.js',
'GridDisplaySettings.js',
'GridList.js',

View File

@ -77,6 +77,12 @@ LayoutView.prototype = {
this.loadHighlighterSettings();
let app = App({
/**
* Shows the box model properties under the box model if true, otherwise, hidden by
* default.
*/
showBoxModelProperties: true,
/**
* Hides the box-model highlighter on the currently selected element.
*/

View File

@ -35,3 +35,7 @@ boxmodel.content=content
# tooltip that appears when hovering over the button that allows users to edit the
# position of an element in the page.
boxmodel.geometryButton.tooltip=Edit position
# LOCALIZATION NOTE: (boxmodel.propertiesLabel) This label is displayed as the header
# for showing and collapsing the properties underneath the box model in the layout view
boxmodel.propertiesLabel=Box Model Properties

View File

@ -26,20 +26,21 @@ define(function (require, exports, module) {
displayName: "Obj",
propTypes: {
object: React.PropTypes.object,
object: React.PropTypes.object.isRequired,
// @TODO Change this to Object.values once it's supported in Node's version of V8
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
objectLink: React.PropTypes.func,
title: React.PropTypes.string,
},
getTitle: function (object) {
let className = object && object.class ? object.class : "Object";
let title = this.props.title || object.class || "Object";
if (this.props.objectLink) {
return this.props.objectLink({
object: object
}, className);
}, title);
}
return className;
return title;
},
safePropIterator: function (object, max) {

View File

@ -249,3 +249,14 @@
display: flex;
align-items: center;
}
/* Box Model Properties: contains a list of relevant box model properties */
.boxmodel-properties-header {
display: flex;
padding: 2px 0;
}
.boxmodel-properties-wrapper {
padding: 0 9px;
}

View File

@ -785,7 +785,9 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
"border-left-width",
"z-index",
"box-sizing",
"display"
"display",
"float",
"line-height"
]) {
layout[prop] = style.getPropertyValue(prop);
}

View File

@ -426,8 +426,6 @@ var testcases = [ {
protocolChange: true,
}, {
input: "?'.com",
fixedURI: "http:///?%27.com",
alternateURI: "http://www..com/?%27.com",
keywordLookup: true,
protocolChange: true,
}, {
@ -436,14 +434,10 @@ var testcases = [ {
protocolChange: true
}, {
input: "?mozilla",
fixedURI: "http:///?mozilla",
alternateURI: "http://www..com/?mozilla",
keywordLookup: true,
protocolChange: true,
}, {
input: "??mozilla",
fixedURI: "http:///??mozilla",
alternateURI: "http://www..com/??mozilla",
keywordLookup: true,
protocolChange: true,
}, {

View File

@ -61,3 +61,14 @@ attribute OfflineResourceList.onprogress
attribute OfflineResourceList.onupdateready
attribute OfflineResourceList.oncached
attribute OfflineResourceList.onobsolete
// DataTransfer API (gecko-only methods)
method DataTransfer.addElement
attribute DataTransfer.mozItemCount
attribute DataTransfer.mozCursor
method DataTransfer.mozTypesAt
method DataTransfer.mozClearDataAt
method DataTransfer.mozSetDataAt
method DataTransfer.mozGetDataAt
attribute DataTransfer.mozUserCancelled
attribute DataTransfer.mozSourceNode

View File

@ -718,9 +718,8 @@ nsGlobalWindow::RunIdleRequest(IdleRequest* aRequest,
{
AssertIsOnMainThread();
RefPtr<IdleRequest> request(aRequest);
nsresult result = request->IdleRun(AsInner(), aDeadline, aDidTimeout);
RemoveIdleCallback(request);
return result;
return request->IdleRun(AsInner(), aDeadline, aDidTimeout);
}
nsresult

View File

@ -655,6 +655,19 @@ nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
return NS_OK;
}
bool
nsScriptLoader::ModuleScriptsEnabled()
{
static bool sEnabledForContent = false;
static bool sCachedPref = false;
if (!sCachedPref) {
sCachedPref = true;
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
}
return nsContentUtils::IsChromeDoc(mDocument) || sEnabledForContent;
}
bool
nsScriptLoader::ModuleMapContainsModule(nsModuleLoadRequest *aRequest) const
{
@ -1229,15 +1242,27 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest)
nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
nsSecurityFlags securityFlags;
// TODO: the spec currently gives module scripts different CORS behaviour to
// classic scripts.
securityFlags = aRequest->mCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aRequest->mCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aRequest->mCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
if (aRequest->IsModuleRequest()) {
// According to the spec, module scripts have different behaviour to classic
// scripts and always use CORS.
securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aRequest->mCORSMode == CORS_NONE) {
securityFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
} else if (aRequest->mCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else {
MOZ_ASSERT(aRequest->mCORSMode == CORS_USE_CREDENTIALS);
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
} else {
securityFlags = aRequest->mCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aRequest->mCORSMode == CORS_ANONYMOUS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else if (aRequest->mCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
}
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
@ -1449,8 +1474,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
nsScriptKind scriptKind = nsScriptKind::Classic;
if (!type.IsEmpty()) {
// Support type="module" only for chrome documents.
if (nsContentUtils::IsChromeDoc(mDocument) && type.LowerCaseEqualsASCII("module")) {
if (ModuleScriptsEnabled() && type.LowerCaseEqualsASCII("module")) {
scriptKind = nsScriptKind::Module;
} else {
NS_ENSURE_TRUE(ParseTypeAttribute(type, &version), false);
@ -2789,7 +2813,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
}
// TODO: Preload module scripts.
if (nsContentUtils::IsChromeDoc(mDocument) && aType.LowerCaseEqualsASCII("module")) {
if (ModuleScriptsEnabled() && aType.LowerCaseEqualsASCII("module")) {
return;
}

View File

@ -585,6 +585,8 @@ private:
JS::SourceBufferHolder GetScriptSource(nsScriptLoadRequest* aRequest,
nsAutoString& inlineData);
bool ModuleScriptsEnabled();
void SetModuleFetchStarted(nsModuleLoadRequest *aRequest);
void SetModuleFetchFinishedAndResumeWaitingRequests(nsModuleLoadRequest *aRequest,
nsresult aResult);

View File

@ -8,10 +8,14 @@ var testFile = Cc["@mozilla.org/file/directory_service;1"]
testFile.append("prefs.js");
addMessageListener("file.open", function () {
sendAsyncMessage("file.opened", {
file: File.createFromNsIFile(testFile),
mtime: testFile.lastModifiedTime,
fileWithDate: File.createFromNsIFile(testFile, { lastModified: 123 }),
fileDate: 123,
File.createFromNsIFile(testFile).then(function(file) {
File.createFromNsIFile(testFile, { lastModified: 123 }).then(function(fileWithDate) {
sendAsyncMessage("file.opened", {
file,
mtime: testFile.lastModifiedTime,
fileWithDate,
fileDate: 123,
});
});
});
});

View File

@ -7,7 +7,9 @@ addMessageListener("file.create", function (message) {
.get("TmpD", Components.interfaces.nsIFile);
file.append("foo.txt");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
sendAsyncMessage("file.created", File.createFromNsIFile(file));
File.createFromNsIFile(file).then(function(domFile) {
sendAsyncMessage("file.created", domFile);
});
});
addMessageListener("file.remove", function (message) {

View File

@ -35,13 +35,22 @@ function createFileWithData(fileData) {
/** Test for Bug 914381. File's created in JS using an nsIFile should allow mozGetFullPathInternal calls to succeed **/
var file = createFileWithData("Test bug 914381");
var f = File.createFromNsIFile(file);
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, file.path, "mozFullPath returns path if created with nsIFile");
File.createFromNsIFile(file).then(f => {
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, file.path, "mozFullPath returns path if created with nsIFile");
})
.then(() => {
return File.createFromFileName(file.path);
})
.then(f => {
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, "", "mozFullPath returns blank if created with a string");
})
.then(() => {
SimpleTest.finish();
});
f = File.createFromFileName(file.path);
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, "", "mozFullPath returns blank if created with a string");
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>

View File

@ -42,30 +42,40 @@ file.append("test");
file.append("chrome");
file.append("fileconstructor_file.png");
doTest(File.createFromFileName(file.path));
doTest(File.createFromNsIFile(file));
function doTest(domfile) {
File.createFromFileName(file.path).then(function(domFile) {
ok(domfile instanceof File, "File() should return a File");
is(domfile.type, "image/png", "File should be a PNG");
is(domfile.size, 95, "File has size 95 (and more importantly we can read it)");
}
try {
var nonexistentfile = File.createFromFileName("i/sure/hope/this/does/not/exist/anywhere.txt");
})
.then(() => {
return File.createFromNsIFile(file);
})
.then(function(domFile) {
ok(domfile instanceof File, "File() should return a File");
is(domfile.type, "image/png", "File should be a PNG");
is(domfile.size, 95, "File has size 95 (and more importantly we can read it)");
})
.then(function() {
return File.createFromFileName("i/sure/hope/this/does/not/exist/anywhere.txt");
})
.then(function() {
ok(false, "This should never be reached!");
} catch (e) {
}, function() {
ok(true, "Attempt to construct a non-existent file should fail.");
}
try {
}).then(function() {
var dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsIFile);
var dirfile = File.createFromNsIFile(dir);
return File.createFromNsIFile(dir);
}).then(function() {
ok(false, "This should never be reached!");
} catch (e) {
}, function() {
ok(true, "Attempt to construct a file from a directory should fail.");
}
}).then(function() {
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
]]>
</script>

View File

@ -13,14 +13,17 @@ function createFileWithData(message) {
outStream.write(message, message.length);
outStream.close();
var domFile = File.createFromNsIFile(testFile);
return domFile;
return File.createFromNsIFile(testFile);
}
addMessageListener("file.open", function (message) {
sendAsyncMessage("file.opened", createFileWithData(message));
createFileWithData(message).then(function(file) {
sendAsyncMessage("file.opened", file);
});
});
addMessageListener("file.modify", function (message) {
sendAsyncMessage("file.modified", createFileWithData(message));
createFileWithData(message).then(function(file) {
sendAsyncMessage("file.modified", file);
});
});

View File

@ -735,7 +735,7 @@ skip-if = toolkit == 'android'
[test_screen_orientation.html]
[test_script_loader_crossorigin_data_url.html]
[test_selection_with_anon_trees.html]
skip-if = toolkit == 'android'
skip-if = (toolkit == 'android' || asan) # bug 1330526
[test_setInterval_uncatchable_exception.html]
skip-if = debug == false
[test_settimeout_extra_arguments.html]

View File

@ -10,8 +10,8 @@ function writeFile(text, answer) {
stream.write(text, text.length);
stream.close();
sendAsyncMessage(answer, {
file: File.createFromNsIFile(tmpFile)
File.createFromNsIFile(tmpFile).then(function(file) {
sendAsyncMessage(answer, { file });
});
}

View File

@ -8,8 +8,8 @@ addMessageListener("file.open", function () {
.get("ProfD", Ci.nsIFile);
testFile.append("prefs.js");
sendAsyncMessage("file.opened", {
file: File.createFromNsIFile(testFile)
File.createFromNsIFile(testFile).then(function(file) {
sendAsyncMessage("file.opened", { file });
});
});

View File

@ -36,7 +36,9 @@
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/FileBinding.h"
#include "mozilla/dom/FileCreatorHelper.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "nsThreadUtils.h"
@ -581,7 +583,7 @@ File::Constructor(const GlobalObject& aGlobal,
return file.forget();
}
/* static */ already_AddRefed<File>
/* static */ already_AddRefed<Promise>
File::CreateFromNsIFile(const GlobalObject& aGlobal,
nsIFile* aData,
const ChromeFilePropertyBag& aBag,
@ -590,45 +592,31 @@ File::CreateFromNsIFile(const GlobalObject& aGlobal,
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
impl->InitializeChromeFile(window, aData, aBag, true, aGuarantee, aRv);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(impl->IsFile());
if (aBag.mLastModified.WasPassed()) {
impl->SetLastModified(aBag.mLastModified.Value());
}
RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
return domFile.forget();
RefPtr<Promise> promise =
FileCreatorHelper::CreateFile(global, aData, aBag, true, aRv);
return promise.forget();
}
/* static */ already_AddRefed<File>
/* static */ already_AddRefed<Promise>
File::CreateFromFileName(const GlobalObject& aGlobal,
const nsAString& aData,
const nsAString& aPath,
const ChromeFilePropertyBag& aBag,
SystemCallerGuarantee aGuarantee,
ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
impl->InitializeChromeFile(window, aData, aBag, aGuarantee, aRv);
if (aRv.Failed()) {
nsCOMPtr<nsIFile> file;
aRv = NS_NewLocalFile(aPath, false, getter_AddRefs(file));
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
MOZ_ASSERT(impl->IsFile());
if (aBag.mLastModified.WasPassed()) {
impl->SetLastModified(aBag.mLastModified.Value());
}
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
return domFile.forget();
RefPtr<Promise> promise =
FileCreatorHelper::CreateFile(global, file, aBag, false, aRv);
return promise.forget();
}
////////////////////////////////////////////////////////////////////////////

View File

@ -43,6 +43,7 @@ struct FilePropertyBag;
class BlobImpl;
class File;
class OwningArrayBufferOrArrayBufferViewOrBlobOrUSVString;
class Promise;
class Blob : public nsIDOMBlob
, public nsIXHRSendable
@ -204,17 +205,17 @@ public:
ErrorResult& aRv);
// ChromeOnly
static already_AddRefed<File>
static already_AddRefed<Promise>
CreateFromFileName(const GlobalObject& aGlobal,
const nsAString& aData,
const nsAString& aFilePath,
const ChromeFilePropertyBag& aBag,
SystemCallerGuarantee aGuarantee,
ErrorResult& aRv);
// ChromeOnly
static already_AddRefed<File>
static already_AddRefed<Promise>
CreateFromNsIFile(const GlobalObject& aGlobal,
nsIFile* aData,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
SystemCallerGuarantee aGuarantee,
ErrorResult& aRv);

View File

@ -0,0 +1,187 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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 "FileCreatorHelper.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/FileBinding.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/Promise.h"
#include "nsContentUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIFile.h"
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
// replaced by FileCreatorHelper#CreateFileW.
#ifdef CreateFile
#undef CreateFile
#endif
namespace mozilla {
namespace dom {
/* static */ already_AddRefed<Promise>
FileCreatorHelper::CreateFile(nsIGlobalObject* aGlobalObject,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<Promise> promise = Promise::Create(aGlobalObject, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
// Parent process
if (XRE_IsParentProcess()) {
RefPtr<File> file =
CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
if (aRv.Failed()) {
return nullptr;
}
promise->MaybeResolve(file);
return promise.forget();
}
// Content process.
RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
// The request is sent to the parent process and it's kept alive by
// ContentChild.
helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return promise.forget();
}
/* static */ already_AddRefed<File>
FileCreatorHelper::CreateFileInternal(nsPIDOMWindowInner* aWindow,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
ErrorResult& aRv)
{
bool lastModifiedPassed = false;
int64_t lastModified = 0;
if (aBag.mLastModified.WasPassed()) {
lastModifiedPassed = true;
lastModified = aBag.mLastModified.Value();
}
RefPtr<BlobImpl> blobImpl;
aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
lastModified, aIsFromNsIFile, getter_AddRefs(blobImpl));
if (aRv.Failed()) {
return nullptr;
}
RefPtr<File> file = File::Create(aWindow, blobImpl);
return file.forget();
}
FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
nsPIDOMWindowInner* aWindow)
: mPromise(aPromise)
, mWindow(aWindow)
{
MOZ_ASSERT(aPromise);
}
void
FileCreatorHelper::SendRequest(nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
ErrorResult& aRv)
{
MOZ_ASSERT(aFile);
ContentChild* cc = ContentChild::GetSingleton();
if (NS_WARN_IF(!cc)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsID uuid;
aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsAutoString path;
aRv = aFile->GetPath(path);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
aBag.mLastModified, aIsFromNsIFile);
}
void
FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv)
{
if (NS_FAILED(aRv)) {
mPromise->MaybeReject(aRv);
return;
}
RefPtr<File> file = File::Create(mWindow, aBlobImpl);
mPromise->MaybeResolve(file);
}
/* static */ nsresult
FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl)
{
nsCOMPtr<nsIFile> file;
nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
aIsFromNsIFile, aBlobImpl);
}
/* static */ nsresult
FileCreatorHelper::CreateBlobImpl(nsIFile* aFile,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl)
{
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
nsresult rv =
impl->InitializeChromeFile(aFile, aType, aName, aLastModifiedPassed,
aLastModified, aIsFromNsIFile);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_ASSERT(impl->IsFile());
impl.forget(aBlobImpl);
return NS_OK;
}
} // dom namespace
} // mozilla namespace

View File

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#ifndef mozilla_dom_FileCreatorHelper_h
#define mozilla_dom_FileCreatorHelper_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/RefPtr.h"
#include "nsISupportsImpl.h"
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
// replaced by FileCreatorHelper#CreateFileW.
#ifdef CreateFile
#undef CreateFile
#endif
class nsIFile;
class nsIGlobalObject;
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
struct ChromeFilePropertyBag;
class Promise;
class File;
class FileCreatorHelper final
{
public:
NS_INLINE_DECL_REFCOUNTING(FileCreatorHelper);
static already_AddRefed<Promise>
CreateFile(nsIGlobalObject* aGlobalObject,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
ErrorResult& aRv);
void
ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv);
// For IPC only
static nsresult
CreateBlobImplForIPC(const nsAString& aPath,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl);
private:
static already_AddRefed<File>
CreateFileInternal(nsPIDOMWindowInner* aWindow,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
ErrorResult& aRv);
static nsresult
CreateBlobImpl(nsIFile* aFile,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl);
FileCreatorHelper(Promise* aPromise, nsPIDOMWindowInner* aWindow);
~FileCreatorHelper() = default;
void
SendRequest(nsIFile* aFile, const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile, ErrorResult& aRv);
RefPtr<Promise> mPromise;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_FileCreatorHelper_h

View File

@ -323,62 +323,60 @@ MultipartBlobImpl::SetMutable(bool aMutable)
return NS_OK;
}
void
MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindowInner* aWindow,
nsIFile* aFile,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv)
nsresult
MultipartBlobImpl::InitializeChromeFile(nsIFile* aFile,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile)
{
MOZ_ASSERT(!mImmutable, "Something went wrong ...");
if (mImmutable) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
return NS_ERROR_UNEXPECTED;
}
mName = aBag.mName;
mContentType = aBag.mType;
mName = aName;
mContentType = aType;
mIsFromNsIFile = aIsFromNsIFile;
bool exists;
aRv = aFile->Exists(&exists);
if (NS_WARN_IF(aRv.Failed())) {
return;
nsresult rv= aFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
aRv.Throw(NS_ERROR_FILE_NOT_FOUND);
return;
return NS_ERROR_FILE_NOT_FOUND;
}
bool isDir;
aRv = aFile->IsDirectory(&isDir);
if (NS_WARN_IF(aRv.Failed())) {
return;
rv = aFile->IsDirectory(&isDir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (isDir) {
aRv.Throw(NS_ERROR_FILE_IS_DIRECTORY);
return;
return NS_ERROR_FILE_IS_DIRECTORY;
}
if (mName.IsEmpty()) {
aFile->GetLeafName(mName);
}
RefPtr<File> blob = File::CreateFromFile(aWindow, aFile);
RefPtr<File> blob = File::CreateFromFile(nullptr, aFile);
// Pre-cache size.
blob->GetSize(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
ErrorResult error;
blob->GetSize(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
// Pre-cache modified date.
blob->GetLastModified(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
blob->GetLastModified(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
// XXXkhuey this is terrible
@ -390,24 +388,16 @@ MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindowInner* aWindow,
blobSet.AppendBlobImpl(static_cast<File*>(blob.get())->Impl());
mBlobImpls = blobSet.GetBlobImpls();
SetLengthAndModifiedDate(aRv);
NS_WARNING_ASSERTION(!aRv.Failed(), "SetLengthAndModifiedDate failed");
}
void
MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindowInner* aWindow,
const nsAString& aData,
const ChromeFilePropertyBag& aBag,
SystemCallerGuarantee aGuarantee,
ErrorResult& aRv)
{
nsCOMPtr<nsIFile> file;
aRv = NS_NewLocalFile(aData, false, getter_AddRefs(file));
if (NS_WARN_IF(aRv.Failed())) {
return;
SetLengthAndModifiedDate(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
InitializeChromeFile(aWindow, file, aBag, false, aGuarantee, aRv);
if (aLastModifiedPassed) {
SetLastModified(aLastModified);
}
return NS_OK;
}
bool

View File

@ -61,18 +61,12 @@ public:
bool aNativeEOL,
ErrorResult& aRv);
void InitializeChromeFile(nsPIDOMWindowInner* aWindow,
const nsAString& aData,
const ChromeFilePropertyBag& aBag,
SystemCallerGuarantee aGuarantee,
ErrorResult& aRv);
void InitializeChromeFile(nsPIDOMWindowInner* aWindow,
nsIFile* aData,
const ChromeFilePropertyBag& aBag,
bool aIsFromNsIFile,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv);
nsresult InitializeChromeFile(nsIFile* aData,
const nsAString& aType,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aIsFromNsIFile);
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,

View File

@ -21,6 +21,7 @@ EXPORTS += [
EXPORTS.mozilla.dom += [
'BlobSet.h',
'File.h',
'FileCreatorHelper.h',
'FileList.h',
'FileReader.h',
'MultipartBlobImpl.h',
@ -31,6 +32,7 @@ EXPORTS.mozilla.dom += [
UNIFIED_SOURCES += [
'BlobSet.cpp',
'File.cpp',
'FileCreatorHelper.cpp',
'FileList.cpp',
'FileReader.cpp',
'MultipartBlobImpl.cpp',

View File

@ -2,9 +2,14 @@ Components.utils.importGlobalProperties(['File']);
addMessageListener("create-file-objects", function(message) {
let files = []
let promises = [];
for (fileName of message.fileNames) {
files.push(File.createFromFileName(fileName));
promises.push(File.createFromFileName(fileName).then(function(file) {
files.push(file);
}));
}
sendAsyncMessage("created-file-objects", files);
Promise.all(promises).then(function() {
sendAsyncMessage("created-file-objects", files);
});
});

View File

@ -17,13 +17,26 @@ function createFileWithData(fileData) {
}
outStream.write(fileData, fileData.length);
outStream.close();
var domFile = File.createFromNsIFile(testFile);
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
return File.createFromNsIFile(testFile).then(domFile => {
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
});
}
addMessageListener("files.open", function (message) {
sendAsyncMessage("files.opened", message.map(createFileWithData));
let promises = [];
let list = [];
for (let fileData of message) {
promises.push(createFileWithData(fileData).then(domFile => {
list.push(domFile);
}));
}
Promise.all(promises).then(() => {
sendAsyncMessage("files.opened", list);
});
});

View File

@ -35,8 +35,10 @@ addMessageListener("entries.open", function (e) {
dir2.append('subsubdir');
dir2.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
sendAsyncMessage("entries.opened", {
data: [ new Directory(tmpDir.path), File.createFromNsIFile(tmpFile) ]
File.createFromNsIFile(tmpFile).then(function(file) {
sendAsyncMessage("entries.opened", {
data: [ new Directory(tmpDir.path), file ]
});
});
});

View File

@ -123,7 +123,7 @@ addMessageListener("file.open", function (e) {
.get("ProfD", Ci.nsIFile);
testFile.append("prefs.js");
sendAsyncMessage("file.opened", {
file: File.createFromNsIFile(testFile)
File.createFromNsIFile(testFile).then(function(file) {
sendAsyncMessage("file.opened", { file });
});
});

View File

@ -2,5 +2,15 @@ var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.importGlobalProperties(["File"]);
addMessageListener("files.open", function (message) {
sendAsyncMessage("files.opened", message.map(path => File.createFromFileName(path)));
let list = [];
let promises = [];
for (let path of message) {
promises.push(File.createFromFileName(path).then(file => {
list.push(file);
}));
}
Promise.all(promises).then(() => {
sendAsyncMessage("files.opened", list);
});
});

View File

@ -7,7 +7,8 @@ addMessageListener("file.open", function (e) {
.QueryInterface(Ci.nsIProperties)
.get('ProfD', Ci.nsIFile);
tmpFile.append('prefs.js');
sendAsyncMessage("file.opened", {
data: [ File.createFromNsIFile(tmpFile) ]
File.createFromNsIFile(tmpFile).then(file => {
sendAsyncMessage("file.opened", { data: [ file ] });
});
});

View File

@ -11,10 +11,13 @@ addMessageListener("file.open", function (stem) {
file.append(stem);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
}
sendAsyncMessage("file.opened", {
fullPath: file.path,
leafName: file.leafName,
domFile: File.createFromNsIFile(file),
File.createFromNsIFile(file).then(function(domFile) {
sendAsyncMessage("file.opened", {
fullPath: file.path,
leafName: file.leafName,
domFile,
});
});
} catch(e) {
sendAsyncMessage("fail", e.toString());

View File

@ -154,13 +154,14 @@ function checkInputURL()
sendString("ttp://mozilla.org");
checkValidApplies(element);
for (var i=0; i<13; ++i) {
for (var i=0; i<10; ++i) {
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
}
synthesizeKey("VK_BACK_SPACE", {});
for (var i=0; i<4; ++i) {
// "http://" is now invalid
for (var i=0; i<7; ++i) {
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
}

View File

@ -27472,6 +27472,11 @@ IndexGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (cloneInfo->mHasPreprocessInfo) {
IDB_WARNING("Preprocessing for indexes not yet implemented!");
return NS_ERROR_NOT_IMPLEMENTED;
}
}
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -27848,6 +27853,11 @@ CursorOpBase::PopulateResponseFromStatement(
return rv;
}
if (cloneInfo.mHasPreprocessInfo) {
IDB_WARNING("Preprocessing for cursors not yet implemented!");
return NS_ERROR_NOT_IMPLEMENTED;
}
if (aInitializeResponse) {
mResponse = nsTArray<ObjectStoreCursorResponse>();
} else {
@ -27891,6 +27901,11 @@ CursorOpBase::PopulateResponseFromStatement(
return rv;
}
if (cloneInfo.mHasPreprocessInfo) {
IDB_WARNING("Preprocessing for cursors not yet implemented!");
return NS_ERROR_NOT_IMPLEMENTED;
}
MOZ_ASSERT(aInitializeResponse);
mResponse = IndexCursorResponse();

View File

@ -112,7 +112,10 @@ support-files =
unit/test_transaction_ordering.js
unit/test_unique_index_update.js
unit/test_view_put_get_values.js
unit/test_wasm_cursors.js
unit/test_wasm_getAll.js
unit/test_wasm_index_getAllObjects.js
unit/test_wasm_indexes.js
unit/test_wasm_put_get_values.js
unit/test_writer_starvation.js
@ -257,5 +260,8 @@ skip-if = e10s
[test_transaction_ordering.html]
[test_unique_index_update.html]
[test_view_put_get_values.html]
[test_wasm_cursors.html]
[test_wasm_getAll.html]
[test_wasm_index_getAllObjects.html]
[test_wasm_indexes.html]
[test_wasm_put_get_values.html]

View File

@ -0,0 +1,20 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_wasm_cursors.js"></script>
<script type="text/javascript;version=1.7" src="file.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,20 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_wasm_index_getAllObjects.js"></script>
<script type="text/javascript;version=1.7" src="file.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,20 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Property Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_wasm_indexes.js"></script>
<script type="text/javascript;version=1.7" src="file.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,66 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function* testSteps()
{
const name =
this.window ? window.location.pathname : "test_wasm_cursors.js";
const objectStoreName = "Wasm";
const wasmData = { key: 1, value: null };
if (!isWasmSupported()) {
finishTest();
return;
}
getWasmBinary('(module (func (nop)))');
let binary = yield undefined;
wasmData.value = getWasmModule(binary);
info("Opening database");
let request = indexedDB.open(name);
request.onerror = errorHandler;
request.onupgradeneeded = continueToNextStepSync;
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
// upgradeneeded
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = continueToNextStepSync;
info("Creating objectStore");
request.result.createObjectStore(objectStoreName);
yield undefined;
// success
let db = request.result;
db.onerror = errorHandler;
info("Storing wasm");
let objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
request = objectStore.add(wasmData.value, wasmData.key);
request.onsuccess = continueToNextStepSync;
yield undefined;
is(request.result, wasmData.key, "Got correct key");
info("Opening cursor");
request = objectStore.openCursor();
request.addEventListener("error", new ExpectError("UnknownError", true));
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
finishTest();
}

View File

@ -10,9 +10,13 @@ function* testSteps()
const name =
this.window ? window.location.pathname : "test_wasm_getAll.js";
const objectStoreInfo = { name: "Wasm", options: { autoIncrement: true } };
const objectStoreName = "Wasm";
const values = [ 42, [], [] ];
const wasmData = [
{ key: 1, value: 42 },
{ key: 2, value: [null, null, null] },
{ key: 3, value: [null, null, null, null, null] }
];
if (!isWasmSupported()) {
finishTest();
@ -21,35 +25,35 @@ function* testSteps()
getWasmBinary('(module (func (result i32) (i32.const 1)))');
let binary = yield undefined;
values[1].push(getWasmModule(binary));
wasmData[1].value[0] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 2)))');
binary = yield undefined;
values[1].push(getWasmModule(binary));
wasmData[1].value[1] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 3)))');
binary = yield undefined;
values[1].push(getWasmModule(binary));
wasmData[1].value[2] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 4)))');
binary = yield undefined;
values[2].push(getWasmModule(binary));
wasmData[2].value[0] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 5)))');
binary = yield undefined;
values[2].push(getWasmModule(binary));
wasmData[2].value[1] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 6)))');
binary = yield undefined;
values[2].push(getWasmModule(binary));
wasmData[2].value[2] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 7)))');
binary = yield undefined;
values[2].push(getWasmModule(binary));
wasmData[2].value[3] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 8)))');
binary = yield undefined;
values[2].push(getWasmModule(binary));
wasmData[2].value[4] = getWasmModule(binary);
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
@ -63,8 +67,7 @@ function* testSteps()
info("Creating objectStore");
request.result.createObjectStore(objectStoreInfo.name,
objectStoreInfo.options);
request.result.createObjectStore(objectStoreName);
yield undefined;
@ -74,13 +77,13 @@ function* testSteps()
info("Storing values");
let objectStore = db.transaction([objectStoreInfo.name], "readwrite")
.objectStore(objectStoreInfo.name);
let objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
let addedCount = 0;
for (let i in values) {
request = objectStore.add(values[i]);
for (let i in wasmData) {
request = objectStore.add(wasmData[i].value, wasmData[i].key);
request.onsuccess = function(event) {
if (++addedCount == values.length) {
if (++addedCount == wasmData.length) {
continueToNextStep();
}
}
@ -89,32 +92,42 @@ function* testSteps()
info("Getting values");
request = db.transaction(objectStoreInfo.name)
.objectStore(objectStoreInfo.name).getAll();
request = db.transaction(objectStoreName)
.objectStore(objectStoreName)
.getAll();
request.onsuccess = continueToNextStepSync;
yield undefined;
// Can't call yield inside of the verify function.
let resultsToProcess = [];
info("Verifying values");
function verifyResult(result, value) {
if (value instanceof WebAssembly.Module) {
resultsToProcess.push({ result: result, value: value });
} else if (value instanceof Array) {
is(result instanceof Array, true, "Got an array object");
is(result.length, value.length, "Same length");
for (let i in value) {
verifyResult(result[i], value[i]);
// Can't call yield inside of the verify function.
let modulesToProcess = [];
function verifyArray(array1, array2) {
is(array1 instanceof Array, true, "Got an array object");
is(array1.length, array2.length, "Same length");
}
function verifyData(data1, data2) {
if (data2 instanceof Array) {
verifyArray(data1, data2);
for (let i in data2) {
verifyData(data1[i], data2[i]);
}
} else if (data2 instanceof WebAssembly.Module) {
modulesToProcess.push({ module1: data1, module2: data2 });
} else {
is(result, value, "Same value");
is(data1, data2, "Same value");
}
}
verifyResult(request.result, values);
verifyArray(request.result, wasmData);
for (let i in wasmData) {
verifyData(request.result[i], wasmData[i].value);
}
for (let resultToProcess of resultsToProcess) {
verifyWasmModule(resultToProcess.result, resultToProcess.value);
for (let moduleToProcess of modulesToProcess) {
verifyWasmModule(moduleToProcess.module1, moduleToProcess.module2);
yield undefined;
}

View File

@ -0,0 +1,110 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function* testSteps()
{
const name =
this.window ? window.location.pathname : "test_wasm_getAll.js";
const objectStoreName = "Wasm";
const wasmData = [
{ key: 1, value: { name: "foo1", data: 42 } },
{ key: 2, value: { name: "foo2", data: [null, null, null] } },
{ key: 3, value: { name: "foo3", data: [null, null, null, null, null] } }
];
const indexData = { name: "nameIndex", keyPath: "name", options: { } };
if (!isWasmSupported()) {
finishTest();
return;
}
getWasmBinary('(module (func (result i32) (i32.const 1)))');
let binary = yield undefined;
wasmData[1].value.data[0] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 2)))');
binary = yield undefined;
wasmData[1].value.data[1] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 3)))');
binary = yield undefined;
wasmData[1].value.data[2] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 4)))');
binary = yield undefined;
wasmData[2].value.data[0] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 5)))');
binary = yield undefined;
wasmData[2].value.data[1] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 6)))');
binary = yield undefined;
wasmData[2].value.data[2] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 7)))');
binary = yield undefined;
wasmData[2].value.data[3] = getWasmModule(binary);
getWasmBinary('(module (func (result i32) (i32.const 8)))');
binary = yield undefined;
wasmData[2].value.data[4] = getWasmModule(binary);
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = continueToNextStepSync;
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
// upgradeneeded
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = continueToNextStepSync;
info("Creating objectStore");
let objectStore = request.result.createObjectStore(objectStoreName);
info("Creating index");
objectStore.createIndex(indexData.name, indexData.keyPath, indexData.options);
yield undefined;
// success
let db = request.result;
db.onerror = errorHandler;
info("Storing values");
objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
let addedCount = 0;
for (let i in wasmData) {
request = objectStore.add(wasmData[i].value, wasmData[i].key);
request.onsuccess = function(event) {
if (++addedCount == wasmData.length) {
continueToNextStep();
}
}
}
yield undefined;
info("Getting values");
request = db.transaction(objectStoreName)
.objectStore(objectStoreName)
.index("nameIndex")
.getAll();
request.addEventListener("error", new ExpectError("UnknownError", true));
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
finishTest();
}

View File

@ -0,0 +1,79 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function* testSteps()
{
const name =
this.window ? window.location.pathname : "test_wasm_indexes.js";
const objectStoreName = "Wasm";
const wasmData = { key: 1, value: { name: "foo", data: null } };
const indexData = { name: "nameIndex", keyPath: "name", options: { } };
if (!isWasmSupported()) {
finishTest();
return;
}
getWasmBinary('(module (func (nop)))');
let binary = yield undefined;
wasmData.value.data = getWasmModule(binary);
info("Opening database");
let request = indexedDB.open(name);
request.onerror = errorHandler;
request.onupgradeneeded = continueToNextStepSync;
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
// upgradeneeded
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = continueToNextStepSync;
info("Creating objectStore");
let objectStore = request.result.createObjectStore(objectStoreName);
info("Creating index");
objectStore.createIndex(indexData.name, indexData.keyPath, indexData.options);
yield undefined;
// success
let db = request.result;
db.onerror = errorHandler;
info("Storing wasm");
objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
request = objectStore.add(wasmData.value, wasmData.key);
request.onsuccess = continueToNextStepSync;
yield undefined;
is(request.result, wasmData.key, "Got correct key");
info("Getting wasm");
request = objectStore.index("nameIndex").get("foo");
request.addEventListener("error", new ExpectError("UnknownError", true));
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
info("Opening cursor");
request = objectStore.index("nameIndex").openCursor();
request.addEventListener("error", new ExpectError("UnknownError", true));
request.onsuccess = unexpectedSuccessHandler;
yield undefined;
finishTest();
}

View File

@ -12,7 +12,7 @@ function* testSteps()
const objectStoreName = "Wasm";
const wasmData = { key: 1, wasm: null };
const wasmData = { key: 1, value: null };
if (!isWasmSupported()) {
finishTest();
@ -21,8 +21,7 @@ function* testSteps()
getWasmBinary('(module (func (nop)))');
let binary = yield undefined;
wasmData.wasm = getWasmModule(binary);
wasmData.value = getWasmModule(binary);
info("Opening database");
@ -50,7 +49,7 @@ function* testSteps()
let objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
request = objectStore.add(wasmData.wasm, wasmData.key);
request = objectStore.add(wasmData.value, wasmData.key);
request.onsuccess = continueToNextStepSync;
yield undefined;
@ -62,7 +61,9 @@ function* testSteps()
request.onsuccess = continueToNextStepSync;
yield undefined;
verifyWasmModule(request.result, wasmData.wasm);
info("Verifying wasm");
verifyWasmModule(request.result, wasmData.value);
yield undefined;
info("Getting wasm in new transaction");
@ -72,7 +73,9 @@ function* testSteps()
request.onsuccess = continueToNextStepSync;
yield undefined;
verifyWasmModule(request.result, wasmData.wasm);
info("Verifying wasm");
verifyWasmModule(request.result, wasmData.value);
yield undefined;
finishTest();

View File

@ -48,7 +48,12 @@ function testSteps()
let fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(File.createFromNsIFile(file));
let domFile;
File.createFromNsIFile(file).then(file => { domFile = file; }).then(continueToNextStepSync);
yield undefined;
fileReader.readAsArrayBuffer(domFile);
yield undefined;
@ -82,7 +87,11 @@ function testSteps()
fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(File.createFromNsIFile(file));
File.createFromNsIFile(file).then(file => { domFile = file; }).then(continueToNextStepSync);
yield undefined;
fileReader.readAsArrayBuffer(domFile);
yield undefined;
@ -108,7 +117,11 @@ function testSteps()
fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(File.createFromNsIFile(file));
File.createFromNsIFile(file).then(file => { domFile = file; }).then(continueToNextStepSync);
yield undefined;
fileReader.readAsArrayBuffer(domFile);
yield undefined;

View File

@ -122,16 +122,20 @@ function expectUncaughtException(expecting)
// This is dummy for xpcshell test.
}
function ExpectError(name)
function ExpectError(name, preventDefault)
{
this._name = name;
this._preventDefault = preventDefault;
}
ExpectError.prototype = {
handleEvent: function(event)
{
do_check_eq(event.type, "error");
do_check_eq(this._name, event.target.error.name);
event.preventDefault();
if (this._preventDefault) {
event.preventDefault();
event.stopPropagation();
}
grabEventAndContinueHandler(event);
}
};
@ -646,6 +650,7 @@ var SpecialPowers = {
this._createdFiles = new Array;
}
let createdFiles = this._createdFiles;
let promises = [];
requests.forEach(function(request) {
const filePerms = 0o666;
let testFile = dirSvc.get("ProfD", Ci.nsIFile);
@ -654,20 +659,24 @@ var SpecialPowers = {
} else {
testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, filePerms);
}
let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
filePerms, 0);
if (request.data) {
outStream.write(request.data, request.data.length);
outStream.close();
}
filePaths.push(File.createFromFileName(testFile.path, request.options));
createdFiles.push(testFile);
let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
filePerms, 0);
if (request.data) {
outStream.write(request.data, request.data.length);
outStream.close();
}
promises.push(File.createFromFileName(testFile.path, request.options).then(function(file) {
filePaths.push(file);
}));
createdFiles.push(testFile);
});
setTimeout(function () {
callback(filePaths);
}, 0);
Promise.all(promises).then(function() {
setTimeout(function () {
callback(filePaths);
}, 0);
});
},
removeFiles: function() {

View File

@ -64,8 +64,11 @@ skip-if = true
# bug 951017: intermittent failure on Android x86 emulator
skip-if = os == "android" && processor == "x86"
[test_view_put_get_values.js]
[test_wasm_cursors.js]
[test_wasm_getAll.js]
skip-if = coverage # bug 1336727
[test_wasm_index_getAllObjects.js]
[test_wasm_indexes.js]
[test_wasm_put_get_values.js]
skip-if = coverage # bug 1336727
[test_wasm_recompile.js]

View File

@ -29,6 +29,7 @@
#include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/ExternalHelperAppChild.h"
#include "mozilla/dom/FileCreatorHelper.h"
#include "mozilla/dom/FlyWebPublishedServerIPC.h"
#include "mozilla/dom/GetFilesHelper.h"
#include "mozilla/dom/MemoryReportRequest.h"
@ -3175,5 +3176,55 @@ ContentChild::GetConstructedEventTarget(const Message& aMsg)
return target.forget();
}
void
ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
const nsAString& aFullPath,
const nsAString& aType,
const nsAString& aName,
const Optional<int64_t>& aLastModified,
bool aIsFromNsIFile)
{
MOZ_ASSERT(aHelper);
bool lastModifiedPassed = false;
int64_t lastModified = 0;
if (aLastModified.WasPassed()) {
lastModifiedPassed = true;
lastModified = aLastModified.Value();
}
Unused << SendFileCreationRequest(aUUID, nsString(aFullPath), nsString(aType),
nsString(aName), lastModifiedPassed,
lastModified, aIsFromNsIFile);
mFileCreationPending.Put(aUUID, aHelper);
}
mozilla::ipc::IPCResult
ContentChild::RecvFileCreationResponse(const nsID& aUUID,
const FileCreationResult& aResult)
{
FileCreatorHelper* helper = mFileCreationPending.GetWeak(aUUID);
if (!helper) {
return IPC_FAIL_NO_REASON(this);
}
if (aResult.type() == FileCreationResult::TFileCreationErrorResult) {
helper->ResponseReceived(nullptr,
aResult.get_FileCreationErrorResult().errorCode());
} else {
MOZ_ASSERT(aResult.type() == FileCreationResult::TFileCreationSuccessResult);
PBlobChild* blobChild =
aResult.get_FileCreationSuccessResult().blobChild();
MOZ_ASSERT(blobChild);
RefPtr<BlobImpl> impl = static_cast<BlobChild*>(blobChild)->GetBlobImpl();
helper->ResponseReceived(impl, NS_OK);
}
mFileCreationPending.Remove(aUUID);
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

View File

@ -49,6 +49,7 @@ class PStorageChild;
class ClonedMessageData;
class TabChild;
class GetFilesHelperChild;
class FileCreatorHelper;
class ContentChild final : public PContentChild
, public nsIWindowProvider
@ -569,6 +570,10 @@ public:
virtual mozilla::ipc::IPCResult
RecvBlobURLUnregistration(const nsCString& aURI) override;
virtual mozilla::ipc::IPCResult
RecvFileCreationResponse(const nsID& aUUID,
const FileCreationResult& aResult) override;
mozilla::ipc::IPCResult
RecvRequestMemoryReport(
const uint32_t& generation,
@ -615,6 +620,14 @@ public:
const char* const aErrorMsg,
base::ProcessId aOtherPid);
// This method is used by FileCreatorHelper for the creation of a BlobImpl.
void
FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
const nsAString& aFullPath, const nsAString& aType,
const nsAString& aName,
const Optional<int64_t>& aLastModified,
bool aIsFromNsIFile);
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();
@ -679,6 +692,10 @@ private:
// received.
nsRefPtrHashtable<nsIDHashKey, GetFilesHelperChild> mGetFilesPendingRequests;
// Hashtable to keep track of the pending file creation.
// These items are removed when RecvFileCreationResponse is received.
nsRefPtrHashtable<nsIDHashKey, FileCreatorHelper> mFileCreationPending;
bool mShuttingDown;
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);

View File

@ -42,6 +42,7 @@
#include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileCreatorHelper.h"
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "mozilla/dom/GetFilesHelper.h"
#include "mozilla/dom/GeolocationBinding.h"
@ -4961,3 +4962,37 @@ ContentParent::RecvClassifyLocal(const URIParams& aURI, const nsCString& aTables
*aRv = uriClassifier->ClassifyLocalWithTables(uri, aTables, *aResults);
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvFileCreationRequest(const nsID& aID,
const nsString& aFullPath,
const nsString& aType,
const nsString& aName,
const bool& aLastModifiedPassed,
const int64_t& aLastModified,
const bool& aIsFromNsIFile)
{
RefPtr<BlobImpl> blobImpl;
nsresult rv =
FileCreatorHelper::CreateBlobImplForIPC(aFullPath, aType, aName,
aLastModifiedPassed,
aLastModified, aIsFromNsIFile,
getter_AddRefs(blobImpl));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
MOZ_ASSERT(blobImpl);
BlobParent* blobParent = BlobParent::GetOrCreate(this, blobImpl);
if (!SendFileCreationResponse(aID,
FileCreationSuccessResult(blobParent, nullptr))) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}

View File

@ -1088,6 +1088,13 @@ private:
virtual mozilla::ipc::IPCResult RecvDeleteGetFilesRequest(const nsID& aID) override;
virtual mozilla::ipc::IPCResult
RecvFileCreationRequest(const nsID& aID, const nsString& aFullPath,
const nsString& aType, const nsString& aName,
const bool& aLastModifiedPassed,
const int64_t& aLastModified,
const bool& aIsFromNsIFile) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildHistogram(
InfallibleTArray<Accumulation>&& aAccumulations) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistogram(

View File

@ -314,6 +314,22 @@ union GetFilesResponseResult
GetFilesResponseFailure;
};
struct FileCreationSuccessResult
{
PBlob blob;
};
struct FileCreationErrorResult
{
nsresult errorCode;
};
union FileCreationResult
{
FileCreationSuccessResult;
FileCreationErrorResult;
};
struct BlobURLRegistrationData
{
nsCString url;
@ -665,6 +681,8 @@ child:
async GMPsChanged(GMPCapabilityData[] capabilities);
async FileCreationResponse(nsID aID, FileCreationResult aResult);
parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
@ -1141,6 +1159,10 @@ parent:
async GetFilesRequest(nsID aID, nsString aDirectory, bool aRecursiveFlag);
async DeleteGetFilesRequest(nsID aID);
async FileCreationRequest(nsID aID, nsString aFullPath, nsString aType,
nsString aName, bool lastModifiedPassed,
int64_t lastModified, bool aIsFromNsIFile);
async StoreAndBroadcastBlobURLRegistration(nsCString url, PBlob blob,
Principal principal);

View File

@ -193,7 +193,7 @@ public:
}
for (uint32_t i = 0; i < aEvent.mCurveLength; ++i) {
if (!IsValid(aEvent.mCurve[i])) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
aRv.Throw(NS_ERROR_TYPE_ERR);
return false;
}
}

View File

@ -203,11 +203,11 @@ TEST(AudioEventTimeline, InvalidEvents)
timeline.SetValueCurveAtTime(nullptr, 0, 1.0, 1.0, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetValueCurveAtTime(badCurve1, ArrayLength(badCurve1), 1.0, 1.0, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
is(rv, NS_ERROR_TYPE_ERR, "Correct error code returned");
timeline.SetValueCurveAtTime(badCurve2, ArrayLength(badCurve2), 1.0, 1.0, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
is(rv, NS_ERROR_TYPE_ERR, "Correct error code returned");
timeline.SetValueCurveAtTime(badCurve3, ArrayLength(badCurve3), 1.0, 1.0, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
is(rv, NS_ERROR_TYPE_ERR, "Correct error code returned");
timeline.SetValueCurveAtTime(curve, ArrayLength(curve), NaN, 1.0, rv);
is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
timeline.SetValueCurveAtTime(curve, ArrayLength(curve), Infinity, 1.0, rv);

View File

@ -189,6 +189,7 @@ skip-if = (toolkit == 'android') || (os == 'mac' && os_version == '10.6')
[test_pannerNodeHRTFSymmetry.html]
[test_pannerNodeTail.html]
[test_pannerNode_maxDistance.html]
[test_setValueCurveWithNonFiniteElements.html]
[test_stereoPannerNode.html]
[test_stereoPannerNodePassThrough.html]
[test_periodicWave.html]

View File

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<html>
<meta charset=utf-8>
<head>
<title>Bug 1308437 - setValueCurve should throw on non-finite elements</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function testInfiniteElement(audioContext, audioParam) {
// create value curve with infinite element
var arr = new Float32Array(5);
arr[0] = 0.5;
arr[1] = 1;
arr[2] = Infinity;
arr[3] = 1;
arr[4] = 0.5;
try {
audioParam.setValueCurveAtTime(arr, audioContext.currentTime(), 2);
ok(false, "We shouldn't be able to call setValueCurve with Infinity but we can");
} catch(e) {
ok(e instanceof TypeError, "TypeError is thrown");
}
};
function testNanElement(audioContext, audioParam) {
// create value curve with infinite element
var arr = new Float32Array(5);
arr[0] = 0.5;
arr[1] = 1;
arr[2] = NaN;
arr[3] = 1;
arr[4] = 0.5;
try {
audioParam.setValueCurveAtTime(arr, audioContext.currentTime(), 2);
ok(false, "We shouldn't be able to call setValueCurve with NaN but we can");
} catch(e) {
ok(e instanceof TypeError, "TypeError is thrown");
}
};
addLoadEvent(function() {
var audioContext = new AudioContext();
var gainNode = audioContext.createGain();
testInfiniteElement(audioContext, gainNode.gain);
testNanElement(audioContext, gainNode.gain);
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -398,6 +398,18 @@
is(url.href, "scheme://tmp\\test");
</script>
<script>
/** Test for Bug 1275746 **/
SimpleTest.doesThrow(() => { var url = new URL("http:"); }, "http: is not a valid URL");
SimpleTest.doesThrow(() => { var url = new URL("http:///"); }, "http: is not a valid URL");
var url = new URL("file:");
is(url.href, "file:///", "Parsing file: should work.");
url = new URL("file:///");
is(url.href, "file:///", "Parsing file:/// should work.");
</script>
<script>
var url = new URL("scheme:path/to/file?query#hash");
is(url.href, "scheme:path/to/file?query#hash");

View File

@ -48,12 +48,13 @@ partial interface DataTransfer {
* @param element drag source to use
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
[Throws]
[Throws, UseCounter]
void addElement(Element element);
/**
* The number of items being dragged.
*/
[UseCounter]
readonly attribute unsigned long mozItemCount;
/**
@ -68,6 +69,7 @@ partial interface DataTransfer {
* Values other than 'default' are indentical to setting mozCursor to
* 'auto'.
*/
[UseCounter]
attribute DOMString mozCursor;
/**
@ -75,7 +77,7 @@ partial interface DataTransfer {
* at the specified index. If the index is not in the range from 0 to
* itemCount - 1, an empty string list is returned.
*/
[Throws, NeedsCallerType]
[Throws, NeedsCallerType, UseCounter]
DOMStringList mozTypesAt(unsigned long index);
/**
@ -92,7 +94,7 @@ partial interface DataTransfer {
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
[Throws, NeedsSubjectPrincipal]
[Throws, NeedsSubjectPrincipal, UseCounter]
void mozClearDataAt(DOMString format, unsigned long index);
/*
@ -116,7 +118,7 @@ partial interface DataTransfer {
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
[Throws, NeedsSubjectPrincipal]
[Throws, NeedsSubjectPrincipal, UseCounter]
void mozSetDataAt(DOMString format, any data, unsigned long index);
/**
@ -128,7 +130,7 @@ partial interface DataTransfer {
* @returns the data of the given format, or null if it doesn't exist.
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
*/
[Throws, NeedsSubjectPrincipal]
[Throws, NeedsSubjectPrincipal, UseCounter]
any mozGetDataAt(DOMString format, unsigned long index);
/**
@ -144,11 +146,13 @@ partial interface DataTransfer {
* false otherwise, including when the drop has been rejected by its target.
* This property is only relevant for the dragend event.
*/
[UseCounter]
readonly attribute boolean mozUserCancelled;
/**
* The node that the mouse was pressed over to begin the drag. For external
* drags, or if the caller cannot access this node, this will be null.
*/
[UseCounter]
readonly attribute Node? mozSourceNode;
};

View File

@ -40,10 +40,10 @@ partial interface File {
readonly attribute DOMString mozFullPath;
[ChromeOnly, Throws, NeedsCallerType]
static File createFromNsIFile(nsIFile file,
optional ChromeFilePropertyBag options);
static Promise<File> createFromNsIFile(nsIFile file,
optional ChromeFilePropertyBag options);
[ChromeOnly, Throws, NeedsCallerType]
static File createFromFileName(USVString fileName,
optional ChromeFilePropertyBag options);
static Promise<File> createFromFileName(USVString fileName,
optional ChromeFilePropertyBag options);
};

View File

@ -1033,7 +1033,7 @@ Wrap(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj)
}
if (existing) {
js::Wrapper::Renew(cx, existing, obj, wrapper);
js::Wrapper::Renew(existing, obj, wrapper);
}
return js::Wrapper::New(cx, obj, wrapper);
}

View File

@ -17,13 +17,26 @@ function createFileWithData(fileData) {
}
outStream.write(fileData, fileData.length);
outStream.close();
var domFile = File.createFromNsIFile(testFile);
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
return File.createFromNsIFile(testFile).then(function(domFile) {
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
});
}
addMessageListener("files.open", function (message) {
sendAsyncMessage("files.opened", message.map(createFileWithData));
let promises = [];
let list = [];
for (let fileData of message) {
promises.push(createFileWithData(fileData).then(domFile => {
list.push(domFile);
}));
}
Promise.all(promises).then(() => {
sendAsyncMessage("files.opened", list);
});
});

View File

@ -9,7 +9,7 @@ addMessageListener("file.open", function (e) {
tmpFile.append('file.txt');
tmpFile.createUnique(Components.interfaces.nsIFile.FILE_TYPE, 0o600);
sendAsyncMessage("file.opened", {
data: File.createFromNsIFile(tmpFile)
File.createFromNsIFile(tmpFile).then(function(file) {
sendAsyncMessage("file.opened", { data: file });
});
});

View File

@ -16,11 +16,13 @@
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/DOMString.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileCreatorHelper.h"
#include "mozilla/dom/FetchUtil.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/MutableBlobStorage.h"
#include "mozilla/dom/XMLDocument.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/LoadInfo.h"
@ -89,6 +91,12 @@
#include "private/pprio.h"
#include "XMLHttpRequestUpload.h"
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
// replaced by FileCreatorHelper#CreateFileW.
#ifdef CreateFile
#undef CreateFile
#endif
using namespace mozilla::net;
namespace mozilla {
@ -295,7 +303,6 @@ XMLHttpRequestMainThread::ResetResponse()
mResponseBody.Truncate();
TruncateResponseText();
mResponseBlob = nullptr;
mDOMBlob = nullptr;
mBlobStorage = nullptr;
mBlobSet = nullptr;
mResultArrayBuffer = nullptr;
@ -323,7 +330,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XMLHttpRequestMainThread,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXMLParserStreamListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponseBlob)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMBlob)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationCallbacks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannelEventSink)
@ -344,7 +350,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XMLHttpRequestMainThread,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXMLParserStreamListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResponseBlob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMBlob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNotificationCallbacks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannelEventSink)
@ -659,19 +664,6 @@ XMLHttpRequestMainThread::CreateResponseParsedJSON(JSContext* aCx)
void
XMLHttpRequestMainThread::CreatePartialBlob(ErrorResult& aRv)
{
if (mDOMBlob) {
// Use progress info to determine whether load is complete, but use
// mDataAvailable to ensure a slice is created based on the uncompressed
// data count.
if (mState == State::done) {
mResponseBlob = mDOMBlob;
} else {
mResponseBlob = mDOMBlob->CreateSlice(0, mDataAvailable,
EmptyString(), aRv);
}
return;
}
// mBlobSet can be null if the request has been canceled
if (!mBlobSet) {
return;
@ -1449,7 +1441,7 @@ XMLHttpRequestMainThread::IsSystemXHR() const
{
return mIsSystem || nsContentUtils::IsSystemPrincipal(mPrincipal);
}
bool
XMLHttpRequestMainThread::InUploadPhase() const
{
@ -1652,17 +1644,13 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
nsresult rv = NS_OK;
if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Blob) {
if (!xmlHttpRequest->mDOMBlob) {
xmlHttpRequest->MaybeCreateBlobStorage();
rv = xmlHttpRequest->mBlobStorage->Append(fromRawSegment, count);
}
xmlHttpRequest->MaybeCreateBlobStorage();
rv = xmlHttpRequest->mBlobStorage->Append(fromRawSegment, count);
} else if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_blob) {
if (!xmlHttpRequest->mDOMBlob) {
if (!xmlHttpRequest->mBlobSet) {
xmlHttpRequest->mBlobSet = new BlobSet();
}
rv = xmlHttpRequest->mBlobSet->AppendVoidPtr(fromRawSegment, count);
if (!xmlHttpRequest->mBlobSet) {
xmlHttpRequest->mBlobSet = new BlobSet();
}
rv = xmlHttpRequest->mBlobSet->AppendVoidPtr(fromRawSegment, count);
// Clear the cache so that the blob size is updated.
xmlHttpRequest->mResponseBlob = nullptr;
} else if ((xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Arraybuffer &&
@ -1723,27 +1711,107 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
return rv;
}
bool XMLHttpRequestMainThread::CreateDOMBlob(nsIRequest *request)
namespace {
nsresult
GetLocalFileFromChannel(nsIRequest* aRequest, nsIFile** aFile)
{
nsCOMPtr<nsIFile> file;
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(request);
if (fc) {
fc->GetFile(getter_AddRefs(file));
MOZ_ASSERT(aRequest);
MOZ_ASSERT(aFile);
*aFile = nullptr;
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aRequest);
if (!fc) {
return NS_OK;
}
if (!file)
return false;
nsCOMPtr<nsIFile> file;
nsresult rv = fc->GetFile(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoCString contentType;
mChannel->GetContentType(contentType);
file.forget(aFile);
return NS_OK;
}
mDOMBlob = File::CreateFromFile(GetOwner(), file, EmptyString(),
NS_ConvertASCIItoUTF16(contentType));
nsresult
DummyStreamReaderFunc(nsIInputStream* aInputStream,
void* aClosure,
const char* aFromRawSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t* aWriteCount)
{
*aWriteCount = aCount;
return NS_OK;
}
class FileCreationHandler final : public PromiseNativeHandler
{
public:
NS_DECL_ISUPPORTS
static void
Create(Promise* aPromise, XMLHttpRequestMainThread* aXHR)
{
MOZ_ASSERT(aPromise);
RefPtr<FileCreationHandler> handler = new FileCreationHandler(aXHR);
aPromise->AppendNativeHandler(handler);
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
if (NS_WARN_IF(!aValue.isObject())) {
mXHR->LocalFileToBlobCompleted(nullptr);
return;
}
RefPtr<Blob> blob;
if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Blob, &aValue.toObject(), blob)))) {
mXHR->LocalFileToBlobCompleted(nullptr);
return;
}
mXHR->LocalFileToBlobCompleted(blob);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
mXHR->LocalFileToBlobCompleted(nullptr);
}
private:
explicit FileCreationHandler(XMLHttpRequestMainThread* aXHR)
: mXHR(aXHR)
{
MOZ_ASSERT(aXHR);
}
~FileCreationHandler() = default;
RefPtr<XMLHttpRequestMainThread> mXHR;
};
NS_IMPL_ISUPPORTS0(FileCreationHandler)
} // namespace
void
XMLHttpRequestMainThread::LocalFileToBlobCompleted(Blob* aBlob)
{
MOZ_ASSERT(mState != State::done);
mResponseBlob = aBlob;
mBlobStorage = nullptr;
mBlobSet = nullptr;
NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
return true;
ChangeStateToDone();
}
NS_IMETHODIMP
@ -1760,31 +1828,45 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request,
mProgressSinceLastProgressEvent = true;
XMLHttpRequestBinding::ClearCachedResponseTextValue(this);
bool cancelable = false;
nsresult rv;
nsCOMPtr<nsIFile> localFile;
if ((mResponseType == XMLHttpRequestResponseType::Blob ||
mResponseType == XMLHttpRequestResponseType::Moz_blob) && !mDOMBlob) {
cancelable = CreateDOMBlob(request);
// The nsIStreamListener contract mandates us
// to read from the stream before returning.
mResponseType == XMLHttpRequestResponseType::Moz_blob)) {
rv = GetLocalFileFromChannel(request, getter_AddRefs(localFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (localFile) {
mBlobStorage = nullptr;
mBlobSet = nullptr;
NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
// We don't have to read from the local file for the blob response
int64_t fileSize;
rv = localFile->GetFileSize(&fileSize);
NS_ENSURE_SUCCESS(rv, rv);
mDataAvailable = fileSize;
// The nsIStreamListener contract mandates us to read from the stream
// before returning.
uint32_t totalRead;
rv =
inStr->ReadSegments(DummyStreamReaderFunc, nullptr, count, &totalRead);
NS_ENSURE_SUCCESS(rv, rv);
ChangeState(State::loading);
return request->Cancel(NS_OK);
}
}
uint32_t totalRead;
nsresult rv = inStr->ReadSegments(XMLHttpRequestMainThread::StreamReaderFunc,
(void*)this, count, &totalRead);
rv = inStr->ReadSegments(XMLHttpRequestMainThread::StreamReaderFunc,
(void*)this, count, &totalRead);
NS_ENSURE_SUCCESS(rv, rv);
if (cancelable) {
// We don't have to read from the local file for the blob response
ErrorResult error;
mDataAvailable = mDOMBlob->GetSize(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
ChangeState(State::loading);
return request->Cancel(NS_OK);
}
mDataAvailable += totalRead;
// Fire the first progress event/loading state change
@ -2106,14 +2188,36 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
if (NS_SUCCEEDED(status) &&
(mResponseType == XMLHttpRequestResponseType::Blob ||
mResponseType == XMLHttpRequestResponseType::Moz_blob)) {
ErrorResult rv;
if (!mDOMBlob) {
CreateDOMBlob(request);
nsCOMPtr<nsIFile> file;
nsresult rv = GetLocalFileFromChannel(request, getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mDOMBlob) {
mResponseBlob = mDOMBlob;
mDOMBlob = nullptr;
if (file) {
nsAutoCString contentType;
rv = mChannel->GetContentType(contentType);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
ChromeFilePropertyBag bag;
bag.mType = NS_ConvertUTF8toUTF16(contentType);
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
ErrorResult error;
RefPtr<Promise> promise =
FileCreatorHelper::CreateFile(global, file, bag, true, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
FileCreationHandler::Create(promise, this);
waitingForBlobCreation = true;
} else {
// No local file.
// Smaller files may be written in cache map instead of separate files.
// Also, no-store response cannot be written in persistent cache.
nsAutoCString contentType;
@ -2132,15 +2236,16 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
mBlobSet = new BlobSet();
}
ErrorResult error;
nsTArray<RefPtr<BlobImpl>> subImpls(mBlobSet->GetBlobImpls());
RefPtr<BlobImpl> blobImpl =
MultipartBlobImpl::Create(Move(subImpls),
NS_ConvertASCIItoUTF16(contentType),
rv);
error);
mBlobSet = nullptr;
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
mResponseBlob = Blob::Create(GetOwner(), blobImpl);

View File

@ -530,6 +530,9 @@ public:
Blob* aBlob,
nsresult aResult) override;
void
LocalFileToBlobCompleted(Blob* aBlob);
protected:
// XHR states are meant to mirror the XHR2 spec:
// https://xhr.spec.whatwg.org/#states
@ -551,7 +554,6 @@ protected:
uint32_t *writeCount);
nsresult CreateResponseParsedJSON(JSContext* aCx);
void CreatePartialBlob(ErrorResult& aRv);
bool CreateDOMBlob(nsIRequest *request);
// Change the state of the object with this. The broadcast argument
// determines if the onreadystatechange listener should be called.
nsresult ChangeState(State aState, bool aBroadcast = true);
@ -639,14 +641,9 @@ protected:
// It is either a cached blob-response from the last call to GetResponse,
// but is also explicitly set in OnStopRequest.
RefPtr<Blob> mResponseBlob;
// Non-null only when we are able to get a os-file representation of the
// response, i.e. when loading from a file.
RefPtr<Blob> mDOMBlob;
// We stream data to mBlobStorage when response type is "blob" and mDOMBlob is
// null.
// We stream data to mBlobStorage when response type is "blob".
RefPtr<MutableBlobStorage> mBlobStorage;
// We stream data to mBlobStorage when response type is "moz-blob" and
// mDOMBlob is null.
// We stream data to mBlobSet when response type is "moz-blob".
nsAutoPtr<BlobSet> mBlobSet;
nsString mOverrideMimeType;

View File

@ -39,6 +39,8 @@ LOCAL_INCLUDES += [
MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ]
BROWSER_CHROME_MANIFESTS += [ 'tests/browser.ini' ]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -0,0 +1,4 @@
[DEFAULT]
support-files =
[browser_blobFromFile.js]

View File

@ -0,0 +1,41 @@
let { classes: Cc, interfaces: Ci } = Components;
add_task(function* test() {
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
let fileHandler = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
let fileURL = fileHandler.getURLSpecFromFile(file);
info("Opening url: " + fileURL);
let tab = gBrowser.addTab(fileURL);
let browser = gBrowser.getBrowserForTab(tab);
yield BrowserTestUtils.browserLoaded(browser);
let blob = yield ContentTask.spawn(browser, null, function() {
return new content.window.Promise(resolve => {
let xhr = new content.window.XMLHttpRequest();
xhr.responseType = "blob";
xhr.open("GET", "prefs.js");
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
}
});
});
ok(blob instanceof File, "We have a file");
file.append("prefs.js");
is(blob.size, file.fileSize, "The size matches");
is(blob.name, "prefs.js", "The name is correct");
gBrowser.removeTab(tab);
});

View File

@ -79,23 +79,10 @@ function run_test() {
cm.removeAll();
// test that setting an empty or '.' http:// host results in a no-op
var uri = NetUtil.newURI("http://baz.com/");
var emptyuri = NetUtil.newURI("http:///");
var doturi = NetUtil.newURI("http://./");
do_check_eq(uri.asciiHost, "baz.com");
do_check_eq(emptyuri.asciiHost, "");
do_check_eq(doturi.asciiHost, ".");
cs.setCookieString(emptyuri, null, "foo2=bar", null);
do_check_eq(getCookieCount(), 0);
cs.setCookieString(doturi, null, "foo3=bar", null);
do_check_eq(getCookieCount(), 0);
cs.setCookieString(uri, null, "foo=bar", null);
do_check_eq(getCookieCount(), 1);
do_check_eq(cs.getCookieString(uri, null), "foo=bar");
do_check_eq(cs.getCookieString(emptyuri, null), null);
do_check_eq(cs.getCookieString(doturi, null), null);
do_check_eq(cm.countCookiesFromHost(""), 0);
do_check_throws(function() {

View File

@ -213,8 +213,14 @@ ShadowLayerForwarder::~ShadowLayerForwarder()
delete mTxn;
if (mShadowManager) {
mShadowManager->SetForwarder(nullptr);
mShadowManager->Destroy();
if (NS_IsMainThread()) {
mShadowManager->Destroy();
} else {
NS_DispatchToMainThread(
NewRunnableMethod(mShadowManager, &LayerTransactionChild::Destroy));
}
}
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(
new ReleaseOnMainThreadTask<ActiveResourceTracker>(mActiveResourceTracker));

0
git Normal file
View File

View File

@ -779,6 +779,10 @@ imgFrame::GetSourceSurfaceInternal()
return surf.forget();
}
if (!mRawSurface) {
return nullptr;
}
return CreateLockedSurface(mRawSurface, mFrameRect.Size(), mFormat);
}

View File

@ -140,12 +140,12 @@ ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, RegExpShared& re, HandleLin
/* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
bool
js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
HandleLinearString input, size_t* lastIndex, bool test,
MutableHandleValue rval)
{
RegExpGuard shared(cx);
if (!reobj.getShared(cx, &shared))
if (!RegExpObject::getShared(cx, reobj, &shared))
return false;
ScopedMatchPairs matches(&cx->tempLifoAlloc());
@ -918,7 +918,7 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard re(cx);
if (!reobj->getShared(cx, &re))
if (!RegExpObject::getShared(cx, reobj, &re))
return RegExpRunStatus_Error;
RegExpStatics* res;

View File

@ -31,7 +31,7 @@ enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics };
* |chars| and |length|.
*/
MOZ_MUST_USE bool
ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
HandleLinearString input, size_t* lastIndex, bool test,
MutableHandleValue rval);

View File

@ -978,7 +978,7 @@ AbortGC(JSContext* cx, unsigned argc, Value* vp)
return false;
}
cx->runtime()->gc.abortGC();
JS::AbortIncrementalGC(cx);
args.rval().setUndefined();
return true;
}
@ -1482,7 +1482,7 @@ OOMTest(JSContext* cx, unsigned argc, Value* vp)
#ifdef JS_TRACE_LOGGING
// Reset the TraceLogger state if enabled.
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
if (logger->enabled()) {
while (logger->enabled())
logger->disable();
@ -2571,7 +2571,7 @@ static bool
EnableTraceLogger(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
if (!TraceLoggerEnable(logger, cx))
return false;
@ -2583,7 +2583,7 @@ static bool
DisableTraceLogger(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
args.rval().setBoolean(TraceLoggerDisable(logger));
return true;
@ -4166,7 +4166,7 @@ DisRegExp(JSContext* cx, unsigned argc, Value* vp)
return false;
}
if (!reobj->dumpBytecode(cx, match_only, input))
if (!RegExpObject::dumpBytecode(cx, reobj, match_only, input))
return false;
args.rval().setUndefined();

View File

@ -111,9 +111,8 @@ class MOZ_STACK_CLASS BytecodeCompiler
AutoCompilationTraceLogger::AutoCompilationTraceLogger(JSContext* cx,
const TraceLoggerTextId id, const ReadOnlyCompileOptions& options)
: logger(!cx->helperThread() ? TraceLoggerForMainThread(cx->runtime())
: TraceLoggerForCurrentThread()),
event(logger, TraceLogger_AnnotateScripts, options),
: logger(TraceLoggerForCurrentThread(cx)),
event(TraceLogger_AnnotateScripts, options),
scriptLogger(logger, event),
typeLogger(logger, id)
{}

View File

@ -849,6 +849,12 @@ class GCRuntime
Finished
};
enum IncrementalResult
{
Reset = 0,
Ok
};
// For ArenaLists::allocateFromArena()
friend class ArenaLists;
Chunk* pickChunk(const AutoLockGC& lock,
@ -883,9 +889,9 @@ class GCRuntime
void requestMajorGC(JS::gcreason::Reason reason);
SliceBudget defaultBudget(JS::gcreason::Reason reason, int64_t millis);
void budgetIncrementalGC(JS::gcreason::Reason reason, SliceBudget& budget,
AutoLockForExclusiveAccess& lock);
void resetIncrementalGC(AbortReason reason, AutoLockForExclusiveAccess& lock);
IncrementalResult budgetIncrementalGC(bool nonincrementalByAPI, JS::gcreason::Reason reason,
SliceBudget& budget, AutoLockForExclusiveAccess& lock);
IncrementalResult resetIncrementalGC(AbortReason reason, AutoLockForExclusiveAccess& lock);
// Assert if the system state is such that we should never
// receive a request to do GC work.
@ -897,8 +903,8 @@ class GCRuntime
gcstats::ZoneGCStats scanZonesBeforeGC();
void collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::Reason reason) JS_HAZ_GC_CALL;
MOZ_MUST_USE bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget,
JS::gcreason::Reason reason);
MOZ_MUST_USE IncrementalResult gcCycle(bool nonincrementalByAPI, SliceBudget& budget,
JS::gcreason::Reason reason);
bool shouldRepeatForDeadZone(JS::gcreason::Reason reason);
void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason,
AutoLockForExclusiveAccess& lock);

View File

@ -268,7 +268,7 @@ Zone::discardJitCode(FreeOp* fop, bool discardBaselineCode)
* Defer freeing any allocated blocks until after the next minor GC.
*/
if (discardBaselineCode) {
jitZone()->optimizedStubSpace()->freeAllAfterMinorGC(fop->runtime());
jitZone()->optimizedStubSpace()->freeAllAfterMinorGC(this);
jitZone()->purgeIonCacheIRStubInfo();
}

View File

@ -834,10 +834,6 @@ struct GCManagedDeletePolicy
namespace JS {
template <typename T>
struct DeletePolicy<js::GCPtr<T>> : public js::GCManagedDeletePolicy<js::GCPtr<T>>
{};
// Scope data that contain GCPtrs must use the correct DeletePolicy.
//
// This is defined here because vm/Scope.h cannot #include "vm/Runtime.h"

View File

@ -157,8 +157,10 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
// avoid failing repeatedly when the regex code is called from Ion JIT code,
// see bug 1208819.
Label stack_ok;
void* stack_limit = &cx->runtime()->contextFromMainThread()->jitStackLimitNoInterrupt;
masm.branchStackPtrRhs(Assembler::Below, AbsoluteAddress(stack_limit), &stack_ok);
void* context_addr = &cx->zone()->group()->context;
masm.loadPtr(AbsoluteAddress(context_addr), temp0);
Address limit_addr(temp0, offsetof(JSContext, jitStackLimitNoInterrupt));
masm.branchStackPtrRhs(Assembler::Below, limit_addr, &stack_ok);
// Exit with an exception. There is not enough space on the stack
// for our working registers.
@ -272,8 +274,9 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
}
// Initialize backtrack stack pointer.
masm.loadPtr(AbsoluteAddress(cx->runtime()->contextFromMainThread()->regexpStack.ref().addressOfBase()),
backtrack_stack_pointer);
size_t baseOffset = offsetof(JSContext, regexpStack) + RegExpStack::offsetOfBase();
masm.loadPtr(AbsoluteAddress(context_addr), backtrack_stack_pointer);
masm.loadPtr(Address(backtrack_stack_pointer, baseOffset), backtrack_stack_pointer);
masm.storePtr(backtrack_stack_pointer,
Address(masm.getStackPointer(), offsetof(FrameData, backtrackStackBase)));
@ -463,7 +466,10 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
Address backtrackStackBaseAddress(temp2, offsetof(FrameData, backtrackStackBase));
masm.subPtr(backtrackStackBaseAddress, backtrack_stack_pointer);
masm.loadPtr(AbsoluteAddress(cx->runtime()->contextFromMainThread()->regexpStack.ref().addressOfBase()), temp1);
void* context_addr = &cx->zone()->group()->context;
size_t baseOffset = offsetof(JSContext, regexpStack) + RegExpStack::offsetOfBase();
masm.loadPtr(AbsoluteAddress(context_addr), temp1);
masm.loadPtr(Address(temp1, baseOffset), temp1);
masm.storePtr(temp1, backtrackStackBaseAddress);
masm.addPtr(temp1, backtrack_stack_pointer);
@ -542,8 +548,9 @@ NativeRegExpMacroAssembler::Backtrack()
// Check for an interrupt.
Label noInterrupt;
masm.branch32(Assembler::Equal,
AbsoluteAddress(&cx->runtime()->contextFromMainThread()->interrupt_), Imm32(0),
void* contextAddr = &cx->zone()->group()->context;
masm.loadPtr(AbsoluteAddress(contextAddr), temp0);
masm.branch32(Assembler::Equal, Address(temp0, offsetof(JSContext, interrupt_)), Imm32(0),
&noInterrupt);
masm.movePtr(ImmWord(RegExpRunStatus_Error), temp0);
masm.jump(&exit_label_);
@ -1101,10 +1108,11 @@ NativeRegExpMacroAssembler::CheckBacktrackStackLimit()
{
JitSpew(SPEW_PREFIX "CheckBacktrackStackLimit");
const void* limitAddr = cx->runtime()->contextFromMainThread()->regexpStack.ref().addressOfLimit();
Label no_stack_overflow;
masm.branchPtr(Assembler::AboveOrEqual, AbsoluteAddress(limitAddr),
void* context_addr = &cx->zone()->group()->context;
size_t limitOffset = offsetof(JSContext, regexpStack) + RegExpStack::offsetOfLimit();
masm.loadPtr(AbsoluteAddress(context_addr), temp1);
masm.branchPtr(Assembler::AboveOrEqual, Address(temp1, limitOffset),
backtrack_stack_pointer, &no_stack_overflow);
// Copy the stack pointer before the call() instruction modifies it.

View File

@ -79,8 +79,8 @@ class RegExpStack
bool grow();
// Address of allocated memory.
const void* addressOfBase() { return &base_; }
const void* addressOfLimit() { return &limit_; }
static size_t offsetOfBase() { return offsetof(RegExpStack, base_); }
static size_t offsetOfLimit() { return offsetof(RegExpStack, limit_); }
void* base() { return base_; }
void* limit() { return limit_; }

View File

@ -44,7 +44,7 @@ jit::Bailout(BailoutStack* sp, BaselineBailoutInfo** bailoutInfo)
MOZ_ASSERT(!iter.ionScript()->invalidated());
CommonFrameLayout* currentFramePtr = iter.current();
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
TraceLogTimestamp(logger, TraceLogger_Bailout);
JitSpew(JitSpew_IonBailouts, "Took bailout! Snapshot offset: %d", iter.snapshotOffset());
@ -115,7 +115,7 @@ jit::InvalidationBailout(InvalidationBailoutStack* sp, size_t* frameSizeOut,
JitFrameIterator iter(jitActivations);
CommonFrameLayout* currentFramePtr = iter.current();
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
TraceLogTimestamp(logger, TraceLogger_Invalidation);
JitSpew(JitSpew_IonBailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());

View File

@ -1481,7 +1481,7 @@ jit::BailoutIonToBaseline(JSContext* cx, JitActivation* activation, JitFrameIter
MOZ_ASSERT(bailoutInfo != nullptr);
MOZ_ASSERT(*bailoutInfo == nullptr);
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
TraceLogStopEvent(logger, TraceLogger_IonMonkey);
TraceLogStartEvent(logger, TraceLogger_Baseline);
@ -1606,7 +1606,7 @@ jit::BailoutIonToBaseline(JSContext* cx, JitActivation* activation, JitFrameIter
// TraceLogger doesn't create entries for inlined frames. But we
// see them in Baseline. Here we create the start events of those
// entries. So they correspond to what we will see in Baseline.
TraceLoggerEvent scriptEvent(logger, TraceLogger_Scripts, scr);
TraceLoggerEvent scriptEvent(TraceLogger_Scripts, scr);
TraceLogStartEvent(logger, scriptEvent);
TraceLogStartEvent(logger, TraceLogger_Baseline);
}

View File

@ -92,8 +92,8 @@ BaselineCompiler::compile()
JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%" PRIuSIZE,
script->filename(), script->lineno());
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEvent scriptEvent(logger, TraceLogger_AnnotateScripts, script);
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
TraceLoggerEvent scriptEvent(TraceLogger_AnnotateScripts, script);
AutoTraceLog logScript(logger, scriptEvent);
AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
@ -525,7 +525,6 @@ bool
BaselineCompiler::emitStackCheck(bool earlyCheck)
{
Label skipCall;
void* limitAddr = &cx->runtime()->contextFromMainThread()->jitStackLimit;
uint32_t slotsSize = script->nslots() * sizeof(Value);
uint32_t tolerance = earlyCheck ? slotsSize : 0;
@ -551,7 +550,10 @@ BaselineCompiler::emitStackCheck(bool earlyCheck)
&forceCall);
}
masm.branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(limitAddr), R1.scratchReg(),
void* contextAddr = &cx->zone()->group()->context;
masm.loadPtr(AbsoluteAddress(contextAddr), R0.scratchReg());
masm.branchPtr(Assembler::BelowOrEqual,
Address(R0.scratchReg(), offsetof(JSContext, jitStackLimit)), R1.scratchReg(),
&skipCall);
if (!earlyCheck && needsEarlyStackCheck())
@ -697,8 +699,11 @@ BaselineCompiler::emitInterruptCheck()
frame.syncStack(0);
Label done;
void* interrupt = &cx->runtime()->contextFromMainThread()->interrupt_;
masm.branch32(Assembler::Equal, AbsoluteAddress(interrupt), Imm32(0), &done);
void* context = &cx->zone()->group()->context;
masm.loadPtr(AbsoluteAddress(context), R0.scratchReg());
masm.branch32(Assembler::Equal,
Address(R0.scratchReg(), offsetof(JSContext, interrupt_)), Imm32(0),
&done);
prepareVMCall();
if (!callVM(InterruptCheckInfo))
@ -838,7 +843,6 @@ BaselineCompiler::emitDebugTrap()
bool
BaselineCompiler::emitTraceLoggerEnter()
{
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
AllocatableRegisterSet regs(RegisterSet::Volatile());
Register loggerReg = regs.takeAnyGeneral();
Register scriptReg = regs.takeAnyGeneral();
@ -850,7 +854,7 @@ BaselineCompiler::emitTraceLoggerEnter()
masm.Push(loggerReg);
masm.Push(scriptReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.loadTraceLogger(loggerReg);
// Script start.
masm.movePtr(ImmGCPtr(script), scriptReg);
@ -873,7 +877,6 @@ BaselineCompiler::emitTraceLoggerEnter()
bool
BaselineCompiler::emitTraceLoggerExit()
{
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
AllocatableRegisterSet regs(RegisterSet::Volatile());
Register loggerReg = regs.takeAnyGeneral();
@ -882,7 +885,7 @@ BaselineCompiler::emitTraceLoggerExit()
return false;
masm.Push(loggerReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.loadTraceLogger(loggerReg);
masm.tracelogStopId(loggerReg, TraceLogger_Baseline, /* force = */ true);
masm.tracelogStopId(loggerReg, TraceLogger_Scripts, /* force = */ true);
@ -904,8 +907,7 @@ BaselineCompiler::emitTraceLoggerResume(Register baselineScript, AllocatableGene
if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
return false;
TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
masm.movePtr(ImmPtr(logger), loggerReg);
masm.loadTraceLogger(loggerReg);
Address scriptEvent(baselineScript, BaselineScript::offsetOfTraceLoggerScriptEvent());
masm.computeEffectiveAddress(scriptEvent, scriptId);

View File

@ -820,8 +820,8 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
bool isTemporarilyUnoptimizable = false;
if (!attached && !JitOptions.disableCacheIR) {
ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, pc, CacheKind::GetElem, engine, &isTemporarilyUnoptimizable,
lhs, rhs, CanAttachGetter::Yes);
GetPropIRGenerator gen(cx, script, pc, CacheKind::GetElem, engine,
&isTemporarilyUnoptimizable, lhs, rhs, CanAttachGetter::Yes);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
engine, info.outerScript(cx), stub);
@ -1110,7 +1110,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
if (stub->numOptimizedStubs() < ICSetElem_Fallback::MAX_OPTIMIZED_STUBS &&
!JitOptions.disableCacheIR)
{
SetPropIRGenerator gen(cx, pc, CacheKind::SetElem, &isTemporarilyUnoptimizable,
SetPropIRGenerator gen(cx, script, pc, CacheKind::SetElem, &isTemporarilyUnoptimizable,
objv, index, rhs);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
@ -1193,7 +1193,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
}
if (!JitOptions.disableCacheIR) {
SetPropIRGenerator gen(cx, pc, CacheKind::SetElem, &isTemporarilyUnoptimizable,
SetPropIRGenerator gen(cx, script, pc, CacheKind::SetElem, &isTemporarilyUnoptimizable,
objv, index, rhs);
if (gen.tryAttachAddSlotStub(oldGroup, oldShape)) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
@ -1205,6 +1205,8 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
newStub->toCacheIR_Updated()->updateStubId() = gen.updateStubId();
return true;
}
} else {
gen.trackNotAttached();
}
}
@ -1963,15 +1965,16 @@ DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub_,
if (stub->numOptimizedStubs() >= ICIn_Fallback::MAX_OPTIMIZED_STUBS)
attached = true;
RootedScript script(cx, frame->script());
RootedObject obj(cx, &objValue.toObject());
jsbytecode* pc = stub->icEntry()->pc(frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
if (!attached && !JitOptions.disableCacheIR) {
ICStubEngine engine = ICStubEngine::Baseline;
InIRGenerator gen(cx, pc, key, obj);
InIRGenerator gen(cx, script, pc, key, obj);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
engine, frame->script(), stub);
engine, script, stub);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
attached = true;
@ -2039,7 +2042,7 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
if (!attached && !JitOptions.disableCacheIR) {
ICStubEngine engine = ICStubEngine::Baseline;
GetNameIRGenerator gen(cx, pc, script, envChain, name);
GetNameIRGenerator gen(cx, script, pc, envChain, name);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
engine, info.outerScript(cx), stub);
@ -2271,7 +2274,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
!JitOptions.disableCacheIR)
{
RootedValue idVal(cx, StringValue(name));
SetPropIRGenerator gen(cx, pc, CacheKind::SetProp, &isTemporarilyUnoptimizable,
SetPropIRGenerator gen(cx, script, pc, CacheKind::SetProp, &isTemporarilyUnoptimizable,
lhs, idVal, rhs);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
@ -2340,7 +2343,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
!JitOptions.disableCacheIR)
{
RootedValue idVal(cx, StringValue(name));
SetPropIRGenerator gen(cx, pc, CacheKind::SetProp, &isTemporarilyUnoptimizable,
SetPropIRGenerator gen(cx, script, pc, CacheKind::SetProp, &isTemporarilyUnoptimizable,
lhs, idVal, rhs);
if (gen.tryAttachAddSlotStub(oldGroup, oldShape)) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
@ -2351,6 +2354,8 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
newStub->toCacheIR_Updated()->updateStubGroup() = gen.updateStubGroup();
newStub->toCacheIR_Updated()->updateStubId() = gen.updateStubId();
}
} else {
gen.trackNotAttached();
}
}
@ -4121,7 +4126,7 @@ ICCall_Native::Compiler::generateStubCode(MacroAssembler& masm)
EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
masm.push(scratch);
masm.push(ICTailCallReg);
masm.enterFakeExitFrameForNative(isConstructing_);
masm.enterFakeExitFrameForNative(scratch, isConstructing_);
// Execute call.
masm.setupUnalignedABICall(scratch);
@ -4213,7 +4218,7 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
masm.push(scratch);
masm.push(ICTailCallReg);
masm.enterFakeExitFrameForNative(isConstructing_);
masm.enterFakeExitFrameForNative(scratch, isConstructing_);
// Execute call.
masm.setupUnalignedABICall(scratch);

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