зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
--HG-- extra : rebase_source : ed5871b95beeb440688654cc676c5438c2898ccf
This commit is contained in:
Коммит
f3a0e0a65e
|
@ -43,7 +43,7 @@ public:
|
|||
protected:
|
||||
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
|
||||
: ProxyAccessibleBase(aThisAsDoc)
|
||||
{ MOZ_COUNT_CTOR(ProxyAccessibleBase); }
|
||||
{ MOZ_COUNT_CTOR(ProxyAccessible); }
|
||||
|
||||
void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible)
|
||||
{ mCOMProxy = aIAccessible; }
|
||||
|
|
|
@ -9,7 +9,7 @@ support-files =
|
|||
doc_content_text.html
|
||||
!/accessible/tests/mochitest/*.js
|
||||
!/accessible/tests/mochitest/moz.png
|
||||
skip-if = os == 'win'
|
||||
skip-if = (os == 'win' && (os_version == '5.1' || os_version == '5.2'))
|
||||
|
||||
[test_alive.html]
|
||||
[test_content_integration.html]
|
||||
|
|
|
@ -1420,9 +1420,11 @@ pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/fi
|
|||
#ifdef NIGHTLY_BUILD
|
||||
pref("privacy.userContext.enabled", true);
|
||||
pref("privacy.userContext.ui.enabled", true);
|
||||
pref("privacy.usercontext.about_newtab_segregation.enabled", true);
|
||||
#else
|
||||
pref("privacy.userContext.enabled", false);
|
||||
pref("privacy.userContext.ui.enabled", false);
|
||||
pref("privacy.usercontext.about_newtab_segregation.enabled", false);
|
||||
#endif
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
|
|
|
@ -91,7 +91,7 @@ function waitForCondition(condition, nextTest, errorMsg, okMsg) {
|
|||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
}, 500);
|
||||
var moveOn = function() {
|
||||
clearInterval(interval); nextTest();
|
||||
};
|
||||
|
|
|
@ -21,6 +21,17 @@ add_task(function*() {
|
|||
EventUtils.synthesizeKey("v", {});
|
||||
yield scrollPromise;
|
||||
|
||||
// Wait for one paint to ensure we've processed the previous key events and scrolling.
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
||||
return new Promise(
|
||||
resolve => {
|
||||
content.requestAnimationFrame(() => {
|
||||
setTimeout(resolve, 0);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Finds the div in the red box.
|
||||
scrollPromise = promiseWaitForEvent(gBrowser, "scroll");
|
||||
EventUtils.synthesizeKey("g", { accelKey: true });
|
||||
|
|
|
@ -169,7 +169,9 @@ function test() {
|
|||
PopupNotifications.panel.removeAttribute("animate");
|
||||
});
|
||||
waitForExplicitFinish();
|
||||
runSocialTests(tests, undefined, postTestCleanup);
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, () => {
|
||||
runSocialTests(tests, undefined, postTestCleanup);
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
|
|
|
@ -65,7 +65,10 @@ var gTests = [
|
|||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// An empty tab where we can load the content script without leaving it
|
||||
// behind at the end of the test.
|
||||
gBrowser.addTab();
|
||||
|
|
|
@ -9,7 +9,8 @@ pref("startup.homepage_welcome_url.additional", "");
|
|||
pref("app.update.interval", 43200); // 12 hours
|
||||
// The time interval between the downloading of mar file chunks in the
|
||||
// background (in seconds)
|
||||
pref("app.update.download.backgroundInterval", 60);
|
||||
// 0 means "download everything at once"
|
||||
pref("app.update.download.backgroundInterval", 0);
|
||||
// Give the user x seconds to react before showing the big UI. default=192 hours
|
||||
pref("app.update.promptWaitTime", 691200);
|
||||
// URL user can browse to manually if for some reason all update installation
|
||||
|
|
|
@ -213,6 +213,8 @@ this.IsolationTestTools = {
|
|||
// Make sure preferences are set properly.
|
||||
yield SpecialPowers.pushPrefEnv({"set": aPref});
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]});
|
||||
|
||||
yield aTask(aMode);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -27,6 +27,9 @@ this.PluginContent = function (global) {
|
|||
this.init(global);
|
||||
}
|
||||
|
||||
const FLASH_MIME_TYPE = "application/x-shockwave-flash";
|
||||
const REPLACEMENT_STYLE_SHEET = Services.io.newURI("chrome://pluginproblem/content/pluginReplaceBinding.css", null, null);
|
||||
|
||||
PluginContent.prototype = {
|
||||
init: function (global) {
|
||||
this.global = global;
|
||||
|
@ -39,6 +42,7 @@ PluginContent.prototype = {
|
|||
|
||||
// Note that the XBL binding is untrusted
|
||||
global.addEventListener("PluginBindingAttached", this, true, true);
|
||||
global.addEventListener("PluginPlaceholderReplaced", this, true, true);
|
||||
global.addEventListener("PluginCrashed", this, true);
|
||||
global.addEventListener("PluginOutdated", this, true);
|
||||
global.addEventListener("PluginInstantiated", this, true);
|
||||
|
@ -62,6 +66,7 @@ PluginContent.prototype = {
|
|||
let global = this.global;
|
||||
|
||||
global.removeEventListener("PluginBindingAttached", this, true);
|
||||
global.removeEventListener("PluginPlaceholderReplaced", this, true, true);
|
||||
global.removeEventListener("PluginCrashed", this, true);
|
||||
global.removeEventListener("PluginOutdated", this, true);
|
||||
global.removeEventListener("PluginInstantiated", this, true);
|
||||
|
@ -174,6 +179,15 @@ PluginContent.prototype = {
|
|||
},
|
||||
|
||||
_getPluginInfo: function (pluginElement) {
|
||||
if (pluginElement instanceof Ci.nsIDOMHTMLAnchorElement) {
|
||||
// Anchor elements are our place holders, and we only have them for Flash
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
return {
|
||||
pluginName: "Shockwave Flash",
|
||||
mimetype: FLASH_MIME_TYPE,
|
||||
permissionString: pluginHost.getPermissionStringForType(FLASH_MIME_TYPE)
|
||||
};
|
||||
}
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
|
||||
|
@ -421,16 +435,38 @@ PluginContent.prototype = {
|
|||
}
|
||||
|
||||
if (eventType == "HiddenPlugin") {
|
||||
let pluginTag = event.tag.QueryInterface(Ci.nsIPluginTag);
|
||||
if (event.target.defaultView.top.document != this.content.document) {
|
||||
return;
|
||||
let win = event.target.defaultView;
|
||||
if (!win.mozHiddenPluginTouched) {
|
||||
let pluginTag = event.tag.QueryInterface(Ci.nsIPluginTag);
|
||||
if (win.top.document != this.content.document) {
|
||||
return;
|
||||
}
|
||||
this._showClickToPlayNotification(pluginTag, false);
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
winUtils.loadSheet(REPLACEMENT_STYLE_SHEET, win.AGENT_SHEET);
|
||||
win.mozHiddenPluginTouched = true;
|
||||
} catch (e) {
|
||||
Cu.reportError("Error adding plugin replacement style sheet: " + e);
|
||||
}
|
||||
}
|
||||
this._showClickToPlayNotification(pluginTag, false);
|
||||
}
|
||||
|
||||
let plugin = event.target;
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
if (eventType == "PluginPlaceholderReplaced") {
|
||||
plugin.removeAttribute("href");
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
this.setVisibility(plugin, overlay, true);
|
||||
let inIDOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
|
||||
.getService(Ci.inIDOMUtils);
|
||||
// Add psuedo class so our styling will take effect
|
||||
inIDOMUtils.addPseudoClassLock(plugin, "-moz-handler-clicktoplay");
|
||||
overlay.addEventListener("click", this, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
|
@ -509,7 +545,7 @@ PluginContent.prototype = {
|
|||
break;
|
||||
}
|
||||
|
||||
if (this._getPluginInfo(plugin).mimetype === "application/x-shockwave-flash") {
|
||||
if (this._getPluginInfo(plugin).mimetype === FLASH_MIME_TYPE) {
|
||||
this._recordFlashPluginTelemetry(eventType, plugin);
|
||||
}
|
||||
|
||||
|
@ -661,12 +697,19 @@ PluginContent.prototype = {
|
|||
_handleClickToPlayEvent: function (plugin) {
|
||||
let doc = plugin.ownerDocument;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// guard against giving pluginHost.getPermissionStringForType a type
|
||||
// not associated with any known plugin
|
||||
if (!this.isKnownPlugin(objLoadingContent))
|
||||
return;
|
||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
||||
let permissionString;
|
||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
||||
// We only have replacement content for Flash installs
|
||||
permissionString = pluginHost.getPermissionStringForType(FLASH_MIME_TYPE);
|
||||
} else {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// guard against giving pluginHost.getPermissionStringForType a type
|
||||
// not associated with any known plugin
|
||||
if (!this.isKnownPlugin(objLoadingContent))
|
||||
return;
|
||||
permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
||||
}
|
||||
|
||||
let principal = doc.defaultView.top.document.nodePrincipal;
|
||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
|
||||
|
||||
|
@ -688,7 +731,6 @@ PluginContent.prototype = {
|
|||
let document = event.target.ownerDocument;
|
||||
let plugin = document.getBindingParent(event.target);
|
||||
let contentWindow = plugin.ownerGlobal.top;
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
// Have to check that the target is not the link to update the plugin
|
||||
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
|
||||
|
@ -729,6 +771,7 @@ PluginContent.prototype = {
|
|||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
let pluginFound = false;
|
||||
let placeHolderFound = false;
|
||||
for (let plugin of plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (!this.isKnownPlugin(plugin)) {
|
||||
|
@ -736,7 +779,11 @@ PluginContent.prototype = {
|
|||
}
|
||||
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
pluginFound = true;
|
||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
||||
placeHolderFound = true;
|
||||
} else {
|
||||
pluginFound = true;
|
||||
}
|
||||
if (newState == "block") {
|
||||
if (overlay) {
|
||||
overlay.addEventListener("click", this, true);
|
||||
|
@ -751,11 +798,12 @@ PluginContent.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// If there are no instances of the plugin on the page any more or if we've
|
||||
// noted that the content needs to be reloaded due to replacing HLS, what the
|
||||
// user probably needs is for us to allow and then refresh.
|
||||
// If there are no instances of the plugin on the page any more, what the
|
||||
// user probably needs is for us to allow and then refresh. Additionally, if
|
||||
// this is content that requires HLS or we replaced the placeholder the page
|
||||
// needs to be refreshed for it to insert its plugins
|
||||
if (newState != "block" &&
|
||||
(!pluginFound || contentWindow.pluginRequiresReload)) {
|
||||
(!pluginFound || placeHolderFound || contentWindow.pluginRequiresReload)) {
|
||||
this.reloadPage();
|
||||
}
|
||||
this.updateNotificationUI();
|
||||
|
|
|
@ -30,6 +30,12 @@ let checkToolbox = Task.async(function* (tab, location) {
|
|||
ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
|
||||
});
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
</filter>
|
||||
|
||||
<!-- Web Audio Gradients -->
|
||||
<linearGradient id="bypass-light" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
|
||||
<stop offset="0%" stop-color="#f0f1f2"/> <!-- theme-toolbar-background -->
|
||||
<stop offset="50%" stop-color="#fff"/>
|
||||
<linearGradient id="bypass-light" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
|
||||
<stop offset="0%" stop-color="#dde1e4a0"/> <!-- theme-splitter-color (0.5 opacity) -->
|
||||
<stop offset="50%" stop-color="transparent"/>
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient id="bypass-dark" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">
|
||||
<stop offset="0%" stop-color="#343c45"/> <!-- theme-toolbar-background -->
|
||||
<linearGradient id="bypass-dark" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
|
||||
<stop offset="0%" stop-color="#454d5d"/> <!-- theme-splitter-color -->
|
||||
<stop offset="50%" stop-color="transparent"/>
|
||||
</linearGradient>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -595,45 +595,43 @@ html, body, #app, #memory-tool {
|
|||
* Dagre-D3 graphs
|
||||
*/
|
||||
|
||||
svg {
|
||||
--arrow-color: var(--theme-splitter-color);
|
||||
--text-color: var(--theme-body-color-alt);
|
||||
}
|
||||
|
||||
.theme-dark svg {
|
||||
--arrow-color: var(--theme-body-color-alt);
|
||||
}
|
||||
|
||||
svg #arrowhead {
|
||||
/* !important is needed to override inline style */
|
||||
fill: var(--arrow-color) !important;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke-width: 1px;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.theme-dark .edgePath path {
|
||||
stroke: var(--theme-body-color-alt);
|
||||
}
|
||||
.theme-light .edgePath path {
|
||||
stroke: var(--theme-splitter-color);
|
||||
stroke: var(--arrow-color);
|
||||
}
|
||||
|
||||
g.edgeLabel rect {
|
||||
fill: var(--theme-body-background);
|
||||
}
|
||||
|
||||
g.edgeLabel tspan {
|
||||
fill: var(--theme-body-color-alt);
|
||||
fill: var(--text-color);
|
||||
}
|
||||
|
||||
.nodes rect {
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.nodes rect {
|
||||
stroke: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
.theme-light rect {
|
||||
fill: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
.theme-dark rect {
|
||||
stroke: var(--theme-splitter-color);
|
||||
fill: var(--theme-toolbar-background);
|
||||
}
|
||||
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
text {
|
||||
fill: var(--theme-body-color-alt);
|
||||
font-size: 1.25em;
|
||||
fill: var(--text-color);
|
||||
/* Make sure text stays inside its container in RTL locales */
|
||||
direction: ltr;
|
||||
}
|
||||
|
|
|
@ -20,31 +20,28 @@
|
|||
svg {
|
||||
overflow: hidden;
|
||||
-moz-box-flex: 1;
|
||||
--arrow-color: var(--theme-splitter-color);
|
||||
--text-color: var(--theme-body-color-alt);
|
||||
}
|
||||
|
||||
.theme-dark svg {
|
||||
--arrow-color: var(--theme-body-color-alt);
|
||||
}
|
||||
|
||||
/* Edges in graph */
|
||||
.edgePath path {
|
||||
stroke-width: 1px;
|
||||
fill: none;
|
||||
stroke: var(--arrow-color);
|
||||
}
|
||||
|
||||
.theme-dark .edgePath path {
|
||||
stroke: var(--theme-body-color-alt);
|
||||
}
|
||||
.theme-light .edgePath path {
|
||||
stroke: var(--theme-splitter-color);
|
||||
svg #arrowhead {
|
||||
/* !important is needed to override inline style */
|
||||
fill: var(--arrow-color) !important;
|
||||
}
|
||||
|
||||
/* AudioParam connection edges */
|
||||
g.edgePath.param-connection {
|
||||
g.edgePath.param-connection path {
|
||||
stroke-dasharray: 5,5;
|
||||
}
|
||||
|
||||
.theme-dark .edgePath.param-connection path {
|
||||
stroke: var(--theme-body-color-alt);
|
||||
}
|
||||
.theme-light .edgePath.param-connection path {
|
||||
stroke: var(--theme-splitter-color);
|
||||
stroke: var(--arrow-colo);
|
||||
}
|
||||
|
||||
/* Labels in AudioParam connection should have background that match
|
||||
|
@ -54,14 +51,14 @@ g.edgeLabel rect {
|
|||
fill: var(--theme-body-background);
|
||||
}
|
||||
g.edgeLabel tspan {
|
||||
fill: var(--theme-body-color-alt);
|
||||
fill: var(--text-color);
|
||||
}
|
||||
|
||||
/* Audio Nodes */
|
||||
.nodes rect {
|
||||
stroke-width: 1px;
|
||||
cursor: pointer;
|
||||
stroke: var(--theme-tab-toolbar-background);
|
||||
stroke: var(--theme-splitter-color);
|
||||
fill: var(--theme-toolbar-background);
|
||||
}
|
||||
|
||||
|
@ -72,18 +69,18 @@ g.edgeLabel tspan {
|
|||
.theme-light .nodes g.bypassed rect {
|
||||
fill: url(chrome://devtools/skin/images/filters.svg#bypass-light);
|
||||
}
|
||||
|
||||
.theme-dark .nodes g.bypassed rect {
|
||||
fill: url(chrome://devtools/skin/images/filters.svg#bypass-dark);
|
||||
}
|
||||
|
||||
.nodes g.bypassed.selected rect {
|
||||
stroke: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
/*
|
||||
.nodes g.bypassed text {
|
||||
opacity: 0.8;
|
||||
opacity: 0.6;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Selected Nodes
|
||||
|
@ -92,25 +89,21 @@ g.edgeLabel tspan {
|
|||
fill: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
/* Don't style bypassed nodes text different because it'd be illegible in light-theme */
|
||||
.theme-light g.selected:not(.bypassed) text {
|
||||
fill: var(--theme-toolbar-background);
|
||||
/* Don't style bypassed nodes text differently because it'd be illegible in light-theme */
|
||||
g.selected:not(.bypassed) text {
|
||||
fill: var(--theme-selection-color);
|
||||
}
|
||||
|
||||
|
||||
/* Text in nodes and edges */
|
||||
text {
|
||||
cursor: default; /* override the "text" cursor */
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
fill: var(--text-color);
|
||||
font-size: 1.25em;
|
||||
/* Make sure text stays inside its container in RTL locales */
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
text {
|
||||
fill: var(--theme-body-color-alt);
|
||||
}
|
||||
|
||||
|
||||
.nodes text {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -260,6 +260,7 @@ skip-if = os != "win"
|
|||
[browser_webconsole_bug_632347_iterators_generators.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
||||
[browser_webconsole_bug_632817.js]
|
||||
skip-if = true # Bug 1244707
|
||||
[browser_webconsole_bug_642108_pruneTest.js]
|
||||
[browser_webconsole_autocomplete_and_selfxss.js]
|
||||
subsuite = clipboard
|
||||
|
|
|
@ -697,6 +697,7 @@ GK_ATOM(onanimationiteration, "onanimationiteration")
|
|||
GK_ATOM(onanimationstart, "onanimationstart")
|
||||
GK_ATOM(onantennaavailablechange, "onantennaavailablechange")
|
||||
GK_ATOM(onAppCommand, "onAppCommand")
|
||||
GK_ATOM(onappinstalled, "onappinstalled")
|
||||
GK_ATOM(onattributechanged, "onattributechanged")
|
||||
GK_ATOM(onattributereadreq, "onattributereadreq")
|
||||
GK_ATOM(onattributewritereq, "onattributewritereq")
|
||||
|
|
|
@ -1886,7 +1886,8 @@ nsINode::Prepend(const Sequence<OwningNodeOrString>& aNodes,
|
|||
return;
|
||||
}
|
||||
|
||||
InsertBefore(*node, mFirstChild, aRv);
|
||||
nsCOMPtr<nsINode> refNode = mFirstChild;
|
||||
InsertBefore(*node, refNode, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2843,6 +2843,11 @@ CanvasRenderingContext2D::UpdateFilter()
|
|||
{
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (!presShell || presShell->IsDestroying()) {
|
||||
// Ensure we set an empty filter and update the state to
|
||||
// reflect the current "taint" status of the canvas
|
||||
CurrentState().filter = FilterDescription();
|
||||
CurrentState().filterSourceGraphicTainted =
|
||||
(mCanvasElement && mCanvasElement->IsWriteOnly());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1082,6 +1082,18 @@ protected:
|
|||
RefPtr<nsSVGFilterChainObserver> filterChainObserver;
|
||||
mozilla::gfx::FilterDescription filter;
|
||||
nsTArray<RefPtr<mozilla::gfx::SourceSurface>> filterAdditionalImages;
|
||||
|
||||
// This keeps track of whether the canvas was "tainted" or not when
|
||||
// we last used a filter. This is a security measure, whereby the
|
||||
// canvas is flipped to write-only if a cross-origin image is drawn to it.
|
||||
// This is to stop bad actors from reading back data they shouldn't have
|
||||
// access to.
|
||||
//
|
||||
// This also limits what filters we can apply to the context; in particular
|
||||
// feDisplacementMap is restricted.
|
||||
//
|
||||
// We keep track of this to ensure that if this gets out of sync with the
|
||||
// tainted state of the canvas itself, we update our filters accordingly.
|
||||
bool filterSourceGraphicTainted;
|
||||
|
||||
bool imageSmoothingEnabled;
|
||||
|
|
|
@ -180,24 +180,6 @@ WebGLContext::InitWebGL2(FailureReason* const out_failReason)
|
|||
|
||||
//////
|
||||
|
||||
static const GLenum kWebGL2_CompressedFormats[] = {
|
||||
LOCAL_GL_COMPRESSED_R11_EAC,
|
||||
LOCAL_GL_COMPRESSED_SIGNED_R11_EAC,
|
||||
LOCAL_GL_COMPRESSED_RG11_EAC,
|
||||
LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC,
|
||||
LOCAL_GL_COMPRESSED_RGB8_ETC2,
|
||||
LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
|
||||
LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC,
|
||||
LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
|
||||
LOCAL_GL_COMPRESSED_SRGB8_ETC2,
|
||||
LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
|
||||
};
|
||||
|
||||
mCompressedTextureFormats.AppendElements(kWebGL2_CompressedFormats,
|
||||
MOZ_ARRAY_LENGTH(kWebGL2_CompressedFormats));
|
||||
|
||||
//////
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ WebGLContext::GetExtensionString(WebGLExtensionID ext)
|
|||
WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_es3)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_es3_0)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc)
|
||||
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc)
|
||||
|
@ -122,6 +122,8 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
|||
// WEBGL_
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_atc:
|
||||
return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture);
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_es3_0:
|
||||
return gl->IsSupported(gl::GLFeature::ES3_compatibility);
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_etc1:
|
||||
return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture);
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
|
||||
|
@ -212,8 +214,6 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
|||
switch (ext) {
|
||||
case WebGLExtensionID::EXT_disjoint_timer_query:
|
||||
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_es3:
|
||||
return gl->IsExtensionSupported(gl::GLContext::ARB_ES3_compatibility);
|
||||
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
|
@ -395,7 +395,7 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
|
|||
case WebGLExtensionID::WEBGL_compressed_texture_atc:
|
||||
obj = new WebGLExtensionCompressedTextureATC(this);
|
||||
break;
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_es3:
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_es3_0:
|
||||
obj = new WebGLExtensionCompressedTextureES3(this);
|
||||
break;
|
||||
case WebGLExtensionID::WEBGL_compressed_texture_etc1:
|
||||
|
|
|
@ -17,6 +17,18 @@ namespace mozilla {
|
|||
WebGLExtensionCompressedTextureES3::WebGLExtensionCompressedTextureES3(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
// GLES 3.0.4, p147, table 3.19
|
||||
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
||||
// Note that all compressed texture formats are filterable:
|
||||
// GLES 3.0.4 p161:
|
||||
// "[A] texture is complete unless any of the following conditions hold true:
|
||||
// [...]
|
||||
// * The effective internal format specified for the texture arrays is a sized
|
||||
// internal color format that is not texture-filterable (see table 3.13) and [the
|
||||
// mag filter requires filtering]."
|
||||
// Compressed formats are not sized internal color formats, and indeed they are not
|
||||
// listed in table 3.13.
|
||||
|
||||
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
|
||||
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto& fua = webgl_->mFormatUsage;
|
||||
|
|
|
@ -959,28 +959,6 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
|
|||
fnAllowES3TexFormat(FOO(DEPTH24_STENCIL8 ), true, false);
|
||||
fnAllowES3TexFormat(FOO(DEPTH32F_STENCIL8 ), true, false);
|
||||
|
||||
// GLES 3.0.4, p147, table 3.19
|
||||
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
||||
// Note that all compressed texture formats are filterable:
|
||||
// GLES 3.0.4 p161:
|
||||
// "[A] texture is complete unless any of the following conditions hold true:
|
||||
// [...]
|
||||
// * The effective internal format specified for the texture arrays is a sized
|
||||
// internal color format that is not texture-filterable (see table 3.13) and [the
|
||||
// mag filter requires filtering]."
|
||||
// Compressed formats are not sized internal color formats, and indeed they are not
|
||||
// listed in table 3.13.
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_ETC2 ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_ETC2 ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_RGBA8_ETC2_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_R11_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_RG11_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_R11_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_RG11_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), false, true);
|
||||
|
||||
#undef FOO
|
||||
|
||||
// GLES 3.0.4, p206, "Required Renderbuffer Formats":
|
||||
|
|
|
@ -158,7 +158,7 @@ enum class WebGLExtensionID : uint8_t {
|
|||
OES_vertex_array_object,
|
||||
WEBGL_color_buffer_float,
|
||||
WEBGL_compressed_texture_atc,
|
||||
WEBGL_compressed_texture_es3,
|
||||
WEBGL_compressed_texture_es3_0,
|
||||
WEBGL_compressed_texture_etc1,
|
||||
WEBGL_compressed_texture_pvrtc,
|
||||
WEBGL_compressed_texture_s3tc,
|
||||
|
|
|
@ -171,11 +171,7 @@ function runTestDisabled() {
|
|||
debug("Testing binding enum with extension disabled");
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats", "[]");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "10");
|
||||
}
|
||||
shouldBe("supportedFormats", "[]");
|
||||
}
|
||||
|
||||
function formatExists(format, supportedFormats) {
|
||||
|
@ -208,12 +204,7 @@ function runTestExtension() {
|
|||
}
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
// There should be exactly 3 formats for WebGL 1.0 and 13 formats for WebGL 2.0.
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats.length", "3");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "13");
|
||||
}
|
||||
shouldBe("supportedFormats.length", "3");
|
||||
|
||||
// check that all 3 formats exist
|
||||
for (var name in validFormats.length) {
|
||||
|
|
|
@ -144,11 +144,7 @@ function runTestDisabled() {
|
|||
debug("Testing binding enum with extension disabled");
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats", "[]");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "10");
|
||||
}
|
||||
shouldBe("supportedFormats", "[]");
|
||||
}
|
||||
|
||||
function formatExists(format, supportedFormats) {
|
||||
|
@ -181,12 +177,7 @@ function runTestExtension() {
|
|||
}
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
// There should be exactly 4 formats for WebGL 1.0 and 14 formats for WebGL 2.0.
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats.length", "4");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "14");
|
||||
}
|
||||
shouldBe("supportedFormats.length", "4");
|
||||
|
||||
// check that all 4 formats exist
|
||||
for (var name in validFormats.length) {
|
||||
|
|
|
@ -151,11 +151,7 @@ function runTestDisabled() {
|
|||
debug("Testing binding enum with extension disabled");
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats", "[]");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "10");
|
||||
}
|
||||
shouldBe("supportedFormats", "[]");
|
||||
}
|
||||
|
||||
function formatExists(format, supportedFormats) {
|
||||
|
@ -188,12 +184,7 @@ function runTestExtension() {
|
|||
}
|
||||
|
||||
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||||
// There should be exactly 4 formats for WebGL 1.0 and 14 formats for WebGL 2.0.
|
||||
if (contextVersion < 2) {
|
||||
shouldBe("supportedFormats.length", "4");
|
||||
} else {
|
||||
shouldBe("supportedFormats.length", "14");
|
||||
}
|
||||
shouldBe("supportedFormats.length", "4");
|
||||
|
||||
// check that all 4 formats exist
|
||||
for (var name in validFormats.length) {
|
||||
|
|
|
@ -620,8 +620,8 @@ WINDOW_ONLY_EVENT(vrdisplaypresentchange,
|
|||
EventNameType_None,
|
||||
eBasicEventClass)
|
||||
// Install events as per W3C Manifest spec
|
||||
WINDOW_ONLY_EVENT(install,
|
||||
eInstall,
|
||||
WINDOW_ONLY_EVENT(appinstalled,
|
||||
eAppInstalled,
|
||||
EventNameType_None,
|
||||
eBasicEventClass)
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
|
||||
|
||||
/* 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 protocol PBrowser;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
protocol PContentDialog
|
||||
{
|
||||
manager PBrowser;
|
||||
|
||||
child:
|
||||
async __delete__(int32_t[] aIntParams, nsString[] aStringParams);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -31,8 +31,8 @@ const MessageHandler = {
|
|||
this.obtainManifest.bind(this)
|
||||
);
|
||||
addMessageListener(
|
||||
"DOM:Manifest:FireInstallEvent",
|
||||
this.fireInstallEvent.bind(this)
|
||||
"DOM:Manifest:FireAppInstalledEvent",
|
||||
this.fireAppInstalledEvent.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -65,8 +65,8 @@ const MessageHandler = {
|
|||
sendAsyncMessage("DOM:ManifestObtainer:Obtain", response);
|
||||
}),
|
||||
|
||||
fireInstallEvent({data: {id}}){
|
||||
const ev = new Event("install");
|
||||
fireAppInstalledEvent({data: {id}}){
|
||||
const ev = new Event("appinstalled");
|
||||
const response = makeMsgResponse(id);
|
||||
if (!content || content.top !== content) {
|
||||
const msg = "Can only dispatch install event on top-level browsing contexts.";
|
||||
|
@ -75,7 +75,7 @@ const MessageHandler = {
|
|||
response.success = true;
|
||||
content.dispatchEvent(ev);
|
||||
}
|
||||
sendAsyncMessage("DOM:Manifest:FireInstallEvent", response);
|
||||
sendAsyncMessage("DOM:Manifest:FireAppInstalledEvent", response);
|
||||
}
|
||||
};
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
file_reg_install_event.html
|
||||
file_reg_appinstalled_event.html
|
||||
file_testserver.sjs
|
||||
manifestLoader.html
|
||||
resource.sjs
|
||||
[browser_ManifestFinder_browserHasManifestLink.js]
|
||||
[browser_ManifestObtainer_obtain.js]
|
||||
[browser_fire_install_event.js]
|
||||
[browser_fire_appinstalled_event.js]
|
|
@ -2,16 +2,16 @@
|
|||
/*global Cu, BrowserTestUtils, ok, add_task, gBrowser */
|
||||
"use strict";
|
||||
const { PromiseMessage } = Cu.import("resource://gre/modules/PromiseMessage.jsm", {});
|
||||
const testPath = "/browser/dom/manifest/test/file_reg_install_event.html";
|
||||
const testPath = "/browser/dom/manifest/test/file_reg_appinstalled_event.html";
|
||||
const defaultURL = new URL("http://example.org/browser/dom/manifest/test/file_testserver.sjs");
|
||||
const testURL = new URL(defaultURL);
|
||||
testURL.searchParams.append("file", testPath);
|
||||
|
||||
// Enable window.oninstall, so we can fire events at it.
|
||||
function enableOnInstallPref() {
|
||||
// Enable window.onappinstalled, so we can fire events at it.
|
||||
function enableOnAppInstalledPref() {
|
||||
const ops = {
|
||||
"set": [
|
||||
["dom.manifest.oninstall", true],
|
||||
["dom.manifest.onappinstalled", true],
|
||||
],
|
||||
};
|
||||
return SpecialPowers.pushPrefEnv(ops);
|
||||
|
@ -22,22 +22,22 @@ function enableOnInstallPref() {
|
|||
function* theTest(aBrowser) {
|
||||
aBrowser.allowEvents = true;
|
||||
let waitForInstall = ContentTask.spawn(aBrowser, null, function*() {
|
||||
yield ContentTaskUtils.waitForEvent(content.window, "install");
|
||||
yield ContentTaskUtils.waitForEvent(content.window, "appinstalled");
|
||||
});
|
||||
const { data: { success } } = yield PromiseMessage
|
||||
.send(aBrowser.messageManager, "DOM:Manifest:FireInstallEvent");
|
||||
.send(aBrowser.messageManager, "DOM:Manifest:FireAppInstalledEvent");
|
||||
ok(success, "message sent and received successfully.");
|
||||
try {
|
||||
yield waitForInstall;
|
||||
ok(true, "Install event fired");
|
||||
ok(true, "AppInstalled event fired");
|
||||
} catch (err) {
|
||||
ok(false, "Install event didn't fire: " + err.message);
|
||||
ok(false, "AppInstalled event didn't fire: " + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Open a tab and run the test
|
||||
add_task(function*() {
|
||||
yield enableOnInstallPref();
|
||||
yield enableOnAppInstalledPref();
|
||||
let tabOptions = {
|
||||
gBrowser: gBrowser,
|
||||
url: testURL.href,
|
|
@ -1,14 +1,14 @@
|
|||
<meta charset=utf-8>
|
||||
<script>
|
||||
"use strict";
|
||||
window.addEventListener("install", () => {
|
||||
window.addEventListener("appinstalled", () => {
|
||||
document
|
||||
.querySelector("#output")
|
||||
.innerHTML = "event received!";
|
||||
// Send a custom event back to the browser
|
||||
// to acknowledge that we got this
|
||||
const detail = { result: true }
|
||||
const ev = new CustomEvent("dom.manifest.oninstall", { detail });
|
||||
const ev = new CustomEvent("dom.manifest.onappinstalled", { detail });
|
||||
document.dispatchEvent(ev);
|
||||
});
|
||||
</script>
|
|
@ -3,7 +3,7 @@ support-files =
|
|||
common.js
|
||||
resource.sjs
|
||||
manifestLoader.html
|
||||
file_reg_install_event.html
|
||||
file_reg_appinstalled_event.html
|
||||
file_testserver.sjs
|
||||
[test_ImageObjectProcessor_sizes.html]
|
||||
[test_ImageObjectProcessor_src.html]
|
||||
|
@ -20,4 +20,4 @@ support-files =
|
|||
[test_ManifestProcessor_start_url.html]
|
||||
[test_ManifestProcessor_theme_color.html]
|
||||
[test_ManifestProcessor_warnings.html]
|
||||
[test_window_oninstall_event.html]
|
||||
[test_window_onappinstalled_event.html]
|
|
@ -6,17 +6,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1265279 - Web Manifest: Implement window.oninstall</title>
|
||||
<title>Test for Bug 1309099 - Web Manifest: Implement window.onappinstalled</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
<script>
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const finish = SimpleTest.finish.bind(SimpleTest);
|
||||
enableOnInstallPref()
|
||||
enableOnAppInstalledPref()
|
||||
.then(createIframe)
|
||||
.then(checkImplementation)
|
||||
.then(checkOnInstallEventFires)
|
||||
.then(checkOnappInstalledEventFired)
|
||||
.then(checkAddEventListenerFires)
|
||||
.then(finish)
|
||||
.catch(err => {
|
||||
|
@ -24,10 +24,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
finish();
|
||||
});
|
||||
|
||||
function enableOnInstallPref() {
|
||||
function enableOnAppInstalledPref() {
|
||||
const ops = {
|
||||
"set": [
|
||||
["dom.manifest.oninstall", true],
|
||||
["dom.manifest.onappinstalled", true],
|
||||
],
|
||||
};
|
||||
return SpecialPowers.pushPrefEnv(ops);
|
||||
|
@ -35,7 +35,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
|
||||
// WebIDL conditional annotations for an interface are evaluate once per
|
||||
// global, so we need to create an iframe to see the effects of calling
|
||||
// enableOnInstallPref().
|
||||
// enableOnAppInstalledPref().
|
||||
function createIframe() {
|
||||
return new Promise((resolve) => {
|
||||
const iframe = document.createElement("iframe");
|
||||
|
@ -48,18 +48,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
// Check that the WebIDL is as expected.
|
||||
function checkImplementation(ifrWindow) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hasOnInstallProp = ifrWindow.hasOwnProperty("oninstall");
|
||||
ok(hasOnInstallProp, "window has own oninstall property");
|
||||
const hasOnAppInstalledProp = ifrWindow.hasOwnProperty("onappinstalled");
|
||||
ok(hasOnAppInstalledProp, "window has own onappinstalled property");
|
||||
|
||||
// no point in continuing
|
||||
if (!hasOnInstallProp) {
|
||||
const err = new Error("No 'oninstall' IDL attribute. Aborting early.");
|
||||
if (!hasOnAppInstalledProp) {
|
||||
const err = new Error("No 'onappinstalled' IDL attribute. Aborting early.");
|
||||
return reject(err);
|
||||
}
|
||||
is(ifrWindow.oninstall, null, "window install is initially set to null");
|
||||
is(ifrWindow.onappinstalled, null, "window install is initially set to null");
|
||||
|
||||
// Check that enumerable, configurable, and has a getter and setter.
|
||||
const objDescriptor = Object.getOwnPropertyDescriptor(ifrWindow, "oninstall");
|
||||
const objDescriptor = Object.getOwnPropertyDescriptor(ifrWindow, "onappinstalled");
|
||||
ok(objDescriptor.enumerable, "is enumerable");
|
||||
ok(objDescriptor.configurable, "is configurable");
|
||||
ok(objDescriptor.hasOwnProperty("get"), "has getter");
|
||||
|
@ -68,13 +68,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
});
|
||||
}
|
||||
|
||||
// Checks that .oninstall receives an event.
|
||||
function checkOnInstallEventFires(ifrWindow) {
|
||||
const customEv = new CustomEvent("install");
|
||||
// Checks that .onappinstalled receives an event.
|
||||
function checkOnappInstalledEventFired(ifrWindow) {
|
||||
const customEv = new CustomEvent("appinstalled");
|
||||
return new Promise((resolve) => {
|
||||
// Test is we receive the event on `oninstall`
|
||||
ifrWindow.oninstall = ev => {
|
||||
ifrWindow.oninstall = null;
|
||||
// Test is we receive the event on `appinstalled`
|
||||
ifrWindow.onappinstalled = ev => {
|
||||
ifrWindow.onappinstalled = null;
|
||||
is(ev, customEv, "The events should be the same event object");
|
||||
resolve(ifrWindow);
|
||||
};
|
||||
|
@ -82,12 +82,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
|||
});
|
||||
}
|
||||
|
||||
// Checks that .addEventListener("install") receives an event.
|
||||
// Checks that .addEventListener("appinstalled") receives an event.
|
||||
function checkAddEventListenerFires(ifrWindow) {
|
||||
const customEv = new CustomEvent("install");
|
||||
const customEv = new CustomEvent("appinstalled");
|
||||
return new Promise((resolve) => {
|
||||
ifrWindow.addEventListener("install", function handler(ev) {
|
||||
ifrWindow.removeEventListener("install", handler);
|
||||
ifrWindow.addEventListener("appinstalled", function handler(ev) {
|
||||
ifrWindow.removeEventListener("appinstalled", handler);
|
||||
is(ev, customEv, "The events should be the same");
|
||||
resolve(ifrWindow);
|
||||
});
|
|
@ -2075,7 +2075,7 @@ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
|
|||
static bool
|
||||
PluginInfoIsFlash(const nsPluginInfo& info)
|
||||
{
|
||||
if (strcmp(info.fName, "Shockwave Flash") != 0) {
|
||||
if (!info.fName || strcmp(info.fName, "Shockwave Flash") != 0) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < info.fVariantCount; ++i) {
|
||||
|
|
|
@ -92,10 +92,10 @@ typedef any Transferable;
|
|||
Window implements GlobalEventHandlers;
|
||||
Window implements WindowEventHandlers;
|
||||
|
||||
// https://w3c.github.io/manifest/#oninstall-attribute
|
||||
// https://www.w3.org/TR/appmanifest/#onappinstalled-attribute
|
||||
partial interface Window {
|
||||
[Pref="dom.manifest.oninstall"]
|
||||
attribute EventHandler oninstall;
|
||||
[Pref="dom.manifest.onappinstalled"]
|
||||
attribute EventHandler onappinstalled;
|
||||
};
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/
|
||||
|
|
|
@ -26,7 +26,6 @@ XPIDL_SOURCES += [
|
|||
|
||||
if CONFIG['NS_PRINTING']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIPrintingPrompt.idl',
|
||||
'nsIPrintingPromptService.idl',
|
||||
'nsIWebBrowserPrint.idl',
|
||||
]
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This is the printing prompt interface which can be used without knowlege of a
|
||||
* parent window. The parentage is hidden by the GetInterface though
|
||||
* which it is gotten. This interface is identical to nsIPintingPromptService
|
||||
* but without the parent nsIDOMWindow parameter. See nsIPrintingPromptService
|
||||
* for all documentation.
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIWebBrowserPrint.idl"
|
||||
#include "nsIWebProgressListener.idl"
|
||||
#include "nsIPrintSettings.idl"
|
||||
#include "nsIPrintProgressParams.idl"
|
||||
#include "nsIObserver.idl"
|
||||
|
||||
[scriptable, uuid(44E314CA-75B1-4f3d-9553-9B3507912108)]
|
||||
interface nsIPrintingPrompt : nsISupports
|
||||
{
|
||||
/**
|
||||
* This service enables embedders to implement their own Print and Progress Dialogs.
|
||||
* Each platform has a "base" or "basckstop" implementation of the service. The
|
||||
* service is automatically registered at start up.
|
||||
*
|
||||
* Historically, platform toolkits with native dialogs have implemented them in the GFX layer
|
||||
* Usually they were displayed when a new DeviceContextSpec specific to that platform
|
||||
* was created.
|
||||
*
|
||||
* Windows: The GFX layer no longers supports default toolkit behavior for displaying the
|
||||
* native Print Dialog.
|
||||
* If an embedder implemented service returns any error code (other than NS_ERROR_ABORT)
|
||||
* printing will terminate.
|
||||
*
|
||||
* Returning NS_OK assumes that the PrintSettings object was correctly filled in and
|
||||
* if it does not have valid fields for printer name, etc. it may also terminate.
|
||||
*
|
||||
* Defaults for platform service:
|
||||
* showPrintDialog - displays a native dialog
|
||||
* showPageSetup - displays a XUL dialog
|
||||
* showProgress - displays a XUL dialog
|
||||
* showPrinterProperties - n/a
|
||||
*
|
||||
* Summary for Windows Embedders:
|
||||
* Stated once again: There is no "fallback" native platform support in GFX for the
|
||||
* displaying of the native print dialog. The current default implementation for Windows
|
||||
* display a native print dialog but a XUL-based progress dialog.
|
||||
* If you wish to have a native progress dialog on Windows you will have to create and
|
||||
* register your own service.
|
||||
*
|
||||
* Note: The Windows version Mozilla implements this service which is
|
||||
* automatically built and registered for you. You can use it as an example.
|
||||
* It is located at "mozilla/embedding/components/printingui/win". That service
|
||||
* is capable of displaying a native print dialog and a XUL progress dialog.
|
||||
*
|
||||
* To fly your own dialog you may:
|
||||
*
|
||||
* 1) Implement this service to display at least the Print Dialog and a Print Progress Dialog
|
||||
* or you may implement just one of the dialogs and pass back NS_ERROR_NOT_IMPLEMENTED
|
||||
* for any of the others.
|
||||
*
|
||||
* 2) For the Print Dialog:
|
||||
* You may stub out this service by having all the methods return NS_ERROR_NOT_IMPLEMENTED.
|
||||
* You can then fly you own dialog and then properly fill in the PrintSettings object
|
||||
* before calling nsIWebBrowserPrint's Print method. If you stub out this service
|
||||
* you MUST set "printSilent" to true, if you do not, Printing will terminate and an
|
||||
* error dialog will be displayed.
|
||||
*
|
||||
* Mac: The GFX layer still supports default toolkit behavior for displaying the Print Dialog.
|
||||
* If an embedder implemented service returns NS_ERROR_NOT_IMPLEMENTED for "showPrintDialog"
|
||||
* The toolkit will display the native print dialog.
|
||||
*
|
||||
* Defaults for platform service:
|
||||
* Mac OS9: showPrintDialog - displays a native dialog
|
||||
* showPageSetup - displays a native dialog
|
||||
* showProgress - displays a XUL dialog
|
||||
* showPrinterProperties - n/a
|
||||
*
|
||||
* Mac OSX: showPrintDialog - displays a native dialog
|
||||
* showPageSetup - displays a native dialog
|
||||
* showProgress - not implemented (provided by OS)
|
||||
* showPrinterProperties - n/a
|
||||
*
|
||||
* GTK: There are no native dialog for GTK.
|
||||
*
|
||||
* Defaults for platform service:
|
||||
* showPrintDialog - displays a XUL dialog
|
||||
* showPageSetup - displays a XUL dialog
|
||||
* showProgress - displays a XUL dialog
|
||||
* showPrinterProperties - displays a XUL dialog
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Show the Print Dialog
|
||||
*
|
||||
* @param webBrowserPrint - represents the document to be printed
|
||||
* @param printSettings - PrintSettings for print "job"
|
||||
*
|
||||
*/
|
||||
void showPrintDialog(in nsIWebBrowserPrint webBrowserPrint,
|
||||
in nsIPrintSettings printSettings);
|
||||
|
||||
/**
|
||||
* Shows the print progress dialog
|
||||
*
|
||||
* @param webBrowserPrint - represents the document to be printed
|
||||
* @param printSettings - PrintSettings for print "job"
|
||||
* @param openDialogObserver - an observer that will be notifed when the dialog is opened
|
||||
* @param isForPrinting - true - for printing, false for print preview
|
||||
* @param webProgressListener - additional listener can be registered for progress notifications
|
||||
* @param printProgressParams - parameter object for passing progress state
|
||||
* @param notifyOnOpen - this indicates that the observer will be notified when the progress
|
||||
* dialog has been opened. If false is returned it means the observer
|
||||
* (usually the caller) shouldn't wait
|
||||
* For Print Preview Progress there is intermediate progress
|
||||
*/
|
||||
void showProgress(in nsIWebBrowserPrint webBrowserPrint,
|
||||
in nsIPrintSettings printSettings,
|
||||
in nsIObserver openDialogObserver,
|
||||
in boolean isForPrinting,
|
||||
out nsIWebProgressListener webProgressListener,
|
||||
out nsIPrintProgressParams printProgressParams,
|
||||
out boolean notifyOnOpen);
|
||||
|
||||
/**
|
||||
* Shows the print progress dialog
|
||||
*
|
||||
* @param printSettings - PrintSettings for page setup (required)
|
||||
* @param aObs - An observer to know if the contents of the Print Settings
|
||||
* object has changed while the dialog is being shown.
|
||||
* For example, some platforms may implement an "Apply" button (not required)
|
||||
*/
|
||||
void showPageSetup(in nsIPrintSettings printSettings, in nsIObserver aObs);
|
||||
|
||||
/**
|
||||
* Sometimes platforms need to bring up a special properties dialog for showing
|
||||
* print specific properties. Although the PrintSettings has a place to set the
|
||||
* printer name, here is is an argument to be clear as to what printer is being
|
||||
* asked to have the properties set for it. The Printer name in the PS is ignored.
|
||||
*
|
||||
* @param printerName - name of printer (required)
|
||||
* @param printSettings - PrintSettings for page setup (required)
|
||||
*/
|
||||
void showPrinterProperties(in wstring printerName,
|
||||
in nsIPrintSettings printSettings);
|
||||
};
|
|
@ -142,7 +142,7 @@ nsPrintingPromptService::GetHWNDForDOMWindow(mozIDOMWindowProxy *aWindow)
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsIPrintingPrompt
|
||||
// nsIPrintingPromptService
|
||||
|
||||
//-----------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -73,7 +73,8 @@ GLImage::GetAsSourceSurface()
|
|||
|
||||
ScopedFramebufferForTexture autoFBForTex(sSnapshotContext, scopedTex.Texture());
|
||||
if (!autoFBForTex.IsComplete()) {
|
||||
MOZ_CRASH("GFX: ScopedFramebufferForTexture failed.");
|
||||
gfxCriticalError() << "GetAsSourceSurface: ScopedFramebufferForTexture failed.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const gl::OriginPos destOrigin = gl::OriginPos::TopLeft;
|
||||
|
|
|
@ -546,7 +546,10 @@ BufferTextureHost::SetCompositor(Compositor* aCompositor)
|
|||
if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
|
||||
mFirstSource->SetOwner(nullptr);
|
||||
}
|
||||
mFirstSource = nullptr;
|
||||
if (mFirstSource) {
|
||||
mFirstSource = nullptr;
|
||||
mNeedsFullUpdate = true;
|
||||
}
|
||||
mCompositor = aCompositor;
|
||||
}
|
||||
|
||||
|
@ -717,6 +720,7 @@ BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
|
|||
aTexture->AsSourceBasic()->SetBufferTextureHost(this);
|
||||
aTexture->AsDataTextureSource()->SetOwner(this);
|
||||
mFirstSource = aTexture->AsDataTextureSource();
|
||||
mNeedsFullUpdate = true;
|
||||
}
|
||||
|
||||
if (!mHasIntermediateBuffer) {
|
||||
|
|
|
@ -578,6 +578,11 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
{
|
||||
*aSent = false;
|
||||
|
||||
MOZ_ASSERT(HasShadowManager(), "no manager to forward to");
|
||||
if (!IPCOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GetCompositorBridgeChild()->WillEndTransaction();
|
||||
|
||||
MOZ_ASSERT(aId);
|
||||
|
@ -586,7 +591,6 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
RenderTraceScope rendertrace("Foward Transaction", "000091");
|
||||
MOZ_ASSERT(HasShadowManager(), "no manager to forward to");
|
||||
MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
|
||||
|
||||
DiagnosticTypes diagnostics = gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes();
|
||||
|
@ -729,9 +733,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
if (mTxn->mSwapRequired) {
|
||||
MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
|
||||
RenderTraceScope rendertrace3("Forward Transaction", "000093");
|
||||
if (!HasShadowManager() ||
|
||||
!mShadowManager->IPCOpen() ||
|
||||
!mShadowManager->SendUpdate(cset, mTxn->mDestroyedActors,
|
||||
if (!mShadowManager->SendUpdate(cset, mTxn->mDestroyedActors,
|
||||
GetFwdTransactionId(),
|
||||
aId, targetConfig, mPluginWindowData,
|
||||
mIsFirstPaint, aScheduleComposite,
|
||||
|
@ -745,9 +747,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
// assumes that aReplies is empty (DEBUG assertion)
|
||||
MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction..."));
|
||||
RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093");
|
||||
if (!HasShadowManager() ||
|
||||
!mShadowManager->IPCOpen() ||
|
||||
!mShadowManager->SendUpdateNoSwap(cset, mTxn->mDestroyedActors,
|
||||
if (!mShadowManager->SendUpdateNoSwap(cset, mTxn->mDestroyedActors,
|
||||
GetFwdTransactionId(),
|
||||
aId, targetConfig, mPluginWindowData,
|
||||
mIsFirstPaint, aScheduleComposite,
|
||||
|
|
|
@ -369,6 +369,66 @@ Module::addSizeOfMisc(MallocSizeOf mallocSizeOf,
|
|||
bytecode_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenBytes);
|
||||
}
|
||||
|
||||
|
||||
// Extracting machine code as JS object. The result has the "code" property, as
|
||||
// a Uint8Array, and the "segments" property as array objects. The objects
|
||||
// contain offsets in the "code" array and basic information about a code
|
||||
// segment/function body.
|
||||
bool
|
||||
Module::extractCode(JSContext* cx, MutableHandleValue vp)
|
||||
{
|
||||
RootedPlainObject result(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
RootedObject code(cx, JS_NewUint8Array(cx, code_.length()));
|
||||
if (!code)
|
||||
return false;
|
||||
|
||||
memcpy(code->as<TypedArrayObject>().viewDataUnshared(), code_.begin(), code_.length());
|
||||
|
||||
RootedValue value(cx, ObjectValue(*code));
|
||||
if (!JS_DefineProperty(cx, result, "code", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
RootedObject segments(cx, NewDenseEmptyArray(cx));
|
||||
if (!segments)
|
||||
return false;
|
||||
|
||||
for (auto p = metadata_->codeRanges.begin(); p != metadata_->codeRanges.end(); p++) {
|
||||
RootedObject segment(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
value.setNumber((uint32_t)p->begin());
|
||||
if (!JS_DefineProperty(cx, segment, "begin", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
value.setNumber((uint32_t)p->end());
|
||||
if (!JS_DefineProperty(cx, segment, "end", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
value.setNumber((uint32_t)p->kind());
|
||||
if (!JS_DefineProperty(cx, segment, "kind", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
if (p->isFunction()) {
|
||||
value.setNumber((uint32_t)p->funcDefIndex());
|
||||
if (!JS_DefineProperty(cx, segment, "funcDefIndex", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
value.setNumber((uint32_t)p->funcNonProfilingEntry());
|
||||
if (!JS_DefineProperty(cx, segment, "funcBodyBegin", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
value.setNumber((uint32_t)p->funcProfilingEpilogue());
|
||||
if (!JS_DefineProperty(cx, segment, "funcBodyEnd", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
}
|
||||
if (!NewbornArrayPush(cx, segments, ObjectValue(*segment)))
|
||||
return false;
|
||||
}
|
||||
|
||||
value.setObject(*segments);
|
||||
if (!JS_DefineProperty(cx, result, "segments", value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
vp.setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
EvaluateInitExpr(const ValVector& globalImports, InitExpr initExpr)
|
||||
{
|
||||
|
|
|
@ -242,6 +242,10 @@ class Module : public RefCounted<Module>
|
|||
Metadata::SeenSet* seenMetadata,
|
||||
ShareableBytes::SeenSet* seenBytes,
|
||||
size_t* code, size_t* data) const;
|
||||
|
||||
// Generated code analysis support:
|
||||
|
||||
bool extractCode(JSContext* cx, MutableHandleValue vp);
|
||||
};
|
||||
|
||||
typedef RefPtr<Module> SharedModule;
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
// selection of a default locale. See RuntimeDefaultLocale(), whose
|
||||
// value controls the value returned by DefaultLocale() that's what's
|
||||
// *actually* used.
|
||||
// localTZA:
|
||||
// The local time zone's adjustment from UTC. See LocalTZA().
|
||||
// icuDefaultTimeZone:
|
||||
// Time zone information provided by ICU. See intl_defaultTimeZone(),
|
||||
// whose value controls the value returned by DefaultTimeZone() that's
|
||||
// what's *actually* used.
|
||||
// formatters:
|
||||
// A Record storing formatters consistent with the above
|
||||
// runtimeDefaultLocale/localTZA values, for use with the appropriate
|
||||
|
@ -27,8 +29,9 @@
|
|||
// dateFormat: for Date's toLocaleDateString operation
|
||||
// timeFormat: for Date's toLocaleTimeString operation
|
||||
//
|
||||
// Using this cache, then, requires 1) verifying the current
|
||||
// runtimeDefaultLocale/localTZA are consistent with cached values, then
|
||||
// Using this cache, then, requires
|
||||
// 1) verifying the current runtimeDefaultLocale/icuDefaultTimeZone are
|
||||
// consistent with cached values, then
|
||||
// 2) seeing if the desired formatter is cached and returning it if so, or else
|
||||
// 3) create the desired formatter and store and return it.
|
||||
var dateTimeFormatCache = new Record();
|
||||
|
@ -50,15 +53,15 @@ function GetCachedFormat(format, required, defaults) {
|
|||
"dateTimeFormatCache");
|
||||
|
||||
var runtimeDefaultLocale = RuntimeDefaultLocale();
|
||||
var localTZA = LocalTZA();
|
||||
var icuDefaultTimeZone = intl_defaultTimeZone();
|
||||
|
||||
var formatters;
|
||||
if (dateTimeFormatCache.runtimeDefaultLocale !== runtimeDefaultLocale ||
|
||||
dateTimeFormatCache.localTZA !== localTZA)
|
||||
dateTimeFormatCache.icuDefaultTimeZone !== icuDefaultTimeZone)
|
||||
{
|
||||
formatters = dateTimeFormatCache.formatters = new Record();
|
||||
dateTimeFormatCache.runtimeDefaultLocale = runtimeDefaultLocale;
|
||||
dateTimeFormatCache.localTZA = localTZA;
|
||||
dateTimeFormatCache.icuDefaultTimeZone = icuDefaultTimeZone;
|
||||
} else {
|
||||
formatters = dateTimeFormatCache.formatters;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "builtin/Intl.h"
|
||||
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
|
@ -47,6 +48,7 @@ using namespace js;
|
|||
using mozilla::IsFinite;
|
||||
using mozilla::IsNegativeZero;
|
||||
using mozilla::MakeScopeExit;
|
||||
using mozilla::PodCopy;
|
||||
|
||||
#if ENABLE_INTL_API
|
||||
using icu::Locale;
|
||||
|
@ -379,6 +381,25 @@ ucal_getAttribute(const UCalendar* cal,
|
|||
MOZ_CRASH("ucal_getAttribute: Intl API disabled");
|
||||
}
|
||||
|
||||
static UEnumeration*
|
||||
ucal_openTimeZones(UErrorCode* status)
|
||||
{
|
||||
MOZ_CRASH("ucal_openTimeZones: Intl API disabled");
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, UChar* result, int32_t resultCapacity,
|
||||
UBool* isSystemID, UErrorCode* status)
|
||||
{
|
||||
MOZ_CRASH("ucal_getCanonicalTimeZoneID: Intl API disabled");
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* status)
|
||||
{
|
||||
MOZ_CRASH("ucal_getDefaultTimeZone: Intl API disabled");
|
||||
}
|
||||
|
||||
typedef void* UDateTimePatternGenerator;
|
||||
|
||||
static UDateTimePatternGenerator*
|
||||
|
@ -1931,6 +1952,160 @@ js::intl_availableCalendars(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a time zone map key. Time zones are keyed by their upper case name.
|
||||
*/
|
||||
static UniqueChars
|
||||
TimeZoneKey(JSContext* cx, const char* timeZone, size_t size)
|
||||
{
|
||||
UniqueChars timeZoneKey = cx->make_pod_array<char>(size);
|
||||
if (!timeZoneKey)
|
||||
return timeZoneKey;
|
||||
PodCopy(timeZoneKey.get(), timeZone, size);
|
||||
|
||||
// Convert time zone name to ASCII upper case.
|
||||
char* chars = timeZoneKey.get();
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
char c = chars[i];
|
||||
if ('a' <= c && c <= 'z')
|
||||
chars[i] = c & ~0x20;
|
||||
}
|
||||
|
||||
return timeZoneKey;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intl_availableTimeZones(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UEnumeration* values = ucal_openTimeZones(&status);
|
||||
if (U_FAILURE(status)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
|
||||
return false;
|
||||
}
|
||||
ScopedICUObject<UEnumeration, uenum_close> toClose(values);
|
||||
|
||||
RootedObject timeZones(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
|
||||
if (!timeZones)
|
||||
return false;
|
||||
RootedString jsTimeZone(cx);
|
||||
RootedValue element(cx);
|
||||
while (true) {
|
||||
int32_t size;
|
||||
const char* timeZone = uenum_next(values, &size, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
|
||||
return false;
|
||||
}
|
||||
if (timeZone == nullptr)
|
||||
break;
|
||||
|
||||
MOZ_ASSERT(size >= 0);
|
||||
UniqueChars timeZoneKey = TimeZoneKey(cx, timeZone, size_t(size));
|
||||
if (!timeZoneKey)
|
||||
return false;
|
||||
|
||||
RootedAtom atom(cx, Atomize(cx, timeZoneKey.get(), size_t(size)));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
jsTimeZone = NewStringCopyN<CanGC>(cx, timeZone, size_t(size));
|
||||
if (!jsTimeZone)
|
||||
return false;
|
||||
element.setString(jsTimeZone);
|
||||
|
||||
if (!DefineProperty(cx, timeZones, atom->asPropertyName(), element))
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*timeZones);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intl_canonicalizeTimeZone(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isString());
|
||||
|
||||
AutoStableStringChars stableChars(cx);
|
||||
if (!stableChars.initTwoByte(cx, args[0].toString()))
|
||||
return false;
|
||||
|
||||
mozilla::Range<const char16_t> tzchars = stableChars.twoByteRange();
|
||||
|
||||
Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
|
||||
if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
|
||||
return false;
|
||||
|
||||
UBool* isSystemID = nullptr;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t size = ucal_getCanonicalTimeZoneID(Char16ToUChar(tzchars.start().get()),
|
||||
tzchars.length(), Char16ToUChar(chars.begin()),
|
||||
INITIAL_CHAR_BUFFER_SIZE, isSystemID, &status);
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
MOZ_ASSERT(size >= 0);
|
||||
if (!chars.resize(size_t(size)))
|
||||
return false;
|
||||
status = U_ZERO_ERROR;
|
||||
ucal_getCanonicalTimeZoneID(Char16ToUChar(tzchars.start().get()), tzchars.length(),
|
||||
Char16ToUChar(chars.begin()), size, isSystemID, &status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(size >= 0);
|
||||
JSString* str = NewStringCopyN<CanGC>(cx, chars.begin(), size);
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intl_defaultTimeZone(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0);
|
||||
|
||||
// The current default might be stale, because JS::ResetTimeZone() doesn't
|
||||
// immediately update ICU's default time zone. So perform an update if
|
||||
// needed.
|
||||
js::ResyncICUDefaultTimeZone();
|
||||
|
||||
Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
|
||||
if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
|
||||
return false;
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t size = ucal_getDefaultTimeZone(Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
|
||||
&status);
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
MOZ_ASSERT(size >= 0);
|
||||
if (!chars.resize(size_t(size)))
|
||||
return false;
|
||||
status = U_ZERO_ERROR;
|
||||
ucal_getDefaultTimeZone(Char16ToUChar(chars.begin()), size, &status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(size >= 0);
|
||||
JSString* str = NewStringCopyN<CanGC>(cx, chars.begin(), size_t(size));
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::intl_patternForSkeleton(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2006,60 +2181,33 @@ NewUDateFormat(JSContext* cx, HandleObject dateTimeFormat)
|
|||
if (!locale)
|
||||
return nullptr;
|
||||
|
||||
// UDateFormat options with default values.
|
||||
const UChar* uTimeZone = nullptr;
|
||||
uint32_t uTimeZoneLength = 0;
|
||||
const UChar* uPattern = nullptr;
|
||||
uint32_t uPatternLength = 0;
|
||||
|
||||
// We don't need to look at calendar and numberingSystem - they can only be
|
||||
// set via the Unicode locale extension and are therefore already set on
|
||||
// locale.
|
||||
|
||||
RootedId id(cx, NameToId(cx->names().timeZone));
|
||||
bool hasP;
|
||||
if (!HasProperty(cx, internals, id, &hasP))
|
||||
if (!GetProperty(cx, internals, internals, cx->names().timeZone, &value))
|
||||
return nullptr;
|
||||
|
||||
AutoStableStringChars timeZoneChars(cx);
|
||||
if (hasP) {
|
||||
if (!GetProperty(cx, internals, internals, cx->names().timeZone, &value))
|
||||
return nullptr;
|
||||
if (!value.isUndefined()) {
|
||||
JSFlatString* flat = value.toString()->ensureFlat(cx);
|
||||
if (!flat || !timeZoneChars.initTwoByte(cx, flat))
|
||||
return nullptr;
|
||||
uTimeZone = Char16ToUChar(timeZoneChars.twoByteRange().start().get());
|
||||
if (!uTimeZone)
|
||||
return nullptr;
|
||||
uTimeZoneLength = u_strlen(uTimeZone);
|
||||
}
|
||||
}
|
||||
Rooted<JSFlatString*> timeZoneFlat(cx, value.toString()->ensureFlat(cx));
|
||||
if (!timeZoneFlat || !timeZoneChars.initTwoByte(cx, timeZoneFlat))
|
||||
return nullptr;
|
||||
|
||||
const UChar* uTimeZone = Char16ToUChar(timeZoneChars.twoByteRange().start().get());
|
||||
uint32_t uTimeZoneLength = u_strlen(uTimeZone);
|
||||
|
||||
if (!GetProperty(cx, internals, internals, cx->names().pattern, &value))
|
||||
return nullptr;
|
||||
|
||||
AutoStableStringChars patternChars(cx);
|
||||
JSFlatString* flat = value.toString()->ensureFlat(cx);
|
||||
if (!flat || !patternChars.initTwoByte(cx, flat))
|
||||
Rooted<JSFlatString*> patternFlat(cx, value.toString()->ensureFlat(cx));
|
||||
if (!patternFlat || !patternChars.initTwoByte(cx, patternFlat))
|
||||
return nullptr;
|
||||
|
||||
uPattern = Char16ToUChar(patternChars.twoByteRange().start().get());
|
||||
if (!uPattern)
|
||||
return nullptr;
|
||||
uPatternLength = u_strlen(uPattern);
|
||||
const UChar* uPattern = Char16ToUChar(patternChars.twoByteRange().start().get());
|
||||
uint32_t uPatternLength = u_strlen(uPattern);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
if (!uTimeZone) {
|
||||
// When no time zone was specified, we use ICU's default time zone.
|
||||
// The current default might be stale, because JS::ResetTimeZone()
|
||||
// doesn't immediately update ICU's default time zone. So perform an
|
||||
// update if needed.
|
||||
js::ResyncICUDefaultTimeZone();
|
||||
}
|
||||
|
||||
// If building with ICU headers before 50.1, use UDAT_IGNORE instead of
|
||||
// UDAT_PATTERN.
|
||||
UDateFormat* df =
|
||||
udat_open(UDAT_PATTERN, UDAT_PATTERN, icuLocale(locale.ptr()), uTimeZone, uTimeZoneLength,
|
||||
uPattern, uPatternLength, &status);
|
||||
|
|
|
@ -158,6 +158,40 @@ intl_DateTimeFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
|
|||
extern MOZ_MUST_USE bool
|
||||
intl_availableCalendars(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
* Return a map of the supported time zone names, derived from the IANA time
|
||||
* zone database <https://www.iana.org/time-zones>.
|
||||
*
|
||||
* There are two kinds of IANA time zone names: Zone and Link (denoted as such
|
||||
* in database source files). Zone names are the canonical, preferred name for
|
||||
* a time zone, e.g. Asia/Kolkata. Link names simply refer to target Zone names
|
||||
* for their meaning, e.g. Asia/Calcutta targets Asia/Kolkata. That a name is a
|
||||
* Link doesn't *necessarily* reflect a sense of deprecation: some Link names
|
||||
* also exist partly for convenience, e.g. UTC and GMT as Link names targeting
|
||||
* the Zone name Etc/UTC.
|
||||
*
|
||||
* Usage: timeZones = intl_availableTimeZones()
|
||||
*/
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_availableTimeZones(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
* Return the canonicalized time zone name. Canonicalization resolves link
|
||||
* names to their target time zones.
|
||||
*
|
||||
* Usage: ianaTimeZone = intl_canonicalizeTimeZone(timeZone)
|
||||
*/
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_canonicalizeTimeZone(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
* Return the default time zone name. The time zone name is not canonicalized.
|
||||
*
|
||||
* Usage: icuDefaultTimeZone = intl_defaultTimeZone()
|
||||
*/
|
||||
extern MOZ_MUST_USE bool
|
||||
intl_defaultTimeZone(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/**
|
||||
* Return a pattern in the date-time format pattern language of Unicode
|
||||
* Technical Standard 35, Unicode Locale Data Markup Language, for the
|
||||
|
|
|
@ -44,10 +44,10 @@ function toASCIIUpperCase(s) {
|
|||
// since we only care about ASCII characters here, that's OK).
|
||||
var result = "";
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
var c = s[i];
|
||||
if ("a" <= c && c <= "z")
|
||||
c = callFunction(std_String_toUpperCase, c);
|
||||
result += c;
|
||||
var c = callFunction(std_String_charCodeAt, s, i);
|
||||
result += (0x61 <= c && c <= 0x7A)
|
||||
? callFunction(std_String_fromCharCode, null, c & ~0x20)
|
||||
: s[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -622,6 +622,113 @@ function IsWellFormedCurrencyCode(currency) {
|
|||
}
|
||||
|
||||
|
||||
var timeZoneCache = {
|
||||
icuDefaultTimeZone: undefined,
|
||||
defaultTimeZone: undefined,
|
||||
timeZones: undefined,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 6.4.1 IsValidTimeZoneName ( timeZone )
|
||||
*
|
||||
* Verifies that the given string is a valid time zone name. If it is a valid
|
||||
* time zone name, its IANA time zone name is returned. Otherwise returns null.
|
||||
*
|
||||
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
|
||||
*/
|
||||
function IsValidTimeZoneName(timeZone) {
|
||||
assert(typeof timeZone === "string", "IsValidTimeZoneName");
|
||||
|
||||
var timeZones = timeZoneCache.timeZones;
|
||||
if (timeZones === undefined) {
|
||||
timeZones = intl_availableTimeZones();
|
||||
timeZoneCache.timeZones = timeZones;
|
||||
}
|
||||
|
||||
// Return |null| if time zone not found or non-IANA time zone.
|
||||
var tz = timeZones[toASCIIUpperCase(timeZone)];
|
||||
return (tz === undefined || tz in legacyICUTimeZones) ? null : tz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 6.4.2 CanonicalizeTimeZoneName ( timeZone )
|
||||
*
|
||||
* Canonicalizes the given IANA time zone name.
|
||||
*
|
||||
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
|
||||
*/
|
||||
function CanonicalizeTimeZoneName(timeZone) {
|
||||
assert(typeof timeZone === "string", "CanonicalizeTimeZoneName");
|
||||
|
||||
// Step 1. (Not applicable, the input is already a valid IANA time zone.)
|
||||
assert(timeZone !== "Etc/Unknown", "Invalid time zone");
|
||||
assert(timeZone === IsValidTimeZoneName(timeZone), "Time zone name not normalized");
|
||||
|
||||
// Step 2.
|
||||
var ianaTimeZone = intl_canonicalizeTimeZone(timeZone);
|
||||
assert(ianaTimeZone !== "Etc/Unknown", "Invalid canonical time zone");
|
||||
assert(ianaTimeZone === IsValidTimeZoneName(ianaTimeZone), "Unsupported canonical time zone");
|
||||
|
||||
// Step 3.
|
||||
if (ianaTimeZone === "Etc/UTC" || ianaTimeZone === "Etc/GMT") {
|
||||
// ICU/CLDR canonicalizes Etc/UCT to Etc/GMT, but following IANA and
|
||||
// ECMA-402 to the letter means Etc/UCT is a separate time zone.
|
||||
if (timeZone === "Etc/UCT" || timeZone === "UCT")
|
||||
ianaTimeZone = "Etc/UCT";
|
||||
else
|
||||
ianaTimeZone = "UTC";
|
||||
} else {
|
||||
// ICU/CLDR doesn't map all names to their new IANA time zone names.
|
||||
// http://bugs.icu-project.org/trac/ticket/12044
|
||||
if (timeZone in tzLinkNamesNonICU) {
|
||||
// Case 1: ICU/CLDR maps the time zone to another time zone, e.g.
|
||||
// America/Virgin is mapped to America/St_Thomas, whereas IANA maps
|
||||
// America/Virgin to America/Port_of_Spain.
|
||||
// Only perform the update when ICU supports the new time zone.
|
||||
if (IsValidTimeZoneName(tzLinkNamesNonICU[timeZone]) !== null) {
|
||||
ianaTimeZone = tzLinkNamesNonICU[timeZone];
|
||||
}
|
||||
} else if (timeZone in tzZoneNamesNonICU) {
|
||||
// Case 2: ICU/CLDR maps the time zone to its old name, e.g.
|
||||
// Asia/Kathmandu is mapped to Asia/Katmandu.
|
||||
ianaTimeZone = timeZone;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
return ianaTimeZone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 6.4.3 DefaultTimeZone ()
|
||||
*
|
||||
* Returns the IANA time zone name for the host environment's current time zone.
|
||||
*
|
||||
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
|
||||
*/
|
||||
function DefaultTimeZone() {
|
||||
const icuDefaultTimeZone = intl_defaultTimeZone();
|
||||
if (timeZoneCache.icuDefaultTimeZone === icuDefaultTimeZone)
|
||||
return timeZoneCache.defaultTimeZone;
|
||||
|
||||
// Verify that the current ICU time zone is a valid ECMA-402 time zone.
|
||||
var timeZone = IsValidTimeZoneName(icuDefaultTimeZone);
|
||||
if (timeZone === null)
|
||||
timeZone = "UTC";
|
||||
|
||||
// Canonicalize the ICU time zone, e.g. change Etc/UTC to UTC.
|
||||
var defaultTimeZone = CanonicalizeTimeZoneName(timeZone);
|
||||
|
||||
timeZoneCache.defaultTimeZone = defaultTimeZone;
|
||||
timeZoneCache.icuDefaultTimeZone = icuDefaultTimeZone;
|
||||
|
||||
return defaultTimeZone;
|
||||
}
|
||||
|
||||
|
||||
/********** Locale and Parameter Negotiation **********/
|
||||
|
||||
/**
|
||||
|
@ -2093,7 +2200,7 @@ function resolveDateTimeFormatInternals(lazyDateTimeFormatData) {
|
|||
// hour12: true / false, // optional
|
||||
// }
|
||||
//
|
||||
// timeZone: undefined / "UTC",
|
||||
// timeZone: IANA time zone name,
|
||||
//
|
||||
// formatOpt: // *second* opt computed in InitializeDateTimeFormat
|
||||
// {
|
||||
|
@ -2225,7 +2332,7 @@ function InitializeDateTimeFormat(dateTimeFormat, locales, options) {
|
|||
// localeMatcher: "lookup" / "best fit",
|
||||
// }
|
||||
//
|
||||
// timeZone: undefined / "UTC",
|
||||
// timeZone: IANA time zone name,
|
||||
//
|
||||
// formatOpt: // *second* opt computed in InitializeDateTimeFormat
|
||||
// {
|
||||
|
@ -2264,9 +2371,19 @@ function InitializeDateTimeFormat(dateTimeFormat, locales, options) {
|
|||
// Steps 15-17.
|
||||
var tz = options.timeZone;
|
||||
if (tz !== undefined) {
|
||||
tz = toASCIIUpperCase(ToString(tz));
|
||||
if (tz !== "UTC")
|
||||
// Step 15.a.
|
||||
tz = ToString(tz);
|
||||
|
||||
// Step 15.b.
|
||||
var timeZone = IsValidTimeZoneName(tz);
|
||||
if (timeZone === null)
|
||||
ThrowRangeError(JSMSG_INVALID_TIME_ZONE, tz);
|
||||
|
||||
// Step 15.c.
|
||||
tz = CanonicalizeTimeZoneName(timeZone);
|
||||
} else {
|
||||
// Step 16.
|
||||
tz = DefaultTimeZone();
|
||||
}
|
||||
lazyDateTimeFormatData.timeZone = tz;
|
||||
|
||||
|
@ -2289,7 +2406,7 @@ function InitializeDateTimeFormat(dateTimeFormat, locales, options) {
|
|||
// For some reason (ICU not exposing enough interface?) we drop the
|
||||
// requested format matcher on the floor after this. In any case, even if
|
||||
// doing so is justified, we have to do this work here in case it triggers
|
||||
// getters or similar.
|
||||
// getters or similar. (bug 852837)
|
||||
var formatMatcher =
|
||||
GetOption(options, "formatMatcher", "string", ["basic", "best fit"],
|
||||
"best fit");
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2015f
|
||||
// ICU tzdata version = 2015f
|
||||
|
||||
// Format:
|
||||
// "ZoneName": true // ICU-Name [time zone file]
|
||||
var tzZoneNamesNonICU = {
|
||||
"Africa/Asmara": true, // Africa/Asmera [backzone]
|
||||
"Africa/Timbuktu": true, // Africa/Bamako [backzone]
|
||||
"America/Argentina/Buenos_Aires": true, // America/Buenos_Aires [southamerica]
|
||||
"America/Argentina/Catamarca": true, // America/Catamarca [southamerica]
|
||||
"America/Argentina/ComodRivadavia": true, // America/Catamarca [backzone]
|
||||
"America/Argentina/Cordoba": true, // America/Cordoba [southamerica]
|
||||
"America/Argentina/Jujuy": true, // America/Jujuy [southamerica]
|
||||
"America/Argentina/Mendoza": true, // America/Mendoza [southamerica]
|
||||
"America/Atikokan": true, // America/Coral_Harbour [northamerica]
|
||||
"America/Ensenada": true, // America/Tijuana [backzone]
|
||||
"America/Indiana/Indianapolis": true, // America/Indianapolis [northamerica]
|
||||
"America/Kentucky/Louisville": true, // America/Louisville [northamerica]
|
||||
"America/Rosario": true, // America/Cordoba [backzone]
|
||||
"Asia/Chongqing": true, // Asia/Shanghai [backzone]
|
||||
"Asia/Hanoi": true, // <not present> [backzone]
|
||||
"Asia/Harbin": true, // Asia/Shanghai [backzone]
|
||||
"Asia/Ho_Chi_Minh": true, // Asia/Saigon [asia]
|
||||
"Asia/Kashgar": true, // Asia/Urumqi [backzone]
|
||||
"Asia/Kathmandu": true, // Asia/Katmandu [asia]
|
||||
"Asia/Kolkata": true, // Asia/Calcutta [asia]
|
||||
"Asia/Tel_Aviv": true, // Asia/Jerusalem [backzone]
|
||||
"Atlantic/Faroe": true, // Atlantic/Faeroe [europe]
|
||||
"Atlantic/Jan_Mayen": true, // Arctic/Longyearbyen [backzone]
|
||||
"CET": true, // <not present> [europe]
|
||||
"EET": true, // <not present> [europe]
|
||||
"EST": true, // Etc/GMT+5 [northamerica]
|
||||
"Europe/Belfast": true, // Europe/London [backzone]
|
||||
"Europe/Tiraspol": true, // Europe/Chisinau [backzone]
|
||||
"HST": true, // Etc/GMT+10 [northamerica]
|
||||
"MET": true, // <not present> [europe]
|
||||
"MST": true, // Etc/GMT+7 [northamerica]
|
||||
"Pacific/Chuuk": true, // Pacific/Truk [australasia]
|
||||
"Pacific/Pohnpei": true, // Pacific/Ponape [australasia]
|
||||
"WET": true, // <not present> [europe]
|
||||
};
|
||||
|
||||
// Format:
|
||||
// "LinkName": "Target" // ICU-Target [time zone file]
|
||||
var tzLinkNamesNonICU = {
|
||||
"Africa/Asmera": "Africa/Asmara", // Africa/Asmera [backward]
|
||||
"America/Buenos_Aires": "America/Argentina/Buenos_Aires", // America/Buenos_Aires [backward]
|
||||
"America/Catamarca": "America/Argentina/Catamarca", // America/Catamarca [backward]
|
||||
"America/Cordoba": "America/Argentina/Cordoba", // America/Cordoba [backward]
|
||||
"America/Fort_Wayne": "America/Indiana/Indianapolis", // America/Indianapolis [backward]
|
||||
"America/Indianapolis": "America/Indiana/Indianapolis", // America/Indianapolis [backward]
|
||||
"America/Jujuy": "America/Argentina/Jujuy", // America/Jujuy [backward]
|
||||
"America/Kralendijk": "America/Curacao", // America/Kralendijk [southamerica]
|
||||
"America/Louisville": "America/Kentucky/Louisville", // America/Louisville [backward]
|
||||
"America/Lower_Princes": "America/Curacao", // America/Lower_Princes [southamerica]
|
||||
"America/Marigot": "America/Port_of_Spain", // America/Marigot [southamerica]
|
||||
"America/Mendoza": "America/Argentina/Mendoza", // America/Mendoza [backward]
|
||||
"America/St_Barthelemy": "America/Port_of_Spain", // America/St_Barthelemy [southamerica]
|
||||
"America/Virgin": "America/Port_of_Spain", // America/St_Thomas [backward]
|
||||
"Antarctica/South_Pole": "Antarctica/McMurdo", // Pacific/Auckland [backward]
|
||||
"Arctic/Longyearbyen": "Europe/Oslo", // Arctic/Longyearbyen [europe]
|
||||
"Asia/Calcutta": "Asia/Kolkata", // Asia/Calcutta [backward]
|
||||
"Asia/Chungking": "Asia/Chongqing", // Asia/Shanghai [backward]
|
||||
"Asia/Katmandu": "Asia/Kathmandu", // Asia/Katmandu [backward]
|
||||
"Asia/Saigon": "Asia/Ho_Chi_Minh", // Asia/Saigon [backward]
|
||||
"Atlantic/Faeroe": "Atlantic/Faroe", // Atlantic/Faeroe [backward]
|
||||
"Europe/Bratislava": "Europe/Prague", // Europe/Bratislava [europe]
|
||||
"Europe/Busingen": "Europe/Zurich", // Europe/Busingen [europe]
|
||||
"Europe/Mariehamn": "Europe/Helsinki", // Europe/Mariehamn [europe]
|
||||
"Europe/Podgorica": "Europe/Belgrade", // Europe/Podgorica [europe]
|
||||
"Europe/San_Marino": "Europe/Rome", // Europe/San_Marino [europe]
|
||||
"Europe/Vatican": "Europe/Rome", // Europe/Vatican [europe]
|
||||
"Pacific/Ponape": "Pacific/Pohnpei", // Pacific/Ponape [backward]
|
||||
"Pacific/Truk": "Pacific/Chuuk", // Pacific/Truk [backward]
|
||||
"Pacific/Yap": "Pacific/Chuuk", // Pacific/Truk [backward]
|
||||
"US/East-Indiana": "America/Indiana/Indianapolis", // America/Indianapolis [backward]
|
||||
};
|
||||
|
||||
// Legacy ICU time zones, these are not valid IANA time zone names. We also
|
||||
// disallow the old and deprecated System V time zones.
|
||||
// http://source.icu-project.org/repos/icu/icu/trunk/source/tools/tzcode/icuzones
|
||||
var legacyICUTimeZones = {
|
||||
"ACT": true,
|
||||
"AET": true,
|
||||
"AGT": true,
|
||||
"ART": true,
|
||||
"AST": true,
|
||||
"BET": true,
|
||||
"BST": true,
|
||||
"CAT": true,
|
||||
"CNT": true,
|
||||
"CST": true,
|
||||
"CTT": true,
|
||||
"EAT": true,
|
||||
"ECT": true,
|
||||
"IET": true,
|
||||
"IST": true,
|
||||
"JST": true,
|
||||
"MIT": true,
|
||||
"NET": true,
|
||||
"NST": true,
|
||||
"PLT": true,
|
||||
"PNT": true,
|
||||
"PRT": true,
|
||||
"PST": true,
|
||||
"SST": true,
|
||||
"VST": true,
|
||||
"SystemV/AST4": true,
|
||||
"SystemV/AST4ADT": true,
|
||||
"SystemV/CST6": true,
|
||||
"SystemV/CST6CDT": true,
|
||||
"SystemV/EST5": true,
|
||||
"SystemV/EST5EDT": true,
|
||||
"SystemV/HST10": true,
|
||||
"SystemV/MST7": true,
|
||||
"SystemV/MST7MDT": true,
|
||||
"SystemV/PST8": true,
|
||||
"SystemV/PST8PDT": true,
|
||||
"SystemV/YST9": true,
|
||||
"SystemV/YST9YDT": true,
|
||||
};
|
|
@ -2,8 +2,53 @@
|
|||
* 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/. */
|
||||
|
||||
/* ES6 20121122 draft 15.14.4.4. */
|
||||
// ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4
|
||||
// 23.1.1.1 Map, steps 6-8
|
||||
function MapConstructorInit(iterable) {
|
||||
var map = this;
|
||||
|
||||
// Step 6.a.
|
||||
var adder = map.set;
|
||||
|
||||
// Step 6.b.
|
||||
if (!IsCallable(adder))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
|
||||
|
||||
// Step 6.c.
|
||||
var iterFn = iterable[std_iterator];
|
||||
if (!IsCallable(iterFn))
|
||||
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
|
||||
|
||||
var iter = callContentFunction(iterFn, iterable);
|
||||
if (!IsObject(iter))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
|
||||
|
||||
// Step 7 (not applicable).
|
||||
|
||||
// Step 8.
|
||||
while (true) {
|
||||
// Step 8.a.
|
||||
var next = callContentFunction(iter.next, iter);
|
||||
if (!IsObject(next))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
|
||||
|
||||
// Step 8.b.
|
||||
if (next.done)
|
||||
return;
|
||||
|
||||
// Step 8.c.
|
||||
var nextItem = next.value;
|
||||
|
||||
// Step 8.d.
|
||||
if (!IsObject(nextItem))
|
||||
ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "Map");
|
||||
|
||||
// Steps 8.e-j.
|
||||
callContentFunction(adder, map, nextItem[0], nextItem[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ES6 20121122 draft 15.14.4.4. */
|
||||
function MapForEach(callbackfn, thisArg = undefined) {
|
||||
/* Step 1-2. */
|
||||
var M = this;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "js/Utility.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
@ -564,73 +565,12 @@ MapObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
if (!args.get(0).isNullOrUndefined()) {
|
||||
RootedValue adderVal(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal))
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(args[0]);
|
||||
|
||||
RootedValue thisv(cx, ObjectValue(*obj));
|
||||
if (!CallSelfHostedFunction(cx, cx->names().MapConstructorInit, thisv, args2, args2.rval()))
|
||||
return false;
|
||||
|
||||
if (!IsCallable(adderVal))
|
||||
return ReportIsNotFunction(cx, adderVal);
|
||||
|
||||
bool isOriginalAdder = IsNativeFunction(adderVal, MapObject::set);
|
||||
RootedValue mapVal(cx, ObjectValue(*obj));
|
||||
FastCallGuard fig(cx, adderVal);
|
||||
InvokeArgs& args2 = fig.args();
|
||||
|
||||
ForOfIterator iter(cx);
|
||||
if (!iter.init(args[0]))
|
||||
return false;
|
||||
|
||||
RootedValue pairVal(cx);
|
||||
RootedObject pairObj(cx);
|
||||
RootedValue dummy(cx);
|
||||
Rooted<HashableValue> hkey(cx);
|
||||
ValueMap* map = obj->getData();
|
||||
while (true) {
|
||||
bool done;
|
||||
if (!iter.next(&pairVal, &done))
|
||||
return false;
|
||||
if (done)
|
||||
break;
|
||||
if (!pairVal.isObject()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INVALID_MAP_ITERABLE,
|
||||
"Map");
|
||||
return false;
|
||||
}
|
||||
|
||||
pairObj = &pairVal.toObject();
|
||||
if (!pairObj)
|
||||
return false;
|
||||
|
||||
RootedValue key(cx);
|
||||
if (!GetElement(cx, pairObj, pairObj, 0, &key))
|
||||
return false;
|
||||
|
||||
RootedValue val(cx);
|
||||
if (!GetElement(cx, pairObj, pairObj, 1, &val))
|
||||
return false;
|
||||
|
||||
if (isOriginalAdder) {
|
||||
if (!hkey.setValue(cx, key))
|
||||
return false;
|
||||
|
||||
HeapPtr<Value> rval(val);
|
||||
if (!WriteBarrierPost(cx->runtime(), obj, key) ||
|
||||
!map->put(hkey, rval))
|
||||
{
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!args2.init(2))
|
||||
return false;
|
||||
|
||||
args2[0].set(key);
|
||||
args2[1].set(val);
|
||||
|
||||
if (!fig.call(cx, adderVal, mapVal, &dummy))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
|
@ -1212,6 +1152,12 @@ SetObject::finalize(FreeOp* fop, JSObject* obj)
|
|||
fop->delete_(set);
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::isBuiltinAdd(HandleValue add, JSContext* cx)
|
||||
{
|
||||
return IsNativeFunction(add, SetObject::add);
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -1230,33 +1176,20 @@ SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
if (!args.get(0).isNullOrUndefined()) {
|
||||
RootedValue adderVal(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().add, &adderVal))
|
||||
RootedValue iterable(cx, args[0]);
|
||||
bool optimized = false;
|
||||
if (!IsOptimizableInitForSet<GlobalObject::getOrCreateSetPrototype, isBuiltinAdd>(cx, obj, iterable, &optimized))
|
||||
return false;
|
||||
|
||||
if (!IsCallable(adderVal))
|
||||
return ReportIsNotFunction(cx, adderVal);
|
||||
if (optimized) {
|
||||
RootedValue keyVal(cx);
|
||||
Rooted<HashableValue> key(cx);
|
||||
ValueSet* set = obj->getData();
|
||||
ArrayObject* array = &iterable.toObject().as<ArrayObject>();
|
||||
for (uint32_t index = 0; index < array->getDenseInitializedLength(); ++index) {
|
||||
keyVal.set(array->getDenseElement(index));
|
||||
MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE));
|
||||
|
||||
bool isOriginalAdder = IsNativeFunction(adderVal, SetObject::add);
|
||||
RootedValue setVal(cx, ObjectValue(*obj));
|
||||
FastCallGuard fig(cx, adderVal);
|
||||
InvokeArgs& args2 = fig.args();
|
||||
|
||||
RootedValue keyVal(cx);
|
||||
ForOfIterator iter(cx);
|
||||
if (!iter.init(args[0]))
|
||||
return false;
|
||||
Rooted<HashableValue> key(cx);
|
||||
RootedValue dummy(cx);
|
||||
ValueSet* set = obj->getData();
|
||||
while (true) {
|
||||
bool done;
|
||||
if (!iter.next(&keyVal, &done))
|
||||
return false;
|
||||
if (done)
|
||||
break;
|
||||
|
||||
if (isOriginalAdder) {
|
||||
if (!key.setValue(cx, keyVal))
|
||||
return false;
|
||||
if (!WriteBarrierPost(cx->runtime(), obj, keyVal) ||
|
||||
|
@ -1265,15 +1198,14 @@ SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!args2.init(1))
|
||||
return false;
|
||||
|
||||
args2[0].set(keyVal);
|
||||
|
||||
if (!fig.call(cx, adderVal, setVal, &dummy))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(args[0]);
|
||||
|
||||
RootedValue thisv(cx, ObjectValue(*obj));
|
||||
if (!CallSelfHostedFunction(cx, cx->names().SetConstructorInit, thisv, args2, args2.rval()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "jsobj.h"
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/PIC.h"
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
namespace js {
|
||||
|
@ -228,6 +230,8 @@ class SetObject : public NativeObject {
|
|||
static bool is(HandleValue v);
|
||||
static bool is(HandleObject o);
|
||||
|
||||
static bool isBuiltinAdd(HandleValue add, JSContext* cx);
|
||||
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
|
@ -266,6 +270,48 @@ class SetIteratorObject : public NativeObject
|
|||
extern bool
|
||||
InitSelfHostingCollectionIteratorFunctions(JSContext* cx, js::HandleObject obj);
|
||||
|
||||
bool IsPackedArray(JSObject* obj);
|
||||
|
||||
using SetInitGetPrototypeOp = NativeObject* (*)(JSContext*, Handle<GlobalObject*>);
|
||||
using SetInitIsBuiltinOp = bool (*)(HandleValue, JSContext*);
|
||||
|
||||
template <SetInitGetPrototypeOp getPrototypeOp, SetInitIsBuiltinOp isBuiltinOp>
|
||||
static MOZ_MUST_USE bool
|
||||
IsOptimizableInitForSet(JSContext* cx, HandleObject setObject, HandleValue iterable, bool* optimized)
|
||||
{
|
||||
if (!iterable.isObject())
|
||||
return true;
|
||||
|
||||
RootedObject array(cx, &iterable.toObject());
|
||||
if (!IsPackedArray(array))
|
||||
return true;
|
||||
|
||||
// Get the canonical prototype object.
|
||||
RootedNativeObject setProto(cx, getPrototypeOp(cx, cx->global()));
|
||||
if (!setProto)
|
||||
return false;
|
||||
|
||||
// Ensures setObject's prototype is the canonical prototype.
|
||||
if (setObject->staticPrototype() != setProto)
|
||||
return true;
|
||||
|
||||
// Look up the 'add' value on the prototype object.
|
||||
Shape* addShape = setProto->lookup(cx, cx->names().add);
|
||||
if (!addShape || !addShape->hasSlot())
|
||||
return true;
|
||||
|
||||
// Get the referred value, ensure it holds the canonical add function.
|
||||
RootedValue add(cx, setProto->getSlot(addShape->slot()));
|
||||
if (!isBuiltinOp(add, cx))
|
||||
return true;
|
||||
|
||||
ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
|
||||
if (!stubChain)
|
||||
return false;
|
||||
|
||||
return stubChain->tryOptimizeArray(cx, array.as<ArrayObject>(), optimized);
|
||||
}
|
||||
|
||||
extern JSObject*
|
||||
InitMapClass(JSContext* cx, HandleObject obj);
|
||||
|
||||
|
|
|
@ -2,8 +2,49 @@
|
|||
* 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/. */
|
||||
|
||||
/* ES6 20121122 draft 15.16.4.6. */
|
||||
// ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4
|
||||
// 23.2.1.1 Set, steps 6-8
|
||||
function SetConstructorInit(iterable) {
|
||||
var set = this;
|
||||
|
||||
// Step 6.a.
|
||||
var adder = set.add;
|
||||
|
||||
// Step 6.b.
|
||||
if (!IsCallable(adder))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
|
||||
|
||||
// Step 6.c.
|
||||
var iterFn = iterable[std_iterator];
|
||||
if (!IsCallable(iterFn))
|
||||
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
|
||||
|
||||
var iter = callContentFunction(iterFn, iterable);
|
||||
if (!IsObject(iter))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
|
||||
|
||||
// Step 7 (not applicable).
|
||||
|
||||
// Step 8.
|
||||
while (true) {
|
||||
// Step 8.a.
|
||||
var next = callContentFunction(iter.next, iter);
|
||||
if (!IsObject(next))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
|
||||
|
||||
// Step 8.b.
|
||||
if (next.done)
|
||||
return;
|
||||
|
||||
// Step 8.c.
|
||||
var nextValue = next.value;
|
||||
|
||||
// Steps 8.d-e.
|
||||
callContentFunction(adder, set, nextValue);
|
||||
}
|
||||
}
|
||||
|
||||
/* ES6 20121122 draft 15.16.4.6. */
|
||||
function SetForEach(callbackfn, thisArg = undefined) {
|
||||
/* Step 1-2. */
|
||||
var S = this;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "asmjs/WasmBinaryToExperimentalText.h"
|
||||
#include "asmjs/WasmBinaryToText.h"
|
||||
#include "asmjs/WasmJS.h"
|
||||
#include "asmjs/WasmModule.h"
|
||||
#include "asmjs/WasmSignalHandlers.h"
|
||||
#include "asmjs/WasmTextToBinary.h"
|
||||
#include "builtin/Promise.h"
|
||||
|
@ -620,6 +621,26 @@ WasmBinaryToText(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WasmExtractCode(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
MOZ_ASSERT(cx->options().wasm());
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!args.get(0).isObject() || !args.get(0).toObject().is<WasmModuleObject>()) {
|
||||
JS_ReportErrorASCII(cx, "argument is not a WebAssembly.Module");
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<WasmModuleObject*> module(cx, &args.get(0).toObject().as<WasmModuleObject>());
|
||||
RootedValue result(cx);
|
||||
if (!module->module().extractCode(cx, &result))
|
||||
return false;
|
||||
|
||||
args.rval().set(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsLazyFunction(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -3818,6 +3839,10 @@ gc::ZealModeHelpText),
|
|||
"wasmBinaryToText(bin)",
|
||||
" Translates binary encoding to text format"),
|
||||
|
||||
JS_FN_HELP("wasmExtractCode", WasmExtractCode, 1, 0,
|
||||
"wasmExtractCode(module)",
|
||||
" Extracts generated machine code from WebAssembly.Module."),
|
||||
|
||||
JS_FN_HELP("isLazyFunction", IsLazyFunction, 1, 0,
|
||||
"isLazyFunction(fun)",
|
||||
" True if fun is a lazy JSFunction."),
|
||||
|
|
|
@ -1436,6 +1436,7 @@ function TypedArraySpecies() {
|
|||
// Step 1.
|
||||
return this;
|
||||
}
|
||||
_SetCanonicalName(TypedArraySpecies, "get [Symbol.species]");
|
||||
|
||||
// ES 2017 draft June 2, 2016 22.2.3.32
|
||||
function TypedArrayToStringTag() {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* 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/. */
|
||||
|
||||
// ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4
|
||||
// 23.3.1.1 WeakMap, steps 6-8
|
||||
function WeakMapConstructorInit(iterable) {
|
||||
var map = this;
|
||||
|
||||
// Step 6.a.
|
||||
var adder = map.set;
|
||||
|
||||
// Step 6.b.
|
||||
if (!IsCallable(adder))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
|
||||
|
||||
// Step 6.c.
|
||||
var iterFn = iterable[std_iterator];
|
||||
if (!IsCallable(iterFn))
|
||||
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
|
||||
|
||||
var iter = callContentFunction(iterFn, iterable);
|
||||
if (!IsObject(iter))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
|
||||
|
||||
// Step 7 (not applicable).
|
||||
|
||||
// Step 8.
|
||||
while (true) {
|
||||
// Step 8.a.
|
||||
var next = callContentFunction(iter.next, iter);
|
||||
if (!IsObject(next))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
|
||||
|
||||
// Step 8.b.
|
||||
if (next.done)
|
||||
return;
|
||||
|
||||
// Step 8.c.
|
||||
var nextItem = next.value;
|
||||
|
||||
// Step 8.d.
|
||||
if (!IsObject(nextItem))
|
||||
ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "WeakMap");
|
||||
|
||||
// Steps 8.e-j.
|
||||
callContentFunction(adder, map, nextItem[0], nextItem[1]);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@
|
|||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "vm/Interpreter-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -300,85 +302,12 @@ WeakMap_construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
// Steps 5-6, 11.
|
||||
if (!args.get(0).isNullOrUndefined()) {
|
||||
// Steps 7a-b.
|
||||
RootedValue adderVal(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal))
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(args[0]);
|
||||
|
||||
RootedValue thisv(cx, ObjectValue(*obj));
|
||||
if (!CallSelfHostedFunction(cx, cx->names().WeakMapConstructorInit, thisv, args2, args2.rval()))
|
||||
return false;
|
||||
|
||||
// Step 7c.
|
||||
if (!IsCallable(adderVal))
|
||||
return ReportIsNotFunction(cx, adderVal);
|
||||
|
||||
bool isOriginalAdder = IsNativeFunction(adderVal, WeakMap_set);
|
||||
RootedValue mapVal(cx, ObjectValue(*obj));
|
||||
FastCallGuard fig(cx, adderVal);
|
||||
InvokeArgs& args2 = fig.args();
|
||||
|
||||
// Steps 7d-e.
|
||||
JS::ForOfIterator iter(cx);
|
||||
if (!iter.init(args[0]))
|
||||
return false;
|
||||
|
||||
RootedValue pairVal(cx);
|
||||
RootedObject pairObject(cx);
|
||||
RootedValue keyVal(cx);
|
||||
RootedObject keyObject(cx);
|
||||
RootedValue val(cx);
|
||||
RootedValue dummy(cx);
|
||||
while (true) {
|
||||
// Steps 12a-e.
|
||||
bool done;
|
||||
if (!iter.next(&pairVal, &done))
|
||||
return false;
|
||||
if (done)
|
||||
break;
|
||||
|
||||
// Step 12f.
|
||||
if (!pairVal.isObject()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INVALID_MAP_ITERABLE,
|
||||
"WeakMap");
|
||||
return false;
|
||||
}
|
||||
|
||||
pairObject = &pairVal.toObject();
|
||||
if (!pairObject)
|
||||
return false;
|
||||
|
||||
// Steps 12g-h.
|
||||
if (!GetElement(cx, pairObject, pairObject, 0, &keyVal))
|
||||
return false;
|
||||
|
||||
// Steps 12i-j.
|
||||
if (!GetElement(cx, pairObject, pairObject, 1, &val))
|
||||
return false;
|
||||
|
||||
// Steps 12k-l.
|
||||
if (isOriginalAdder) {
|
||||
if (keyVal.isPrimitive()) {
|
||||
UniqueChars bytes =
|
||||
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_NONNULL_OBJECT,
|
||||
bytes.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
keyObject = &keyVal.toObject();
|
||||
if (!SetWeakMapEntry(cx, obj, keyObject, val))
|
||||
return false;
|
||||
} else {
|
||||
if (!args2.init(2))
|
||||
return false;
|
||||
|
||||
args2[0].set(keyVal);
|
||||
args2[1].set(val);
|
||||
|
||||
if (!fig.call(cx, adderVal, mapVal, &dummy))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
|
|
|
@ -2,6 +2,48 @@
|
|||
* 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/. */
|
||||
|
||||
// ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4
|
||||
// 23.4.1.1 WeakSet, steps 6-8
|
||||
function WeakSetConstructorInit(iterable) {
|
||||
var set = this;
|
||||
|
||||
// Step 6.a.
|
||||
var adder = set.add;
|
||||
|
||||
// Step 6.b.
|
||||
if (!IsCallable(adder))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
|
||||
|
||||
// Step 6.c.
|
||||
var iterFn = iterable[std_iterator];
|
||||
if (!IsCallable(iterFn))
|
||||
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
|
||||
|
||||
var iter = callContentFunction(iterFn, iterable);
|
||||
if (!IsObject(iter))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
|
||||
|
||||
// Step 7 (not applicable).
|
||||
|
||||
// Step 8.
|
||||
while (true) {
|
||||
// Step 8.a.
|
||||
var next = callContentFunction(iter.next, iter);
|
||||
if (!IsObject(next))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
|
||||
|
||||
// Step 8.b.
|
||||
if (next.done)
|
||||
return;
|
||||
|
||||
// Step 8.c.
|
||||
var nextValue = next.value;
|
||||
|
||||
// Steps 8.d-e.
|
||||
callContentFunction(adder, set, nextValue);
|
||||
}
|
||||
}
|
||||
|
||||
// 23.4.3.1
|
||||
function WeakSet_add(value) {
|
||||
// Steps 1-3.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "jscntxt.h"
|
||||
#include "jsiter.h"
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
|
@ -74,6 +75,13 @@ WeakSetObject::create(JSContext* cx, HandleObject proto /* = nullptr */)
|
|||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
WeakSetObject::isBuiltinAdd(HandleValue add, JSContext* cx)
|
||||
{
|
||||
JSFunction* addFn;
|
||||
return IsFunctionObject(add, &addFn) && IsSelfHostedFunctionWithName(addFn, cx->names().WeakSet_add);
|
||||
}
|
||||
|
||||
bool
|
||||
WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -93,61 +101,42 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
if (!args.get(0).isNullOrUndefined()) {
|
||||
RootedObject map(cx, &obj->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
|
||||
|
||||
RootedValue adderVal(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().add, &adderVal))
|
||||
RootedValue iterable(cx, args[0]);
|
||||
bool optimized = false;
|
||||
if (!IsOptimizableInitForSet<GlobalObject::getOrCreateWeakSetPrototype, isBuiltinAdd>(cx, obj, iterable, &optimized))
|
||||
return false;
|
||||
|
||||
if (!IsCallable(adderVal))
|
||||
return ReportIsNotFunction(cx, adderVal);
|
||||
if (optimized) {
|
||||
RootedValue keyVal(cx);
|
||||
RootedObject keyObject(cx);
|
||||
RootedValue placeholder(cx, BooleanValue(true));
|
||||
RootedObject map(cx, &obj->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
|
||||
RootedArrayObject array(cx, &iterable.toObject().as<ArrayObject>());
|
||||
for (uint32_t index = 0; index < array->getDenseInitializedLength(); ++index) {
|
||||
keyVal.set(array->getDenseElement(index));
|
||||
MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE));
|
||||
|
||||
JSFunction* adder;
|
||||
bool isOriginalAdder = IsFunctionObject(adderVal, &adder) &&
|
||||
IsSelfHostedFunctionWithName(adder, cx->names().WeakSet_add);
|
||||
RootedValue setVal(cx, ObjectValue(*obj));
|
||||
FastCallGuard fig(cx, adderVal);
|
||||
InvokeArgs& args2 = fig.args();
|
||||
|
||||
JS::ForOfIterator iter(cx);
|
||||
if (!iter.init(args[0]))
|
||||
return false;
|
||||
|
||||
RootedValue keyVal(cx);
|
||||
RootedObject keyObject(cx);
|
||||
RootedValue dummy(cx);
|
||||
RootedValue placeholder(cx, BooleanValue(true));
|
||||
while (true) {
|
||||
bool done;
|
||||
if (!iter.next(&keyVal, &done))
|
||||
return false;
|
||||
if (done)
|
||||
break;
|
||||
|
||||
if (isOriginalAdder) {
|
||||
if (keyVal.isPrimitive()) {
|
||||
UniqueChars bytes =
|
||||
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_NONNULL_OBJECT,
|
||||
bytes.get());
|
||||
JSMSG_NOT_NONNULL_OBJECT, bytes.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
keyObject = &keyVal.toObject();
|
||||
if (!SetWeakMapEntry(cx, map, keyObject, placeholder))
|
||||
return false;
|
||||
} else {
|
||||
if (!args2.init(1))
|
||||
return false;
|
||||
|
||||
args2[0].set(keyVal);
|
||||
|
||||
if (!fig.call(cx, adderVal, setVal, &dummy))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
FixedInvokeArgs<1> args2(cx);
|
||||
args2[0].set(args[0]);
|
||||
|
||||
RootedValue thisv(cx, ObjectValue(*obj));
|
||||
if (!CallSelfHostedFunction(cx, cx->names().WeakSetConstructorInit, thisv, args2, args2.rval()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ class WeakSetObject : public NativeObject
|
|||
|
||||
static WeakSetObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool isBuiltinAdd(HandleValue add, JSContext* cx);
|
||||
};
|
||||
|
||||
extern JSObject*
|
||||
|
|
|
@ -40,7 +40,7 @@ import urllib2
|
|||
import urlparse
|
||||
from contextlib import closing
|
||||
from functools import partial
|
||||
from itertools import chain, ifilter, ifilterfalse, imap, tee
|
||||
from itertools import chain, ifilter, ifilterfalse, tee
|
||||
from operator import attrgetter, itemgetter
|
||||
|
||||
def readRegistryRecord(registry):
|
||||
|
@ -583,7 +583,7 @@ def updateTzdata(args):
|
|||
elif os.path.isdir(f):
|
||||
processTimeZones(TzDataDir(f), icuDir, icuTzDir, version, out)
|
||||
else:
|
||||
raise RuntimError("unknown format")
|
||||
raise RuntimeError("unknown format")
|
||||
|
||||
if tzDir is None:
|
||||
print("Downloading tzdata file...")
|
||||
|
|
|
@ -3719,28 +3719,23 @@ Parser<ParseHandler>::matchLabel(YieldHandling yieldHandling, MutableHandle<Prop
|
|||
|
||||
template <typename ParseHandler>
|
||||
Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
|
||||
: parser_(parser)
|
||||
{
|
||||
state_ = ErrorState::None;
|
||||
}
|
||||
: parser_(parser),
|
||||
state_(ErrorState::None)
|
||||
{}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::PossibleError::setPending(ParseReportKind kind, unsigned errorNumber,
|
||||
bool strict)
|
||||
void
|
||||
Parser<ParseHandler>::PossibleError::setPending(Node pn, unsigned errorNumber)
|
||||
{
|
||||
// Don't overwrite a previously recorded error.
|
||||
if (hasError())
|
||||
return false;
|
||||
return;
|
||||
|
||||
// If we report an error later, we'll do it from the position where we set
|
||||
// the state to pending.
|
||||
offset_ = parser_.pos().begin;
|
||||
reportKind_ = kind;
|
||||
strict_ = strict;
|
||||
offset_ = (pn ? parser_.handler.getPosition(pn) : parser_.pos()).begin;
|
||||
errorNumber_ = errorNumber;
|
||||
state_ = ErrorState::Pending;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -3761,27 +3756,25 @@ template <typename ParseHandler>
|
|||
bool
|
||||
Parser<ParseHandler>::PossibleError::checkForExprErrors()
|
||||
{
|
||||
bool err = hasError();
|
||||
if (err)
|
||||
parser_.reportWithOffset(reportKind_, strict_, offset_, errorNumber_);
|
||||
return !err;
|
||||
if (hasError()) {
|
||||
parser_.reportWithOffset(ParseError, false, offset_, errorNumber_);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::PossibleError::transferErrorTo(PossibleError* other)
|
||||
{
|
||||
if (other) {
|
||||
MOZ_ASSERT(this != other);
|
||||
MOZ_ASSERT(!other->hasError());
|
||||
MOZ_ASSERT(other);
|
||||
MOZ_ASSERT(this != other);
|
||||
MOZ_ASSERT(&parser_ == &other->parser_,
|
||||
"Can't transfer fields to an instance which belongs to a different parser");
|
||||
|
||||
// We should never allow fields to be copied between instances
|
||||
// that point to different underlying parsers.
|
||||
MOZ_ASSERT(&parser_ == &other->parser_);
|
||||
if (hasError() && !other->hasError()) {
|
||||
other->offset_ = offset_;
|
||||
other->reportKind_ = reportKind_;
|
||||
other->errorNumber_ = errorNumber_;
|
||||
other->strict_ = strict_;
|
||||
other->state_ = state_;
|
||||
}
|
||||
}
|
||||
|
@ -3849,7 +3842,8 @@ Parser<FullParseHandler>::checkDestructuringName(ParseNode* expr, Maybe<Declarat
|
|||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkDestructuringPattern(ParseNode* pattern,
|
||||
Maybe<DeclarationKind> maybeDecl);
|
||||
Maybe<DeclarationKind> maybeDecl,
|
||||
PossibleError* possibleError /* = nullptr */);
|
||||
|
||||
template <>
|
||||
bool
|
||||
|
@ -3961,22 +3955,31 @@ Parser<FullParseHandler>::checkDestructuringArray(ParseNode* arrayPattern,
|
|||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkDestructuringPattern(ParseNode* pattern,
|
||||
Maybe<DeclarationKind> maybeDecl)
|
||||
Maybe<DeclarationKind> maybeDecl,
|
||||
PossibleError* possibleError /* = nullptr */)
|
||||
{
|
||||
if (pattern->isKind(PNK_ARRAYCOMP)) {
|
||||
report(ParseError, false, pattern, JSMSG_ARRAY_COMP_LEFTSIDE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pattern->isKind(PNK_ARRAY))
|
||||
return checkDestructuringArray(pattern, maybeDecl);
|
||||
return checkDestructuringObject(pattern, maybeDecl);
|
||||
bool isDestructuring = pattern->isKind(PNK_ARRAY)
|
||||
? checkDestructuringArray(pattern, maybeDecl)
|
||||
: checkDestructuringObject(pattern, maybeDecl);
|
||||
|
||||
// Resolve asap instead of checking since we already know that we are
|
||||
// destructuring.
|
||||
if (isDestructuring && possibleError)
|
||||
possibleError->setResolved();
|
||||
|
||||
return isDestructuring;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::checkDestructuringPattern(Node pattern,
|
||||
Maybe<DeclarationKind> maybeDecl)
|
||||
Maybe<DeclarationKind> maybeDecl,
|
||||
PossibleError* possibleError /* = nullptr */)
|
||||
{
|
||||
return abortIfSyntaxParser();
|
||||
}
|
||||
|
@ -3987,21 +3990,20 @@ Parser<ParseHandler>::destructuringDeclaration(DeclarationKind kind, YieldHandli
|
|||
TokenKind tt)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
|
||||
MOZ_ASSERT(tt == TOK_LB || tt == TOK_LC);
|
||||
|
||||
pc->inDestructuringDecl = Some(kind);
|
||||
PossibleError possibleError(*this);
|
||||
Node pn = primaryExpr(yieldHandling, TripledotProhibited,
|
||||
&possibleError, tt);
|
||||
Node pattern;
|
||||
{
|
||||
pc->inDestructuringDecl = Some(kind);
|
||||
pattern = primaryExpr(yieldHandling, TripledotProhibited, tt, &possibleError);
|
||||
pc->inDestructuringDecl = Nothing();
|
||||
}
|
||||
|
||||
// Resolve asap instead of checking since we already know that we are
|
||||
// destructuring.
|
||||
possibleError.setResolved();
|
||||
pc->inDestructuringDecl = Nothing();
|
||||
if (!pn)
|
||||
if (!pattern || !checkDestructuringPattern(pattern, Some(kind), &possibleError))
|
||||
return null();
|
||||
if (!checkDestructuringPattern(pn, Some(kind)))
|
||||
return null();
|
||||
return pn;
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
@ -4061,19 +4063,7 @@ Parser<ParseHandler>::declarationPattern(Node decl, DeclarationKind declKind, To
|
|||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB) ||
|
||||
tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
||||
Node pattern;
|
||||
{
|
||||
pc->inDestructuringDecl = Some(declKind);
|
||||
|
||||
PossibleError possibleError(*this);
|
||||
pattern = primaryExpr(yieldHandling, TripledotProhibited,
|
||||
&possibleError, tt);
|
||||
|
||||
// Resolve asap instead of checking since we already know that we are
|
||||
// destructuring.
|
||||
possibleError.setResolved();
|
||||
pc->inDestructuringDecl = Nothing();
|
||||
}
|
||||
Node pattern = destructuringDeclaration(declKind, yieldHandling, tt);
|
||||
if (!pattern)
|
||||
return null();
|
||||
|
||||
|
@ -4095,9 +4085,6 @@ Parser<ParseHandler>::declarationPattern(Node decl, DeclarationKind declKind, To
|
|||
}
|
||||
|
||||
if (*forHeadKind != PNK_FORHEAD) {
|
||||
if (!checkDestructuringPattern(pattern, Some(declKind)))
|
||||
return null();
|
||||
|
||||
*forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling);
|
||||
if (!*forInOrOfExpression)
|
||||
return null();
|
||||
|
@ -4106,9 +4093,6 @@ Parser<ParseHandler>::declarationPattern(Node decl, DeclarationKind declKind, To
|
|||
}
|
||||
}
|
||||
|
||||
if (!checkDestructuringPattern(pattern, Some(declKind)))
|
||||
return null();
|
||||
|
||||
TokenKind token;
|
||||
if (!tokenStream.getToken(&token, TokenStream::None))
|
||||
return null();
|
||||
|
@ -4968,7 +4952,8 @@ typename ParseHandler::Node
|
|||
Parser<ParseHandler>::expressionStatement(YieldHandling yieldHandling, InvokedPrediction invoked)
|
||||
{
|
||||
tokenStream.ungetToken();
|
||||
Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited, invoked);
|
||||
Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited,
|
||||
/* possibleError = */ nullptr, invoked);
|
||||
if (!pnexpr)
|
||||
return null();
|
||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
||||
|
@ -5122,15 +5107,8 @@ template <class ParseHandler>
|
|||
bool
|
||||
Parser<ParseHandler>::validateForInOrOfLHSExpression(Node target, PossibleError* possibleError)
|
||||
{
|
||||
if (handler.isUnparenthesizedDestructuringPattern(target)) {
|
||||
bool isDestructuring = checkDestructuringPattern(target);
|
||||
// Here we've successfully distinguished between destructuring and an
|
||||
// object literal. In the case where "CoverInitializedName" syntax was
|
||||
// used there will be a pending error that needs clearing.
|
||||
if (isDestructuring)
|
||||
possibleError->setResolved();
|
||||
return isDestructuring;
|
||||
}
|
||||
if (handler.isUnparenthesizedDestructuringPattern(target))
|
||||
return checkDestructuringPattern(target, Nothing(), possibleError);
|
||||
|
||||
// All other permitted targets are simple.
|
||||
if (!reportIfNotValidSimpleAssignmentTarget(target, ForInOrOfTarget))
|
||||
|
@ -6347,7 +6325,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
|||
if (hasHeritage) {
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
classHeritage = memberExpr(yieldHandling, TripledotProhibited, tt, true);
|
||||
classHeritage = memberExpr(yieldHandling, TripledotProhibited, tt);
|
||||
if (!classHeritage)
|
||||
return null();
|
||||
}
|
||||
|
@ -6946,8 +6924,8 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked)
|
||||
PossibleError* possibleError /* = nullptr */,
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
|
||||
possibleError, invoked);
|
||||
|
@ -7001,19 +6979,14 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
|
|||
if (!pn)
|
||||
return null();
|
||||
|
||||
// If we find an error here we should report it immedately instead of
|
||||
// passing it back out of the function.
|
||||
if (possibleErrorInner.hasError()) {
|
||||
|
||||
// We begin by checking for an outer pending error since it would
|
||||
// have occurred first.
|
||||
if (possibleError && !possibleError->checkForExprErrors())
|
||||
if (!possibleError) {
|
||||
// Report any pending expression error.
|
||||
if (!possibleErrorInner.checkForExprErrors())
|
||||
return null();
|
||||
|
||||
// Go ahead and report the inner error.
|
||||
possibleErrorInner.checkForExprErrors();
|
||||
return null();
|
||||
} else {
|
||||
possibleErrorInner.transferErrorTo(possibleError);
|
||||
}
|
||||
|
||||
handler.addList(seq, pn);
|
||||
|
||||
if (!tokenStream.matchToken(&matched, TOK_COMMA))
|
||||
|
@ -7024,19 +6997,6 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
|
|||
return seq;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
InvokedPrediction invoked)
|
||||
{
|
||||
PossibleError possibleError(*this);
|
||||
Node pn = expr(inHandling, yieldHandling, tripledotHandling, &possibleError, invoked);
|
||||
if (!pn || !possibleError.checkForExprErrors())
|
||||
return null();
|
||||
return pn;
|
||||
}
|
||||
|
||||
static const JSOp ParseNodeKindToJSOp[] = {
|
||||
JSOP_OR,
|
||||
JSOP_AND,
|
||||
|
@ -7126,7 +7086,7 @@ MOZ_ALWAYS_INLINE typename ParseHandler::Node
|
|||
Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked)
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
// Shift-reduce parser for the binary operator part of the JS expression
|
||||
// syntax.
|
||||
|
@ -7150,7 +7110,8 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
|
|||
|
||||
ParseNodeKind pnk;
|
||||
if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) {
|
||||
// Destructuring defaults are an error in this context
|
||||
// We're definitely not in a destructuring context, so report any
|
||||
// pending expression error now.
|
||||
if (possibleError && !possibleError->checkForExprErrors())
|
||||
return null();
|
||||
// Report an error for unary expressions on the LHS of **.
|
||||
|
@ -7201,22 +7162,20 @@ MOZ_ALWAYS_INLINE typename ParseHandler::Node
|
|||
Parser<ParseHandler>::condExpr1(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked)
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
Node condition = orExpr1(inHandling, yieldHandling, tripledotHandling, possibleError, invoked);
|
||||
|
||||
if (!condition || !tokenStream.isCurrentTokenType(TOK_HOOK))
|
||||
return condition;
|
||||
|
||||
Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
|
||||
nullptr /* possibleError */);
|
||||
Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
if (!thenExpr)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
|
||||
|
||||
Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited,
|
||||
nullptr /* possibleError */);
|
||||
Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
|
||||
if (!elseExpr)
|
||||
return null();
|
||||
|
||||
|
@ -7242,13 +7201,7 @@ Parser<ParseHandler>::checkAndMarkAsAssignmentLhs(Node target, AssignmentFlavor
|
|||
return false;
|
||||
}
|
||||
|
||||
bool isDestructuring = checkDestructuringPattern(target);
|
||||
// Here we've successfully distinguished between destructuring and
|
||||
// an object literal. In the case where "CoverInitializedName"
|
||||
// syntax was used there will be a pending error that needs clearing.
|
||||
if (possibleError && isDestructuring)
|
||||
possibleError->setResolved();
|
||||
return isDestructuring;
|
||||
return checkDestructuringPattern(target, Nothing(), possibleError);
|
||||
}
|
||||
|
||||
// All other permitted targets are simple.
|
||||
|
@ -7296,8 +7249,8 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked)
|
||||
PossibleError* possibleError /* = nullptr */,
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
|
@ -7356,9 +7309,8 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
|||
|
||||
PossibleError possibleErrorInner(*this);
|
||||
Node lhs = condExpr1(inHandling, yieldHandling, tripledotHandling, &possibleErrorInner, invoked);
|
||||
if (!lhs) {
|
||||
if (!lhs)
|
||||
return null();
|
||||
}
|
||||
|
||||
ParseNodeKind kind;
|
||||
JSOp op;
|
||||
|
@ -7462,7 +7414,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
|||
Node rhs;
|
||||
{
|
||||
AutoClearInDestructuringDecl autoClear(pc);
|
||||
rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited, possibleError);
|
||||
rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited);
|
||||
if (!rhs)
|
||||
return null();
|
||||
}
|
||||
|
@ -7470,20 +7422,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
|||
return handler.newAssignment(kind, lhs, rhs, op);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
InvokedPrediction invoked)
|
||||
{
|
||||
PossibleError possibleError(*this);
|
||||
Node expr = assignExpr(inHandling, yieldHandling, tripledotHandling, &possibleError, invoked);
|
||||
if (!expr || !possibleError.checkForExprErrors())
|
||||
return null();
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::isValidSimpleAssignmentTarget(Node node,
|
||||
|
@ -7606,9 +7544,8 @@ typename ParseHandler::Node
|
|||
Parser<ParseHandler>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op,
|
||||
uint32_t begin)
|
||||
{
|
||||
PossibleError possibleError(*this);
|
||||
Node kid = unaryExpr(yieldHandling, TripledotProhibited, &possibleError);
|
||||
if (!kid || !possibleError.checkForExprErrors())
|
||||
Node kid = unaryExpr(yieldHandling, TripledotProhibited);
|
||||
if (!kid)
|
||||
return null();
|
||||
return handler.newUnary(kind, op, begin, kid);
|
||||
}
|
||||
|
@ -7616,7 +7553,8 @@ Parser<ParseHandler>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kin
|
|||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError, InvokedPrediction invoked)
|
||||
PossibleError* possibleError /* = nullptr */,
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
|
@ -7648,7 +7586,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
|
|||
// // Evaluates expression, triggering a runtime ReferenceError for
|
||||
// // the undefined name.
|
||||
// typeof (1, nonExistentName);
|
||||
Node kid = unaryExpr(yieldHandling, TripledotProhibited, nullptr /* possibleError */);
|
||||
Node kid = unaryExpr(yieldHandling, TripledotProhibited);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
|
@ -7661,8 +7599,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
|
|||
TokenKind tt2;
|
||||
if (!tokenStream.getToken(&tt2, TokenStream::Operand))
|
||||
return null();
|
||||
Node pn2 = memberExpr(yieldHandling, TripledotProhibited, nullptr /* possibleError */,
|
||||
tt2, true);
|
||||
Node pn2 = memberExpr(yieldHandling, TripledotProhibited, tt2);
|
||||
if (!pn2)
|
||||
return null();
|
||||
AssignmentFlavor flavor = (tt == TOK_INC) ? IncrementAssignment : DecrementAssignment;
|
||||
|
@ -7674,7 +7611,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
|
|||
}
|
||||
|
||||
case TOK_DELETE: {
|
||||
Node expr = unaryExpr(yieldHandling, TripledotProhibited, nullptr /* possibleError */);
|
||||
Node expr = unaryExpr(yieldHandling, TripledotProhibited);
|
||||
if (!expr)
|
||||
return null();
|
||||
|
||||
|
@ -7690,8 +7627,8 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
|
|||
}
|
||||
|
||||
default: {
|
||||
Node pn = memberExpr(yieldHandling, tripledotHandling, possibleError, tt,
|
||||
/* allowCallSyntax = */ true, invoked);
|
||||
Node pn = memberExpr(yieldHandling, tripledotHandling, tt, /* allowCallSyntax = */ true,
|
||||
possibleError, invoked);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
|
@ -8103,8 +8040,9 @@ Parser<ParseHandler>::checkAndMarkSuperScope()
|
|||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError, TokenKind tt,
|
||||
bool allowCallSyntax, InvokedPrediction invoked)
|
||||
TokenKind tt, bool allowCallSyntax /* = true */,
|
||||
PossibleError* possibleError /* = nullptr */,
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
|
||||
|
||||
|
@ -8128,8 +8066,9 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
|
||||
// Gotten by tryNewTarget
|
||||
tt = tokenStream.currentToken().type;
|
||||
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited,
|
||||
nullptr /* possibleError */, tt, false, PredictInvoked);
|
||||
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt,
|
||||
/* allowCallSyntax = */ false,
|
||||
/* possibleError = */ nullptr, PredictInvoked);
|
||||
if (!ctorExpr)
|
||||
return null();
|
||||
|
||||
|
@ -8154,7 +8093,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
if (!lhs)
|
||||
return null();
|
||||
} else {
|
||||
lhs = primaryExpr(yieldHandling, tripledotHandling, possibleError, tt, invoked);
|
||||
lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError, invoked);
|
||||
if (!lhs)
|
||||
return null();
|
||||
}
|
||||
|
@ -8185,7 +8124,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
return null();
|
||||
}
|
||||
} else if (tt == TOK_LB) {
|
||||
Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited, nullptr /* possibleError */);
|
||||
Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
if (!propExpr)
|
||||
return null();
|
||||
|
||||
|
@ -8315,19 +8254,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
return lhs;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
|
||||
bool allowCallSyntax, InvokedPrediction invoked)
|
||||
{
|
||||
PossibleError possibleError(*this);
|
||||
Node pn = memberExpr(yieldHandling, tripledotHandling, &possibleError, tt,
|
||||
allowCallSyntax, invoked);
|
||||
if (!pn || !possibleError.checkForExprErrors())
|
||||
return null();
|
||||
return pn;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::newName(PropertyName* name)
|
||||
|
@ -8507,7 +8433,7 @@ Parser<ParseHandler>::newRegExp()
|
|||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling)
|
||||
Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
|
||||
|
||||
|
@ -8554,13 +8480,15 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling)
|
|||
} else if (tt == TOK_TRIPLEDOT) {
|
||||
tokenStream.consumeKnownToken(TOK_TRIPLEDOT, TokenStream::Operand);
|
||||
uint32_t begin = pos().begin;
|
||||
Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
|
||||
possibleError);
|
||||
if (!inner)
|
||||
return null();
|
||||
if (!handler.addSpreadElement(literal, begin, inner))
|
||||
return null();
|
||||
} else {
|
||||
Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
|
||||
possibleError);
|
||||
if (!element)
|
||||
return null();
|
||||
if (foldConstants && !FoldConstants(context, &element, this))
|
||||
|
@ -8814,7 +8742,8 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
|||
return null();
|
||||
|
||||
if (propType == PropertyType::Normal) {
|
||||
Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
|
||||
possibleError);
|
||||
if (!propExpr)
|
||||
return null();
|
||||
|
||||
|
@ -8823,8 +8752,16 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
|||
|
||||
if (propAtom == context->names().proto) {
|
||||
if (seenPrototypeMutation) {
|
||||
report(ParseError, false, propName, JSMSG_DUPLICATE_PROPERTY, "__proto__");
|
||||
return null();
|
||||
// Directly report the error when we're not in a
|
||||
// destructuring context.
|
||||
if (!possibleError) {
|
||||
report(ParseError, false, propName, JSMSG_DUPLICATE_PROTO_PROPERTY);
|
||||
return null();
|
||||
}
|
||||
|
||||
// Otherwise delay error reporting until we've determined
|
||||
// whether or not we're destructuring.
|
||||
possibleError->setPending(propName, JSMSG_DUPLICATE_PROTO_PROPERTY);
|
||||
}
|
||||
seenPrototypeMutation = true;
|
||||
|
||||
|
@ -8909,11 +8846,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
|||
// Here we set a pending error so that later in the parse, once we've
|
||||
// determined whether or not we're destructuring, the error can be
|
||||
// reported or ignored appropriately.
|
||||
if (!possibleError->setPending(ParseError, JSMSG_COLON_AFTER_ID, false)) {
|
||||
// Report any previously pending error.
|
||||
possibleError->checkForExprErrors();
|
||||
return null();
|
||||
}
|
||||
possibleError->setPending(null(), JSMSG_COLON_AFTER_ID);
|
||||
}
|
||||
|
||||
Node rhs;
|
||||
|
@ -9033,8 +8966,8 @@ Parser<ParseHandler>::tryNewTarget(Node &newTarget)
|
|||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError, TokenKind tt,
|
||||
InvokedPrediction invoked)
|
||||
TokenKind tt, PossibleError* possibleError,
|
||||
InvokedPrediction invoked /* = PredictUninvoked */)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
|
@ -9047,7 +8980,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
return classDefinition(yieldHandling, ClassExpression, NameRequired);
|
||||
|
||||
case TOK_LB:
|
||||
return arrayInitializer(yieldHandling);
|
||||
return arrayInitializer(yieldHandling, possibleError);
|
||||
|
||||
case TOK_LC:
|
||||
return objectLiteral(yieldHandling, possibleError);
|
||||
|
@ -9082,6 +9015,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
return generatorComprehension(begin);
|
||||
}
|
||||
|
||||
// Pass |possibleError| to support destructuring in arrow parameters.
|
||||
Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed, possibleError);
|
||||
if (!expr)
|
||||
return null();
|
||||
|
@ -9193,21 +9127,12 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError)
|
||||
PossibleError* possibleError /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
|
||||
return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
|
||||
return expr(inHandling, yieldHandling, tripledotHandling, PredictInvoked);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::addTelemetry(JSCompartment::DeprecatedLanguageExtension e)
|
||||
|
|
|
@ -722,6 +722,8 @@ template <typename ParseHandler>
|
|||
class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
||||
{
|
||||
private:
|
||||
using Node = typename ParseHandler::Node;
|
||||
|
||||
/*
|
||||
* A class for temporarily stashing errors while parsing continues.
|
||||
*
|
||||
|
@ -739,12 +741,12 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
*
|
||||
* Ex:
|
||||
* PossibleError possibleError(*this);
|
||||
* possibleError.setPending(ParseError, JSMSG_BAD_PROP_ID, false);
|
||||
* possibleError.setPending(pn, JSMSG_BAD_PROP_ID);
|
||||
* // A JSMSG_BAD_PROP_ID ParseError is reported, returns false.
|
||||
* possibleError.checkForExprErrors();
|
||||
*
|
||||
* PossibleError possibleError(*this);
|
||||
* possibleError.setPending(ParseError, JSMSG_BAD_PROP_ID, false);
|
||||
* possibleError.setPending(pn, JSMSG_BAD_PROP_ID);
|
||||
* possibleError.setResolved();
|
||||
* // Returns true, no error is reported.
|
||||
* possibleError.checkForExprErrors();
|
||||
|
@ -756,22 +758,21 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
class MOZ_STACK_CLASS PossibleError
|
||||
{
|
||||
protected:
|
||||
Parser<ParseHandler>& parser_;
|
||||
|
||||
enum ErrorState { None, Pending };
|
||||
ErrorState state_;
|
||||
|
||||
// Error reporting fields.
|
||||
uint32_t offset_;
|
||||
unsigned errorNumber_;
|
||||
ParseReportKind reportKind_;
|
||||
Parser<ParseHandler>& parser_;
|
||||
bool strict_;
|
||||
|
||||
public:
|
||||
explicit PossibleError(Parser<ParseHandler>& parser);
|
||||
|
||||
// Set a pending error. Only a single error may be set per instance.
|
||||
// Returns true on success or false on failure.
|
||||
bool setPending(ParseReportKind kind, unsigned errorNumber, bool strict);
|
||||
void setPending(Node pn, unsigned errorNumber);
|
||||
|
||||
// Resolve any pending error.
|
||||
void setResolved();
|
||||
|
@ -834,8 +835,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
|
||||
bool isUnexpectedEOF_:1;
|
||||
|
||||
typedef typename ParseHandler::Node Node;
|
||||
|
||||
public:
|
||||
/* State specific to the kind of parse being performed. */
|
||||
ParseHandler handler;
|
||||
|
@ -1122,18 +1121,10 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Node* forInOrOfExpression);
|
||||
|
||||
Node expr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node expr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node assignExprWithoutYield(YieldHandling yieldHandling, unsigned err);
|
||||
Node yieldExpression(InHandling inHandling);
|
||||
|
@ -1146,21 +1137,17 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
PossibleError* possibleError,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node unaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError,
|
||||
PossibleError* possibleError = nullptr,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError, TokenKind tt,
|
||||
bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked);
|
||||
Node memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
|
||||
bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked);
|
||||
TokenKind tt, bool allowCallSyntax = true,
|
||||
PossibleError* possibleError = nullptr,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError, TokenKind tt,
|
||||
TokenKind tt, PossibleError* possibleError,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling,
|
||||
PossibleError* possibleError);
|
||||
Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
|
||||
TripledotHandling tripledotHandling);
|
||||
TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr);
|
||||
|
||||
bool tryNewTarget(Node& newTarget);
|
||||
bool checkAndMarkSuperScope();
|
||||
|
@ -1323,14 +1310,14 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Node propertyName(YieldHandling yieldHandling, Node propList,
|
||||
PropertyType* propType, MutableHandleAtom propAtom);
|
||||
Node computedPropertyName(YieldHandling yieldHandling, Node literal);
|
||||
Node arrayInitializer(YieldHandling yieldHandling);
|
||||
Node arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
Node newRegExp();
|
||||
|
||||
Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
|
||||
// Top-level entrypoint into destructuring pattern checking/name-analyzing.
|
||||
bool checkDestructuringPattern(Node pattern,
|
||||
mozilla::Maybe<DeclarationKind> maybeDecl = mozilla::Nothing());
|
||||
bool checkDestructuringPattern(Node pattern, mozilla::Maybe<DeclarationKind> maybeDecl,
|
||||
PossibleError* possibleError = nullptr);
|
||||
|
||||
// Recursive methods for checking/name-analyzing subcomponents of a
|
||||
// destructuring pattern. The array/object methods *must* be passed arrays
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// |jit-test| test-also-wasm-baseline
|
||||
load(libdir + "wasm.js");
|
||||
|
||||
var module = new WebAssembly.Module(wasmTextToBinary(`(module (func (nop)))`));
|
||||
var exp = wasmExtractCode(module);
|
||||
assertEq(exp.code instanceof Uint8Array, true);
|
||||
assertEq(Array.isArray(exp.segments), true);
|
||||
var funcs = exp.segments.filter(s => s.kind === 0);
|
||||
assertEq(funcs.length, 1);
|
||||
assertEq(funcs[0].funcDefIndex, 0);
|
||||
assertEq(funcs[0].begin >= 0, true);
|
||||
assertEq(funcs[0].begin <= funcs[0].funcBodyBegin, true);
|
||||
assertEq(funcs[0].funcBodyBegin < funcs[0].funcBodyEnd, true);
|
||||
assertEq(funcs[0].funcBodyEnd <= funcs[0].end, true);
|
||||
assertEq(funcs[0].end <= exp.code.length, true);
|
|
@ -245,6 +245,7 @@ MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export nam
|
|||
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label")
|
||||
MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal")
|
||||
MSG_DEF(JSMSG_DUPLICATE_PROTO_PROPERTY, 0, JSEXN_SYNTAXERR, "property name __proto__ appears more than once in object literal")
|
||||
MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?")
|
||||
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?")
|
||||
MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level of a module")
|
||||
|
|
|
@ -55,7 +55,7 @@ virtual JSContext* createContext() override {
|
|||
// OOM. (Actually, this only happens with nursery zeal, because normally
|
||||
// the nursery will start out with only a single chunk before triggering a
|
||||
// major GC.)
|
||||
JSContext* cx = JS_NewContext(768 * 1024, 128 * 1024);
|
||||
JSContext* cx = JS_NewContext(1024 * 1024, 128 * 1024);
|
||||
if (!cx)
|
||||
return nullptr;
|
||||
setNativeStackQuota(cx);
|
||||
|
|
|
@ -1578,14 +1578,20 @@ DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res)
|
|||
return true;
|
||||
|
||||
/* Don't handle getters, setters or calls from fun.call/fun.apply. */
|
||||
if (JSOp(*current) != JSOP_CALL || static_cast<unsigned>(formalIndex) >= GET_ARGC(current))
|
||||
JSOp op = JSOp(*current);
|
||||
if (op != JSOP_CALL && op != JSOP_NEW)
|
||||
return true;
|
||||
|
||||
if (static_cast<unsigned>(formalIndex) >= GET_ARGC(current))
|
||||
return true;
|
||||
|
||||
BytecodeParser parser(cx, script);
|
||||
if (!parser.parse())
|
||||
return false;
|
||||
|
||||
int formalStackIndex = parser.stackDepthAtPC(current) - GET_ARGC(current) + formalIndex;
|
||||
bool pushedNewTarget = op == JSOP_NEW;
|
||||
int formalStackIndex = parser.stackDepthAtPC(current) - GET_ARGC(current) - pushedNewTarget +
|
||||
formalIndex;
|
||||
MOZ_ASSERT(formalStackIndex >= 0);
|
||||
if (uint32_t(formalStackIndex) >= parser.stackDepthAtPC(current))
|
||||
return true;
|
||||
|
|
|
@ -753,6 +753,7 @@ selfhosted.inputs = [
|
|||
'builtin/Generator.js',
|
||||
'builtin/Intl.js',
|
||||
'builtin/IntlData.js',
|
||||
'builtin/IntlTzData.js',
|
||||
'builtin/Iterator.js',
|
||||
'builtin/Map.js',
|
||||
'builtin/Module.js',
|
||||
|
@ -767,6 +768,7 @@ selfhosted.inputs = [
|
|||
'builtin/Sorting.js',
|
||||
'builtin/TypedArray.js',
|
||||
'builtin/TypedObject.js',
|
||||
'builtin/WeakMap.js',
|
||||
'builtin/WeakSet.js'
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
const defaultLocale = "en-US";
|
||||
const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0);
|
||||
const defaultOptions = {
|
||||
year: "numeric", month: "numeric", day: "numeric",
|
||||
hour: "numeric", minute: "numeric", second: "numeric",
|
||||
};
|
||||
const longFormatOptions = Object.assign({}, defaultOptions, {
|
||||
month: "long"
|
||||
});
|
||||
const tzNameFormatOptions = Object.assign({}, defaultOptions, {
|
||||
timeZoneName: "short"
|
||||
});
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
x => x.toUpperCase(),
|
||||
x => x.toLowerCase(),
|
||||
];
|
||||
|
||||
const tests = [
|
||||
{
|
||||
timeZone: "UTC",
|
||||
result: "12/6/2012, 12:00:00 PM",
|
||||
},
|
||||
{
|
||||
timeZone: "America/Los_Angeles",
|
||||
result: "12/6/2012, 4:00:00 AM",
|
||||
},
|
||||
{
|
||||
timeZone: "America/New_York",
|
||||
options: tzNameFormatOptions,
|
||||
result: "12/6/2012, 7:00:00 AM EST",
|
||||
},
|
||||
{
|
||||
timeZone: "America/Caracas",
|
||||
result: "12/6/2012, 7:30:00 AM",
|
||||
},
|
||||
{
|
||||
timeZone: "Europe/London",
|
||||
result: "12/6/2012, 12:00:00 PM",
|
||||
},
|
||||
{
|
||||
timeZone: "Africa/Casablanca",
|
||||
locale: "ar-MA-u-ca-islamicc", options: longFormatOptions,
|
||||
result: "22 محرم، 1434 12:00:00",
|
||||
},
|
||||
{
|
||||
timeZone: "Europe/Berlin",
|
||||
locale: "de-DE", options: tzNameFormatOptions,
|
||||
result: "6.12.2012, 13:00:00 MEZ",
|
||||
},
|
||||
{
|
||||
timeZone: "Asia/Kathmandu",
|
||||
result: "12/6/2012, 5:45:00 PM",
|
||||
},
|
||||
{
|
||||
timeZone: "Asia/Bangkok",
|
||||
locale: "th-th-u-nu-thai", options: longFormatOptions,
|
||||
result: "๖ ธันวาคม ๒๕๕๕ ๑๙:๐๐:๐๐",
|
||||
},
|
||||
{
|
||||
timeZone: "Asia/Tokyo",
|
||||
locale: "ja-JP", options: longFormatOptions,
|
||||
result: "2012年12月6日 21:00:00",
|
||||
},
|
||||
{
|
||||
timeZone: "Australia/Lord_Howe",
|
||||
result: "12/6/2012, 11:00:00 PM",
|
||||
},
|
||||
{
|
||||
timeZone: "Australia/Lord_Howe",
|
||||
date: Date.UTC(2012, 7-1, 6, 12, 0, 0),
|
||||
result: "7/6/2012, 10:30:00 PM",
|
||||
},
|
||||
{
|
||||
timeZone: "Pacific/Kiritimati",
|
||||
date: Date.UTC(1978, 12-1, 6, 12, 0, 0),
|
||||
result: "12/6/1978, 1:20:00 AM",
|
||||
},
|
||||
{
|
||||
timeZone: "Africa/Monrovia",
|
||||
date: Date.UTC(1971, 12-1, 6, 12, 0, 0),
|
||||
result: "12/6/1971, 11:15:30 AM",
|
||||
},
|
||||
{
|
||||
timeZone: "Asia/Riyadh",
|
||||
date: Date.UTC(1946, 12-1, 6, 12, 0, 0),
|
||||
result: "12/6/1946, 3:06:52 PM",
|
||||
},
|
||||
];
|
||||
|
||||
for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) {
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(locale, Object.assign({timeZone: map(timeZone)}, options));
|
||||
assertEq(dtf.format(date), result);
|
||||
assertEq(dtf.resolvedOptions().timeZone, timeZone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0, "ok");
|
|
@ -0,0 +1,152 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
x => x.toUpperCase(),
|
||||
x => x.toLowerCase(),
|
||||
];
|
||||
|
||||
|
||||
const utcTimeZones = [
|
||||
// Etc/UTC and Etc/GMT are normalized to UTC.
|
||||
"Etc/UTC", "Etc/GMT",
|
||||
|
||||
// Links to Etc/GMT. (tzdata/etcetera)
|
||||
"GMT", "Etc/Greenwich", "Etc/GMT-0", "Etc/GMT+0", "Etc/GMT0",
|
||||
|
||||
// Links to Etc/UTC. (tzdata/etcetera)
|
||||
"Etc/Universal", "Etc/Zulu",
|
||||
|
||||
// Links to Etc/GMT. (tzdata/backward)
|
||||
"GMT+0", "GMT-0", "GMT0", "Greenwich",
|
||||
|
||||
// Links to Etc/UTC. (tzdata/backward)
|
||||
"UTC", "Universal", "Zulu",
|
||||
];
|
||||
|
||||
for (let timeZone of utcTimeZones) {
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
assertEq(dtf.resolvedOptions().timeZone, "UTC");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ECMA-402 doesn't normalize Etc/UCT to UTC.
|
||||
const uctTimeZones = [
|
||||
"Etc/UCT", "UCT",
|
||||
];
|
||||
|
||||
for (let timeZone of uctTimeZones) {
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
assertEq(dtf.resolvedOptions().timeZone, "Etc/UCT");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const invalidTimeZones = [
|
||||
"", "null", "undefined", "UTC\0",
|
||||
|
||||
// ICU time zone name for invalid time zones.
|
||||
"Etc/Unknown",
|
||||
|
||||
// ICU custom time zones.
|
||||
"GMT-1", "GMT+1", "GMT-10", "GMT+10",
|
||||
"GMT-10:00", "GMT+10:00",
|
||||
"GMT-1000", "GMT+1000",
|
||||
|
||||
// Legacy ICU time zones.
|
||||
"ACT", "AET", "AGT", "ART", "AST", "BET", "BST", "CAT", "CNT", "CST",
|
||||
"CTT", "EAT", "ECT", "IET", "IST", "JST", "MIT", "NET", "NST", "PLT",
|
||||
"PNT", "PRT", "PST", "SST", "VST",
|
||||
|
||||
// Deprecated IANA time zones.
|
||||
"SystemV/AST4ADT", "SystemV/EST5EDT", "SystemV/CST6CDT", "SystemV/MST7MDT",
|
||||
"SystemV/PST8PDT", "SystemV/YST9YDT", "SystemV/AST4", "SystemV/EST5",
|
||||
"SystemV/CST6", "SystemV/MST7", "SystemV/PST8", "SystemV/YST9", "SystemV/HST10",
|
||||
];
|
||||
|
||||
for (let timeZone of invalidTimeZones) {
|
||||
for (let map of tzMapper) {
|
||||
assertThrowsInstanceOf(() => {
|
||||
new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
}, RangeError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GMT[+-]hh is invalid, but Etc/GMT[+-]hh is a valid IANA time zone.
|
||||
for (let gmtOffset = -14; gmtOffset <= 12; ++gmtOffset) {
|
||||
// Skip Etc/GMT0.
|
||||
if (gmtOffset === 0)
|
||||
continue;
|
||||
|
||||
let timeZone = `Etc/GMT${gmtOffset > 0 ? "+" : ""}${gmtOffset}`;
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
assertEq(dtf.resolvedOptions().timeZone, timeZone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const invalidEtcGMTNames = [
|
||||
// Out of bounds GMT offset.
|
||||
"Etc/GMT-15", "Etc/GMT+13",
|
||||
|
||||
// Etc/GMT[+-]hh:mm isn't a IANA time zone name.
|
||||
"Etc/GMT-10:00", "Etc/GMT+10:00",
|
||||
"Etc/GMT-1000", "Etc/GMT+1000",
|
||||
];
|
||||
|
||||
for (let timeZone of invalidEtcGMTNames) {
|
||||
for (let map of tzMapper) {
|
||||
assertThrowsInstanceOf(() => {
|
||||
new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
}, RangeError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// RangeError is thrown for primitive values, because ToString(<primitive>)
|
||||
// isn't a valid time zone name.
|
||||
for (let nonStrings of [null, 0, 0.5, true, false]) {
|
||||
assertThrowsInstanceOf(() => {
|
||||
new Intl.DateTimeFormat(undefined, {timeZone: nonStrings});
|
||||
}, RangeError);
|
||||
}
|
||||
|
||||
// ToString(<symbol>) throws TypeError.
|
||||
assertThrowsInstanceOf(() => {
|
||||
new Intl.DateTimeFormat(undefined, {timeZone: Symbol()});
|
||||
}, TypeError);
|
||||
|
||||
// |undefined| or absent "timeZone" option selects the default time zone.
|
||||
{
|
||||
let {timeZone: tzAbsent} = new Intl.DateTimeFormat(undefined, {}).resolvedOptions();
|
||||
let {timeZone: tzUndefined} = new Intl.DateTimeFormat(undefined, {timeZone: undefined}).resolvedOptions();
|
||||
|
||||
assertEq(typeof tzAbsent, "string");
|
||||
assertEq(typeof tzUndefined, "string");
|
||||
assertEq(tzUndefined, tzAbsent);
|
||||
|
||||
// The default time zone isn't a link name.
|
||||
let {timeZone: tzDefault} = new Intl.DateTimeFormat(undefined, {timeZone: tzAbsent}).resolvedOptions();
|
||||
assertEq(tzDefault, tzAbsent);
|
||||
}
|
||||
|
||||
// Objects are converted through ToString().
|
||||
{
|
||||
let timeZone = "Europe/Warsaw";
|
||||
let obj = {
|
||||
toString() {
|
||||
return timeZone;
|
||||
}
|
||||
};
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: obj});
|
||||
assertEq(dtf.resolvedOptions().timeZone, timeZone);
|
||||
}
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0, "ok");
|
|
@ -0,0 +1,104 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
x => x.toUpperCase(),
|
||||
x => x.toLowerCase(),
|
||||
];
|
||||
|
||||
// Backzone names derived from IANA Time Zone Database, version tzdata2016f.
|
||||
const backZones = [
|
||||
"Africa/Addis_Ababa", // Africa/Nairobi
|
||||
"Africa/Asmara", // Africa/Nairobi
|
||||
"Africa/Bamako", // Africa/Abidjan
|
||||
"Africa/Bangui", // Africa/Lagos
|
||||
"Africa/Banjul", // Africa/Abidjan
|
||||
"Africa/Blantyre", // Africa/Maputo
|
||||
"Africa/Brazzaville", // Africa/Lagos
|
||||
"Africa/Bujumbura", // Africa/Maputo
|
||||
"Africa/Conakry", // Africa/Abidjan
|
||||
"Africa/Dakar", // Africa/Abidjan
|
||||
"Africa/Dar_es_Salaam", // Africa/Nairobi
|
||||
"Africa/Djibouti", // Africa/Nairobi
|
||||
"Africa/Douala", // Africa/Lagos
|
||||
"Africa/Freetown", // Africa/Abidjan
|
||||
"Africa/Gaborone", // Africa/Maputo
|
||||
"Africa/Harare", // Africa/Maputo
|
||||
"Africa/Juba", // Africa/Khartoum
|
||||
"Africa/Kampala", // Africa/Nairobi
|
||||
"Africa/Kigali", // Africa/Maputo
|
||||
"Africa/Kinshasa", // Africa/Lagos
|
||||
"Africa/Libreville", // Africa/Lagos
|
||||
"Africa/Lome", // Africa/Abidjan
|
||||
"Africa/Luanda", // Africa/Lagos
|
||||
"Africa/Lubumbashi", // Africa/Maputo
|
||||
"Africa/Lusaka", // Africa/Maputo
|
||||
"Africa/Malabo", // Africa/Lagos
|
||||
"Africa/Maseru", // Africa/Johannesburg
|
||||
"Africa/Mbabane", // Africa/Johannesburg
|
||||
"Africa/Mogadishu", // Africa/Nairobi
|
||||
"Africa/Niamey", // Africa/Lagos
|
||||
"Africa/Nouakchott", // Africa/Abidjan
|
||||
"Africa/Ouagadougou", // Africa/Abidjan
|
||||
"Africa/Porto-Novo", // Africa/Lagos
|
||||
"Africa/Sao_Tome", // Africa/Abidjan
|
||||
"Africa/Timbuktu", // Africa/Abidjan
|
||||
"America/Anguilla", // America/Port_of_Spain
|
||||
"America/Antigua", // America/Port_of_Spain
|
||||
"America/Argentina/ComodRivadavia", // America/Argentina/Catamarca
|
||||
"America/Aruba", // America/Curacao
|
||||
"America/Cayman", // America/Panama
|
||||
"America/Coral_Harbour", // America/Atikokan
|
||||
"America/Dominica", // America/Port_of_Spain
|
||||
"America/Ensenada", // America/Tijuana
|
||||
"America/Grenada", // America/Port_of_Spain
|
||||
"America/Guadeloupe", // America/Port_of_Spain
|
||||
"America/Montreal", // America/Toronto
|
||||
"America/Montserrat", // America/Port_of_Spain
|
||||
"America/Rosario", // America/Argentina/Cordoba
|
||||
"America/St_Kitts", // America/Port_of_Spain
|
||||
"America/St_Lucia", // America/Port_of_Spain
|
||||
"America/St_Thomas", // America/Port_of_Spain
|
||||
"America/St_Vincent", // America/Port_of_Spain
|
||||
"America/Tortola", // America/Port_of_Spain
|
||||
"Antarctica/McMurdo", // Pacific/Auckland
|
||||
"Asia/Aden", // Asia/Riyadh
|
||||
"Asia/Bahrain", // Asia/Qatar
|
||||
"Asia/Chongqing", // Asia/Shanghai
|
||||
"Asia/Harbin", // Asia/Shanghai
|
||||
"Asia/Kashgar", // Asia/Urumqi
|
||||
"Asia/Kuwait", // Asia/Riyadh
|
||||
"Asia/Muscat", // Asia/Dubai
|
||||
"Asia/Phnom_Penh", // Asia/Bangkok
|
||||
"Asia/Tel_Aviv", // Asia/Jerusalem
|
||||
"Asia/Vientiane", // Asia/Bangkok
|
||||
"Atlantic/Jan_Mayen", // Europe/Oslo
|
||||
"Atlantic/St_Helena", // Africa/Abidjan
|
||||
"Europe/Belfast", // Europe/London
|
||||
"Europe/Guernsey", // Europe/London
|
||||
"Europe/Isle_of_Man", // Europe/London
|
||||
"Europe/Jersey", // Europe/London
|
||||
"Europe/Ljubljana", // Europe/Belgrade
|
||||
"Europe/Sarajevo", // Europe/Belgrade
|
||||
"Europe/Skopje", // Europe/Belgrade
|
||||
"Europe/Tiraspol", // Europe/Chisinau
|
||||
"Europe/Vaduz", // Europe/Zurich
|
||||
"Europe/Zagreb", // Europe/Belgrade
|
||||
"Indian/Antananarivo", // Africa/Nairobi
|
||||
"Indian/Comoro", // Africa/Nairobi
|
||||
"Indian/Mayotte", // Africa/Nairobi
|
||||
"Pacific/Johnston", // Pacific/Honolulu
|
||||
"Pacific/Midway", // Pacific/Pago_Pago
|
||||
"Pacific/Saipan", // Pacific/Guam
|
||||
];
|
||||
|
||||
for (let timeZone of backZones) {
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
|
||||
assertEq(dtf.resolvedOptions().timeZone, timeZone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0, "ok");
|
|
@ -0,0 +1,152 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
x => x.toUpperCase(),
|
||||
x => x.toLowerCase(),
|
||||
];
|
||||
|
||||
// Link names derived from IANA Time Zone Database, version tzdata2016f.
|
||||
const links = [
|
||||
["Africa/Asmera", "Africa/Asmara"],
|
||||
["America/Atka", "America/Adak"],
|
||||
["America/Buenos_Aires", "America/Argentina/Buenos_Aires"],
|
||||
["America/Catamarca", "America/Argentina/Catamarca"],
|
||||
["America/Cordoba", "America/Argentina/Cordoba"],
|
||||
["America/Fort_Wayne", "America/Indiana/Indianapolis"],
|
||||
["America/Indianapolis", "America/Indiana/Indianapolis"],
|
||||
["America/Jujuy", "America/Argentina/Jujuy"],
|
||||
["America/Knox_IN", "America/Indiana/Knox"],
|
||||
["America/Kralendijk", "America/Curacao"],
|
||||
["America/Louisville", "America/Kentucky/Louisville"],
|
||||
["America/Lower_Princes", "America/Curacao"],
|
||||
["America/Marigot", "America/Port_of_Spain"],
|
||||
["America/Mendoza", "America/Argentina/Mendoza"],
|
||||
["America/Porto_Acre", "America/Rio_Branco"],
|
||||
// Enable when we support tzdata2016a or later.
|
||||
// ["America/Santa_Isabel", "America/Tijuana"],
|
||||
["America/Santa_Isabel", "America/Santa_Isabel"],
|
||||
["America/Shiprock", "America/Denver"],
|
||||
["America/St_Barthelemy", "America/Port_of_Spain"],
|
||||
["America/Virgin", "America/Port_of_Spain"],
|
||||
["Antarctica/South_Pole", "Antarctica/McMurdo"],
|
||||
["Arctic/Longyearbyen", "Europe/Oslo"],
|
||||
["Asia/Ashkhabad", "Asia/Ashgabat"],
|
||||
["Asia/Calcutta", "Asia/Kolkata"],
|
||||
["Asia/Chungking", "Asia/Chongqing"],
|
||||
["Asia/Dacca", "Asia/Dhaka"],
|
||||
["Asia/Istanbul", "Europe/Istanbul"],
|
||||
["Asia/Katmandu", "Asia/Kathmandu"],
|
||||
["Asia/Macao", "Asia/Macau"],
|
||||
["Asia/Saigon", "Asia/Ho_Chi_Minh"],
|
||||
["Asia/Thimbu", "Asia/Thimphu"],
|
||||
["Asia/Ujung_Pandang", "Asia/Makassar"],
|
||||
["Asia/Ulan_Bator", "Asia/Ulaanbaatar"],
|
||||
["Atlantic/Faeroe", "Atlantic/Faroe"],
|
||||
["Australia/ACT", "Australia/Sydney"],
|
||||
["Australia/Canberra", "Australia/Sydney"],
|
||||
["Australia/LHI", "Australia/Lord_Howe"],
|
||||
["Australia/NSW", "Australia/Sydney"],
|
||||
["Australia/North", "Australia/Darwin"],
|
||||
["Australia/Queensland", "Australia/Brisbane"],
|
||||
["Australia/South", "Australia/Adelaide"],
|
||||
["Australia/Tasmania", "Australia/Hobart"],
|
||||
["Australia/Victoria", "Australia/Melbourne"],
|
||||
["Australia/West", "Australia/Perth"],
|
||||
["Australia/Yancowinna", "Australia/Broken_Hill"],
|
||||
["Brazil/Acre", "America/Rio_Branco"],
|
||||
["Brazil/DeNoronha", "America/Noronha"],
|
||||
["Brazil/East", "America/Sao_Paulo"],
|
||||
["Brazil/West", "America/Manaus"],
|
||||
["Canada/Atlantic", "America/Halifax"],
|
||||
["Canada/Central", "America/Winnipeg"],
|
||||
["Canada/East-Saskatchewan", "America/Regina"],
|
||||
["Canada/Eastern", "America/Toronto"],
|
||||
["Canada/Mountain", "America/Edmonton"],
|
||||
["Canada/Newfoundland", "America/St_Johns"],
|
||||
["Canada/Pacific", "America/Vancouver"],
|
||||
["Canada/Saskatchewan", "America/Regina"],
|
||||
["Canada/Yukon", "America/Whitehorse"],
|
||||
["Chile/Continental", "America/Santiago"],
|
||||
["Chile/EasterIsland", "Pacific/Easter"],
|
||||
["Cuba", "America/Havana"],
|
||||
["Egypt", "Africa/Cairo"],
|
||||
["Eire", "Europe/Dublin"],
|
||||
["Etc/GMT+0", "Etc/GMT"],
|
||||
["Etc/GMT-0", "Etc/GMT"],
|
||||
["Etc/GMT0", "Etc/GMT"],
|
||||
["Etc/Greenwich", "Etc/GMT"],
|
||||
["Etc/Universal", "Etc/UTC"],
|
||||
["Etc/Zulu", "Etc/UTC"],
|
||||
["Europe/Bratislava", "Europe/Prague"],
|
||||
["Europe/Busingen", "Europe/Zurich"],
|
||||
["Europe/Mariehamn", "Europe/Helsinki"],
|
||||
["Europe/Nicosia", "Asia/Nicosia"],
|
||||
["Europe/Podgorica", "Europe/Belgrade"],
|
||||
["Europe/San_Marino", "Europe/Rome"],
|
||||
["Europe/Vatican", "Europe/Rome"],
|
||||
["GB", "Europe/London"],
|
||||
["GB-Eire", "Europe/London"],
|
||||
["GMT", "Etc/GMT"],
|
||||
["GMT+0", "Etc/GMT"],
|
||||
["GMT-0", "Etc/GMT"],
|
||||
["GMT0", "Etc/GMT"],
|
||||
["Greenwich", "Etc/GMT"],
|
||||
["Hongkong", "Asia/Hong_Kong"],
|
||||
["Iceland", "Atlantic/Reykjavik"],
|
||||
["Iran", "Asia/Tehran"],
|
||||
["Israel", "Asia/Jerusalem"],
|
||||
["Jamaica", "America/Jamaica"],
|
||||
["Japan", "Asia/Tokyo"],
|
||||
["Kwajalein", "Pacific/Kwajalein"],
|
||||
["Libya", "Africa/Tripoli"],
|
||||
["Mexico/BajaNorte", "America/Tijuana"],
|
||||
["Mexico/BajaSur", "America/Mazatlan"],
|
||||
["Mexico/General", "America/Mexico_City"],
|
||||
["NZ", "Pacific/Auckland"],
|
||||
["NZ-CHAT", "Pacific/Chatham"],
|
||||
["Navajo", "America/Denver"],
|
||||
["PRC", "Asia/Shanghai"],
|
||||
["Pacific/Ponape", "Pacific/Pohnpei"],
|
||||
["Pacific/Samoa", "Pacific/Pago_Pago"],
|
||||
["Pacific/Truk", "Pacific/Chuuk"],
|
||||
["Pacific/Yap", "Pacific/Chuuk"],
|
||||
["Poland", "Europe/Warsaw"],
|
||||
["Portugal", "Europe/Lisbon"],
|
||||
["ROC", "Asia/Taipei"],
|
||||
["ROK", "Asia/Seoul"],
|
||||
["Singapore", "Asia/Singapore"],
|
||||
["Turkey", "Europe/Istanbul"],
|
||||
["UCT", "Etc/UCT"],
|
||||
["US/Alaska", "America/Anchorage"],
|
||||
["US/Aleutian", "America/Adak"],
|
||||
["US/Arizona", "America/Phoenix"],
|
||||
["US/Central", "America/Chicago"],
|
||||
["US/East-Indiana", "America/Indiana/Indianapolis"],
|
||||
["US/Eastern", "America/New_York"],
|
||||
["US/Hawaii", "Pacific/Honolulu"],
|
||||
["US/Indiana-Starke", "America/Indiana/Knox"],
|
||||
["US/Michigan", "America/Detroit"],
|
||||
["US/Mountain", "America/Denver"],
|
||||
["US/Pacific", "America/Los_Angeles"],
|
||||
["US/Pacific-New", "America/Los_Angeles"],
|
||||
["US/Samoa", "Pacific/Pago_Pago"],
|
||||
["UTC", "Etc/UTC"],
|
||||
["Universal", "Etc/UTC"],
|
||||
["W-SU", "Europe/Moscow"],
|
||||
["Zulu", "Etc/UTC"],
|
||||
];
|
||||
|
||||
for (let [linkName, target] of links) {
|
||||
if (target === "Etc/UTC" || target === "Etc/GMT")
|
||||
target = "UTC";
|
||||
|
||||
for (let map of tzMapper) {
|
||||
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
|
||||
assertEq(dtf.resolvedOptions().timeZone, target, `${linkName} -> ${target}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0, "ok");
|
|
@ -0,0 +1,72 @@
|
|||
/* 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/. */
|
||||
|
||||
|
||||
// CoverInitName in arrow parameters.
|
||||
({a = 1}, {b = 2}, {c = 3}) => {};
|
||||
({a = 1} = {}, {b = 2}, {c = 3}) => {};
|
||||
({a = 1} = {}, {b = 2} = {}, {c = 3}) => {};
|
||||
({a = 1} = {}, {b = 2} = {}, {c = 3} = {}) => {};
|
||||
|
||||
|
||||
// CoverInitName in CoverParenthesizedExpressionAndArrowParameterList,
|
||||
// but not ArrowParameters.
|
||||
assertThrowsInstanceOf(() => eval(`
|
||||
({a = 1}, {b = 2}, {c = 3});
|
||||
`), SyntaxError);
|
||||
assertThrowsInstanceOf(() => eval(`
|
||||
({a = 1}, {b = 2}, {c = 3} = {});
|
||||
`), SyntaxError);
|
||||
assertThrowsInstanceOf(() => eval(`
|
||||
({a = 1}, {b = 2} = {}, {c = 3} = {});
|
||||
`), SyntaxError);
|
||||
|
||||
|
||||
// CoverInitName nested in array destructuring.
|
||||
[{a = 0}] = [{}];
|
||||
var [{a = 0}] = [{}];
|
||||
{ let [{a = 0}] = [{}]; }
|
||||
{ const [{a = 0}] = [{}]; }
|
||||
|
||||
for ([{a = 0}] of []);
|
||||
for (var [{a = 0}] of []);
|
||||
for (let [{a = 0}] of []);
|
||||
for (const [{a = 0}] of []);
|
||||
|
||||
function f([{a = 0}]) {}
|
||||
var h = ([{a = 0}]) => {};
|
||||
|
||||
|
||||
// CoverInitName nested in rest pattern.
|
||||
[...[{a = 0}]] = [{}];
|
||||
var [...[{a = 0}]] = [{}];
|
||||
{ let [...[{a = 0}]] = [{}]; }
|
||||
{ const [...[{a = 0}]] = [{}]; }
|
||||
|
||||
for ([...[{a = 0}]] of []);
|
||||
for (var [...[{a = 0}]] of []);
|
||||
for (let [...[{a = 0}]] of []);
|
||||
for (const [...[{a = 0}]] of []);
|
||||
|
||||
function f([...[{a = 0}]]) {}
|
||||
var h = ([...[{a = 0}]]) => {};
|
||||
|
||||
|
||||
// CoverInitName nested in object destructuring.
|
||||
({p: {a = 0}} = {p: {}});
|
||||
var {p: {a = 0}} = {p: {}};
|
||||
{ let {p: {a = 0}} = {p: {}}; }
|
||||
{ const {p: {a = 0}} = {p: {}}; }
|
||||
|
||||
for ({p: {a = 0}} of []);
|
||||
for (var {p: {a = 0}} of []);
|
||||
for (let {p: {a = 0}} of []);
|
||||
for (const {p: {a = 0}} of []);
|
||||
|
||||
function f({p: {a = 0}}) {}
|
||||
var h = ({p: {a = 0}}) => {};
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
|
@ -15,7 +15,6 @@ const SYNTAX_ERROR_STMTS = [
|
|||
"({x=1} = {y=1});",
|
||||
"({x: y={z=1}}={})",
|
||||
"({x=1}),",
|
||||
"({z=1}={}, {w=2}, {e=3})=>{};",
|
||||
"({z={x=1}})=>{};",
|
||||
"({x = ({y=1}) => y})",
|
||||
"(({x=1})) => x",
|
||||
|
|
|
@ -5,14 +5,12 @@ print(BUGNUMBER + ": " + summary);
|
|||
|
||||
let TypedArray = Object.getPrototypeOf(Float32Array.prototype).constructor;
|
||||
|
||||
// FIXME: bug 1165053
|
||||
// assertEq(Object.getOwnPropertyDescriptor(TypedArray, Symbol.species).get.name, "get [Symbol.species]");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray, Symbol.species).get.name, "get [Symbol.species]");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, "buffer").get.name, "get buffer");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, "byteLength").get.name, "get byteLength");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, "byteOffset").get.name, "get byteOffset");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, "length").get.name, "get length");
|
||||
// FIXME: bug 1114580
|
||||
// assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, Symbol.toStringTag).get.name, "get [Symbol.toStringTag]");
|
||||
assertEq(Object.getOwnPropertyDescriptor(TypedArray.prototype, Symbol.toStringTag).get.name, "get [Symbol.toStringTag]");
|
||||
|
||||
if (typeof reportCompare === 'function')
|
||||
reportCompare(true, true);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* 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/. */
|
||||
|
||||
|
||||
// Destructuring assignment.
|
||||
var a, b;
|
||||
({__proto__: a, __proto__: b} = {});
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
|
||||
// Destructuring binding with "var".
|
||||
var {__proto__: a, __proto__: b} = {};
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
|
||||
// Destructuring binding with "let".
|
||||
{
|
||||
let {__proto__: a, __proto__: b} = {};
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
}
|
||||
|
||||
// Destructuring binding with "const".
|
||||
{
|
||||
const {__proto__: a, __proto__: b} = {};
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
}
|
||||
|
||||
// Function parameters.
|
||||
function f1({__proto__: a, __proto__: b}) {
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
}
|
||||
f1({});
|
||||
|
||||
// Arrow function parameters.
|
||||
var f2 = ({__proto__: a, __proto__: b}) => {
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
};
|
||||
f2({});
|
||||
|
||||
// Arrow function parameters with defaults (initially parsed as destructuring assignment).
|
||||
var f3 = ({__proto__: a, __proto__: b} = {}) => {
|
||||
assertEq(a, Object.prototype);
|
||||
assertEq(b, Object.prototype);
|
||||
};
|
||||
f3({});
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
|
@ -34,6 +34,11 @@ skip script test262/intl402/ch12/12.2/12.2.2_L15.js
|
|||
skip script test262/ch13/13.2/13.2-15-1.js
|
||||
skip script test262/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js
|
||||
|
||||
# ECMA-402 1st ed. required |timeZoneName: undefined|, but newer versions have
|
||||
# changed it to being the default time zone, cf. the NOTE in
|
||||
# Intl.DateTimeFormat.prototype.resolvedOptions().
|
||||
skip script test262/intl402/ch12/12.3/12.3.3.js
|
||||
|
||||
#######################################################################
|
||||
# Tests disabled due to jstest limitations wrt imported test262 tests #
|
||||
#######################################################################
|
||||
|
|
|
@ -181,6 +181,7 @@
|
|||
macro(locale, locale, "locale") \
|
||||
macro(lookupGetter, lookupGetter, "__lookupGetter__") \
|
||||
macro(lookupSetter, lookupSetter, "__lookupSetter__") \
|
||||
macro(MapConstructorInit, MapConstructorInit, "MapConstructorInit") \
|
||||
macro(MapIterator, MapIterator, "Map Iterator") \
|
||||
macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
|
||||
macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
|
||||
|
@ -262,6 +263,7 @@
|
|||
macro(selfHosted, selfHosted, "self-hosted") \
|
||||
macro(sensitivity, sensitivity, "sensitivity") \
|
||||
macro(set, set, "set") \
|
||||
macro(SetConstructorInit, SetConstructorInit, "SetConstructorInit") \
|
||||
macro(SetIterator, SetIterator, "Set Iterator") \
|
||||
macro(setPrefix, setPrefix, "set ") \
|
||||
macro(setPrototypeOf, setPrototypeOf, "setPrototypeOf") \
|
||||
|
@ -326,6 +328,8 @@
|
|||
macro(void0, void0, "(void 0)") \
|
||||
macro(wasm, wasm, "wasm") \
|
||||
macro(watch, watch, "watch") \
|
||||
macro(WeakMapConstructorInit, WeakMapConstructorInit, "WeakMapConstructorInit") \
|
||||
macro(WeakSetConstructorInit, WeakSetConstructorInit, "WeakSetConstructorInit") \
|
||||
macro(WeakSet_add, WeakSet_add, "WeakSet_add") \
|
||||
macro(weekday, weekday, "weekday") \
|
||||
macro(weekendEnd, weekendEnd, "weekendEnd") \
|
||||
|
|
|
@ -427,6 +427,18 @@ class GlobalObject : public NativeObject
|
|||
return &global->getPrototype(key).toObject();
|
||||
}
|
||||
|
||||
static NativeObject* getOrCreateSetPrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_Set))
|
||||
return nullptr;
|
||||
return &global->getPrototype(JSProto_Set).toObject().as<NativeObject>();
|
||||
}
|
||||
|
||||
static NativeObject* getOrCreateWeakSetPrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_WeakSet))
|
||||
return nullptr;
|
||||
return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
|
||||
}
|
||||
|
||||
JSObject* getOrCreateIntlObject(JSContext* cx) {
|
||||
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
|
||||
}
|
||||
|
|
|
@ -1875,16 +1875,6 @@ intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_LocalTZA(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments");
|
||||
|
||||
args.rval().setDouble(DateTimeInfo::localTZA());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2314,7 +2304,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
|
||||
JS_FN("_FinishBoundFunctionInit", intrinsic_FinishBoundFunctionInit, 4,0),
|
||||
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
|
||||
JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0),
|
||||
JS_FN("AddContentTelemetry", intrinsic_AddContentTelemetry, 2,0),
|
||||
|
||||
JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0,
|
||||
|
@ -2499,11 +2488,14 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
// See builtin/Intl.h for descriptions of the intl_* functions.
|
||||
JS_FN("intl_availableCalendars", intl_availableCalendars, 1,0),
|
||||
JS_FN("intl_availableCollations", intl_availableCollations, 1,0),
|
||||
JS_FN("intl_availableTimeZones", intl_availableTimeZones, 0,0),
|
||||
JS_FN("intl_canonicalizeTimeZone", intl_canonicalizeTimeZone, 1,0),
|
||||
JS_FN("intl_Collator", intl_Collator, 2,0),
|
||||
JS_FN("intl_Collator_availableLocales", intl_Collator_availableLocales, 0,0),
|
||||
JS_FN("intl_CompareStrings", intl_CompareStrings, 3,0),
|
||||
JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2,0),
|
||||
JS_FN("intl_DateTimeFormat_availableLocales", intl_DateTimeFormat_availableLocales, 0,0),
|
||||
JS_FN("intl_defaultTimeZone", intl_defaultTimeZone, 0,0),
|
||||
JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2,0),
|
||||
JS_FN("intl_FormatNumber", intl_FormatNumber, 2,0),
|
||||
JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1,0),
|
||||
|
|
|
@ -1318,7 +1318,13 @@ XPCJSContext::InterruptCallback(JSContext* cx)
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!win->IsDying());
|
||||
if (win->IsDying()) {
|
||||
// The window is being torn down. When that happens we try to prevent
|
||||
// the dispatch of new runnables, so it also makes sense to kill any
|
||||
// long-running script. The user is primarily interested in this page
|
||||
// going away.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (win->GetIsPrerendered()) {
|
||||
// We cannot display a dialog if the page is being prerendered, so
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include "nsCSSProps.h"
|
||||
#include "nsPluginFrame.h"
|
||||
#include "DisplayItemScrollClip.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount().
|
||||
|
@ -6723,6 +6724,17 @@ nsCharClipDisplayItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
|
||||
nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
bool aHandleOpacity,
|
||||
const DisplayItemScrollClip* aScrollClip)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList, aScrollClip)
|
||||
, mEffectsBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
|
||||
, mHandleOpacity(aHandleOpacity)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplaySVGEffects);
|
||||
}
|
||||
|
||||
nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
bool aHandleOpacity)
|
||||
|
@ -6815,10 +6827,132 @@ bool nsDisplaySVGEffects::ValidateSVGFrame()
|
|||
return true;
|
||||
}
|
||||
|
||||
static IntRect
|
||||
ComputeClipExtsInDeviceSpace(gfxContext& aCtx)
|
||||
{
|
||||
gfxContextMatrixAutoSaveRestore matRestore(&aCtx);
|
||||
|
||||
// Get the clip extents in device space.
|
||||
aCtx.SetMatrix(gfxMatrix());
|
||||
gfxRect clippedFrameSurfaceRect = aCtx.GetClipExtents();
|
||||
clippedFrameSurfaceRect.RoundOut();
|
||||
|
||||
IntRect result;
|
||||
ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
|
||||
return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
|
||||
: IntRect();
|
||||
}
|
||||
|
||||
typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
|
||||
|
||||
static nsPoint
|
||||
ComputeOffsetToUserSpace(const PaintFramesParams& aParams)
|
||||
{
|
||||
nsIFrame* frame = aParams.frame;
|
||||
nsPoint offsetToBoundingBox = aParams.builder->ToReferenceFrame(frame) -
|
||||
nsSVGIntegrationUtils::GetOffsetToBoundingBox(frame);
|
||||
if (!frame->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
// Snap the offset if the reference frame is not a SVG frame, since other
|
||||
// frames will be snapped to pixel when rendering.
|
||||
offsetToBoundingBox = nsPoint(
|
||||
frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
|
||||
frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
|
||||
}
|
||||
|
||||
// After applying only "offsetToBoundingBox", aParams.ctx would have its
|
||||
// origin at the top left corner of frame's bounding box (over all
|
||||
// continuations).
|
||||
// However, SVG painting needs the origin to be located at the origin of the
|
||||
// SVG frame's "user space", i.e. the space in which, for example, the
|
||||
// frame's BBox lives.
|
||||
// SVG geometry frames and foreignObject frames apply their own offsets, so
|
||||
// their position is relative to their user space. So for these frame types,
|
||||
// if we want aCtx to be in user space, we first need to subtract the
|
||||
// frame's position so that SVG painting can later add it again and the
|
||||
// frame is painted in the right place.
|
||||
gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(frame);
|
||||
nsPoint toUserSpace =
|
||||
nsPoint(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
|
||||
nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
|
||||
|
||||
return (offsetToBoundingBox - toUserSpace);
|
||||
}
|
||||
|
||||
static void
|
||||
ComputeMaskGeometry(PaintFramesParams& aParams)
|
||||
{
|
||||
// Properties are added lazily and may have been removed by a restyle, so
|
||||
// make sure all applicable ones are set again.
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aParams.frame);
|
||||
|
||||
const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
|
||||
|
||||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
|
||||
|
||||
if (maskFrames.Length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
nsIFrame* frame = aParams.frame;
|
||||
|
||||
nsPoint offsetToUserSpace = ComputeOffsetToUserSpace(aParams);
|
||||
gfxPoint devPixelOffsetToUserSpace =
|
||||
nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
|
||||
frame->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
gfxContextMatrixAutoSaveRestore matSR(&ctx);
|
||||
ctx.SetMatrix(ctx.CurrentMatrix().Translate(devPixelOffsetToUserSpace));
|
||||
|
||||
// Convert boaderArea and dirtyRect to user space.
|
||||
int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
nsRect userSpaceBorderArea = aParams.borderArea - offsetToUserSpace;
|
||||
nsRect userSpaceDirtyRect = aParams.dirtyRect - offsetToUserSpace;
|
||||
|
||||
// Union all mask layer rectangles in user space.
|
||||
gfxRect maskInUserSpace;
|
||||
for (size_t i = 0; i < maskFrames.Length() ; i++) {
|
||||
nsSVGMaskFrame* maskFrame = maskFrames[i];
|
||||
gfxRect currentMaskSurfaceRect;
|
||||
|
||||
if (maskFrame) {
|
||||
currentMaskSurfaceRect = maskFrame->GetMaskArea(aParams.frame);
|
||||
} else {
|
||||
nsCSSRendering::ImageLayerClipState clipState;
|
||||
nsCSSRendering::GetImageLayerClip(svgReset->mMask.mLayers[i],
|
||||
frame,
|
||||
*frame->StyleBorder(),
|
||||
userSpaceBorderArea,
|
||||
userSpaceDirtyRect,
|
||||
false, /* aWillPaintBorder */
|
||||
appUnitsPerDevPixel,
|
||||
&clipState);
|
||||
currentMaskSurfaceRect = clipState.mDirtyRectGfx;
|
||||
}
|
||||
|
||||
maskInUserSpace = maskInUserSpace.Union(currentMaskSurfaceRect);
|
||||
}
|
||||
|
||||
ctx.Save();
|
||||
|
||||
if (!maskInUserSpace.IsEmpty()) {
|
||||
ctx.Clip(maskInUserSpace);
|
||||
}
|
||||
|
||||
IntRect result = ComputeClipExtsInDeviceSpace(ctx);
|
||||
ctx.Restore();
|
||||
|
||||
aParams.maskRect = result;
|
||||
}
|
||||
|
||||
nsDisplayMask::nsDisplayMask(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
bool aHandleOpacity)
|
||||
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aHandleOpacity)
|
||||
bool aHandleOpacity,
|
||||
const DisplayItemScrollClip* aScrollClip)
|
||||
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aHandleOpacity, aScrollClip)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayMask);
|
||||
}
|
||||
|
@ -6926,9 +7060,20 @@ nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
|||
aManager,
|
||||
mHandleOpacity);
|
||||
|
||||
// Clip the drawing target by mVisibleRect, which contains the visible
|
||||
// region of the target frame and its out-of-flow and inflow descendants.
|
||||
gfxContext* context = aCtx->ThebesContext();
|
||||
context->Clip(NSRectToSnappedRect(mVisibleRect,
|
||||
mFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
*aCtx->GetDrawTarget()));
|
||||
|
||||
ComputeMaskGeometry(params);
|
||||
|
||||
image::DrawResult result =
|
||||
nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
|
||||
|
||||
context->PopClip();
|
||||
|
||||
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
|
||||
}
|
||||
|
||||
|
|
|
@ -3839,6 +3839,9 @@ private:
|
|||
|
||||
class nsDisplaySVGEffects: public nsDisplayWrapList {
|
||||
public:
|
||||
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aHandleOpacity,
|
||||
const DisplayItemScrollClip* aScrollClip);
|
||||
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aHandleOpacity);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
@ -3850,11 +3853,6 @@ public:
|
|||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState,
|
||||
nsTArray<nsIFrame*> *aOutFrames) override;
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override {
|
||||
*aSnap = false;
|
||||
return mEffectsBounds + ToReferenceFrame();
|
||||
}
|
||||
|
||||
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
|
||||
return false;
|
||||
|
@ -3886,7 +3884,8 @@ protected:
|
|||
class nsDisplayMask : public nsDisplaySVGEffects {
|
||||
public:
|
||||
nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aHandleOpacity);
|
||||
nsDisplayList* aList, bool aHandleOpacity,
|
||||
const DisplayItemScrollClip* aScrollClip);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayMask();
|
||||
#endif
|
||||
|
@ -3933,7 +3932,11 @@ public:
|
|||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters) override;
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override {
|
||||
*aSnap = false;
|
||||
return mEffectsBounds + ToReferenceFrame();
|
||||
}
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion) override;
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
|
|
@ -2183,8 +2183,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
inTransform = true;
|
||||
}
|
||||
bool usingFilter = StyleEffects()->HasFilters();
|
||||
bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this);
|
||||
bool usingSVGEffects = usingFilter || usingMask;
|
||||
|
||||
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
||||
nsRect dirtyRectOutsideSVGEffects = dirtyRect;
|
||||
nsDisplayList hoistedScrollInfoItemsStorage;
|
||||
if (usingSVGEffects) {
|
||||
|
@ -2226,7 +2228,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
eTransform,
|
||||
eSeparatorTransforms,
|
||||
eOpacity,
|
||||
eSVGEffects,
|
||||
eFilter,
|
||||
eBlendContainer
|
||||
};
|
||||
|
||||
|
@ -2258,8 +2260,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
} else {
|
||||
clipCapturedBy = ContainerItemType::eTransform;
|
||||
}
|
||||
} else if (usingSVGEffects) {
|
||||
clipCapturedBy = ContainerItemType::eSVGEffects;
|
||||
} else if (usingFilter) {
|
||||
clipCapturedBy = ContainerItemType::eFilter;
|
||||
}
|
||||
|
||||
bool clearClip = false;
|
||||
|
@ -2407,26 +2409,21 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
* output even if the element being filtered wouldn't otherwise do so.
|
||||
*/
|
||||
if (usingSVGEffects) {
|
||||
MOZ_ASSERT(StyleEffects()->HasFilters() ||
|
||||
nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this),
|
||||
MOZ_ASSERT(usingFilter ||usingMask,
|
||||
"Beside filter & mask/clip-path, what else effect do we have?");
|
||||
|
||||
if (clipCapturedBy == ContainerItemType::eSVGEffects) {
|
||||
if (clipCapturedBy == ContainerItemType::eFilter) {
|
||||
clipState.ExitStackingContextContents(&containerItemScrollClip);
|
||||
}
|
||||
// Revert to the post-filter dirty rect.
|
||||
buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects);
|
||||
|
||||
// Skip all filter effects while generating glyph mask.
|
||||
bool createFilter =
|
||||
StyleEffects()->HasFilters() && !aBuilder->IsForGenerateGlyphMask();
|
||||
bool createMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this);
|
||||
|
||||
if (createFilter) {
|
||||
if (usingFilter && !aBuilder->IsForGenerateGlyphMask()) {
|
||||
// If we are going to create a mask display item, handle opacity effect
|
||||
// in that mask display item; Otherwise, take care of opacity in this
|
||||
// filter display item.
|
||||
bool handleOpacity = !createMask && !useOpacity;
|
||||
bool handleOpacity = !usingMask && !useOpacity;
|
||||
|
||||
/* List now emptied, so add the new list to the top. */
|
||||
resultList.AppendNewToTop(
|
||||
|
@ -2434,11 +2431,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
handleOpacity));
|
||||
}
|
||||
|
||||
if (createMask) {
|
||||
if (usingMask) {
|
||||
DisplayListClipState::AutoSaveRestore maskClipState(aBuilder);
|
||||
maskClipState.Clear();
|
||||
/* List now emptied, so add the new list to the top. */
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayMask(aBuilder, this, &resultList,
|
||||
!useOpacity));
|
||||
!useOpacity, containerItemScrollClip));
|
||||
}
|
||||
|
||||
// Also add the hoisted scroll info items. We need those for APZ scrolling
|
||||
|
|
|
@ -2602,8 +2602,8 @@ public:
|
|||
|
||||
/**
|
||||
* Returns a rect that encompasses everything that might be painted by
|
||||
* this frame. This includes this frame, all its descendent frames, this
|
||||
* frame's outline, and descentant frames' outline, but does not include
|
||||
* this frame. This includes this frame, all its descendant frames, this
|
||||
* frame's outline, and descendant frames' outline, but does not include
|
||||
* areas clipped out by the CSS "overflow" and "clip" properties.
|
||||
*
|
||||
* HasOverflowRects() (below) will return true when this overflow
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
mask: url(#myMask);
|
||||
clip-path: url(#myClip);
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the mask, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<mask id="myMask" x="0" y="0" width="400" height="400" maskUnits="userSpaceOnUse">
|
||||
<rect x="0" y="0" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="100" y="100" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="200" y="200" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
</mask>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
mask: url(#myMask);
|
||||
clip-path: url(#myClip);
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the mask, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<mask id="myMask" x="0" y="0" width="400" height="400" maskUnits="userSpaceOnUse">
|
||||
<rect x="0" y="0" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="100" y="100" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="200" y="200" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
</mask>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
<!-- The forth rect should be clipped out -->
|
||||
<rect x="300" y="300" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body style="margin: 0px;">
|
||||
<svg x="0" y="0" height="300" width="300">
|
||||
<rect x="0" y="0" width="100" height="100" style="stroke:none; fill: blue"/>
|
||||
<rect x="100" y="100" width="100" height="100" style="stroke:none; fill: blue"/>
|
||||
<rect x="200" y="200" width="100" height="100" style="stroke:none; fill: blue"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
clip-path: url(#myClip);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the clip-path, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
clip-path: url(#myClip);
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the clip-path, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body style="margin: 0px;">
|
||||
<svg width="200" height="200">
|
||||
<rect x="10" y="10" width="180" height="180" fill="blue" opacity="0.5"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
clip-path: inset(10px 10px 10px 10px);
|
||||
opacity: 0.5;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the clip-path, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
clip-path: inset(10px 10px 10px 10px);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position:absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: rgba(0,0,255,0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the clip-path, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<clipPath id="myClip">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
<rect x="100" y="100" width="100" height="100"/>
|
||||
<rect x="200" y="200" width="100" height="100"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
mask: url(#myMask);
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the mask, not by the 100x100
|
||||
overflow:hidden clip. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg height="0">
|
||||
<defs>
|
||||
<mask id="myMask" x="0" y="0" width="1" height="1" maskUnits="objectBoundingBox">
|
||||
<rect x="0" y="0" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="100" y="100" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="200" y="200" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<!-- The forth rect should be clipped out -->
|
||||
<rect x="300" y="300" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
</mask>
|
||||
</defs>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#clipped {
|
||||
mask: url(mask-on-outflowElement.svg);
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#absolutePosition {
|
||||
position:absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body style="margin: 0px;">
|
||||
<div id="outer">
|
||||
<div id="clipped">
|
||||
<div id="absolutePosition">
|
||||
<!-- This should only be clipped by the mask, not by the 100x100
|
||||
overflow:hidden clip.
|
||||
image mask is always clipped by the rect of associated element. The
|
||||
forth rectangle in mask-on-outflowElement.svg is clipped out since
|
||||
the size of #clipped is (w=300, height=300)
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect x="0" y="0" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="100" y="100" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="200" y="200" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
<rect x="300" y="300" width="100" height="100" style="stroke:none; fill: #ffffff"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 430 B |
|
@ -443,4 +443,18 @@ skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-differenc
|
|||
== use-localRef-stroke-01.svg use-localRef-stroke-01-ref.svg
|
||||
== use-localRef-mask-01.svg use-localRef-mask-01-ref.svg
|
||||
|
||||
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01-ref.svg
|
||||
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01-ref.svg
|
||||
|
||||
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
|
||||
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
|
||||
|
||||
default-preferences pref(layout.css.clip-path-shapes.enabled,true)
|
||||
fuzzy(1,32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02-ref.html
|
||||
fuzzy(1,32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02-ref.html
|
||||
default-preferences
|
||||
|
||||
== mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
|
||||
== mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
|
||||
|
||||
== clipPath-and-mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
|
||||
== clipPath-and-mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче