Merge mozilla-central to autoland

--HG--
extra : rebase_source : ed5871b95beeb440688654cc676c5438c2898ccf
This commit is contained in:
Carsten "Tomcat" Book 2016-10-13 12:00:23 +02:00
Родитель ababc57dbb 802e7b16f9
Коммит f3a0e0a65e
136 изменённых файлов: 2830 добавлений и 1259 удалений

Просмотреть файл

@ -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() {

49
js/src/builtin/WeakMap.js Normal file
Просмотреть файл

@ -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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше