mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
merge mozilla-central to autoland. r=merge a=merge
This commit is contained in:
commit
f4f104e7e0
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="*"
|
||||
name="Firefox"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Firefox</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<comInterfaceExternalProxyStub
|
||||
iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
|
||||
name="IAccessible"
|
||||
tlbid="{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}"
|
||||
/>
|
||||
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:security>
|
||||
<ms_asmv3:requestedPrivileges>
|
||||
<ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</ms_asmv3:requestedPrivileges>
|
||||
</ms_asmv3:security>
|
||||
</ms_asmv3:trustInfo>
|
||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||
</ms_asmv3:windowsSettings>
|
||||
</ms_asmv3:application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
@ -2059,6 +2059,34 @@
|
||||
let getter;
|
||||
let setter;
|
||||
switch (name) {
|
||||
case "audioMuted":
|
||||
getter = () => {
|
||||
return false;
|
||||
};
|
||||
break;
|
||||
case "contentTitle":
|
||||
getter = () => {
|
||||
return SessionStore.getLazyTabValue(aTab, "title");
|
||||
};
|
||||
break;
|
||||
case "currentURI":
|
||||
getter = () => {
|
||||
let url = SessionStore.getLazyTabValue(aTab, "url");
|
||||
return Services.io.newURI(url);
|
||||
};
|
||||
break;
|
||||
case "getTabBrowser":
|
||||
getter = () => {
|
||||
return () => {
|
||||
return this;
|
||||
};
|
||||
};
|
||||
break;
|
||||
case "isRemoteBrowser":
|
||||
getter = () => {
|
||||
return browser.getAttribute("remote") == "true";
|
||||
};
|
||||
break;
|
||||
case "permitUnload":
|
||||
getter = () => {
|
||||
return () => {
|
||||
@ -2079,27 +2107,6 @@
|
||||
};
|
||||
};
|
||||
break;
|
||||
case "isRemoteBrowser":
|
||||
getter = () => {
|
||||
return browser.getAttribute("remote") == "true";
|
||||
};
|
||||
break;
|
||||
case "audioMuted":
|
||||
getter = () => {
|
||||
return false;
|
||||
};
|
||||
break;
|
||||
case "currentURI":
|
||||
getter = () => {
|
||||
let url = SessionStore.getLazyTabValue(aTab, "url");
|
||||
return Services.io.newURI(url);
|
||||
};
|
||||
break;
|
||||
case "contentTitle":
|
||||
getter = () => {
|
||||
return SessionStore.getLazyTabValue(aTab, "title");
|
||||
};
|
||||
break;
|
||||
case "userTypedValue":
|
||||
case "userTypedClear":
|
||||
getter = () => {
|
||||
|
@ -1,3 +1,3 @@
|
||||
[DEFAULT]
|
||||
[browser_toolbariconcolor_restyles.js]
|
||||
skip-if = os == "mac" && debug # Bug 1358356
|
||||
skip-if = (os == "mac" || os == "win") && debug # Bug 1358356
|
||||
|
@ -989,7 +989,7 @@ html|span.ac-emphasize-text-url {
|
||||
.ac-type-icon[type=keyword],
|
||||
.ac-site-icon[type=searchengine] {
|
||||
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg);
|
||||
/* uncomment after bug 1350010 lands: context-properties: fill; */
|
||||
-moz-context-properties: fill;
|
||||
fill: GrayText;
|
||||
}
|
||||
|
||||
|
@ -1766,7 +1766,7 @@ html|span.ac-emphasize-text-url {
|
||||
.ac-type-icon[type=keyword],
|
||||
.ac-site-icon[type=searchengine] {
|
||||
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg);
|
||||
/* uncomment after bug 1350010 lands: context-properties: fill; */
|
||||
-moz-context-properties: fill;
|
||||
fill: GrayText;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
-moz-appearance: none;
|
||||
border-style: none;
|
||||
list-style-image: url("chrome://browser/skin/page-action.svg");
|
||||
-moz-context-properties: fill;
|
||||
margin: 0;
|
||||
padding: 0 6px;
|
||||
fill: currentColor;
|
||||
|
@ -73,7 +73,7 @@
|
||||
#urlbar[actiontype="searchengine"] > #identity-box > #identity-icon {
|
||||
-moz-image-region: inherit;
|
||||
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg);
|
||||
/* uncomment after bug 1350010 lands: context-properties: fill; */
|
||||
-moz-context-properties: fill;
|
||||
fill: GrayText;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
@ -184,12 +184,15 @@ toolbarpaletteitem[place="palette"] > #zoom-controls > #zoom-in-button {
|
||||
|
||||
#appMenu-new-window-button {
|
||||
list-style-image: url(chrome://browser/skin/menu-icons/new-window.svg);
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
||||
#appMenu-private-window-button {
|
||||
list-style-image: url(chrome://browser/skin/menu-icons/private-window.svg);
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
||||
#appMenu-print-button {
|
||||
list-style-image: url(chrome://browser/skin/menu-icons/print.svg);
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
@ -1509,7 +1509,7 @@ html|span.ac-emphasize-text-url {
|
||||
.ac-type-icon[type=keyword],
|
||||
.ac-site-icon[type=searchengine] {
|
||||
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg);
|
||||
/* uncomment after bug 1350010 lands: context-properties: fill; */
|
||||
-moz-context-properties: fill;
|
||||
fill: GrayText;
|
||||
}
|
||||
|
||||
|
20
build/cargo-linker
Executable file
20
build/cargo-linker
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# If you want to use a custom linker with Cargo, Cargo requires that you
|
||||
# specify it in Cargo.toml or via the matching environment variable.
|
||||
# Passing extra options to the linker is possible with Cargo via
|
||||
# RUSTFLAGS='-C link-args', but testing showed that doing this reliably
|
||||
# was difficult.
|
||||
#
|
||||
# Our solution to these problems is to use this wrapper script. We pass
|
||||
# in the LD and the LDFLAGS to use via environment variables. Note that
|
||||
# we do *not* quote either MOZ_CARGO_WRAP variable:
|
||||
#
|
||||
# * MOZ_CARGO_WRAP_LD is equivalent to CC on Unix-y platforms, and CC
|
||||
# frequently has additional arguments in addition to the compiler
|
||||
# itself.
|
||||
# * MOZ_CARGO_WRAP_LDFLAGS contains space-separated arguments to pass,
|
||||
# and not quoting it ensures that either of those arguments is passed
|
||||
# as a separate argument to the actual LD.
|
||||
|
||||
${MOZ_CARGO_WRAP_LD} ${MOZ_CARGO_WRAP_LDFLAGS} "$@"
|
@ -223,6 +223,15 @@ rust_host_triple = rust_triple_alias(host)
|
||||
set_config('RUST_TARGET', rust_target_triple)
|
||||
set_config('RUST_HOST_TARGET', rust_host_triple)
|
||||
|
||||
@depends(rust_target_triple)
|
||||
def rust_target_env_name(triple):
|
||||
return triple.upper().replace('-','_')
|
||||
|
||||
# We need this to form various Cargo environment variables, as there is no
|
||||
# uppercase function in make, and we don't want to shell out just for
|
||||
# converting a string to uppercase.
|
||||
set_config('RUST_TARGET_ENV_NAME', rust_target_env_name)
|
||||
|
||||
# Until we remove all the other Rust checks in old-configure.
|
||||
add_old_configure_assignment('MOZ_RUST', rust_compiler)
|
||||
add_old_configure_assignment('RUSTC', rustc)
|
||||
|
@ -963,7 +963,15 @@ else
|
||||
environment_cleaner =
|
||||
endif
|
||||
|
||||
CARGO_BUILD = env $(environment_cleaner) $(rustflags_override) \
|
||||
# This function is intended to be called by:
|
||||
#
|
||||
# $(call CARGO_BUILD,EXTRA_ENV_VAR1=X EXTRA_ENV_VAR2=Y ...)
|
||||
#
|
||||
# but, given the idiosyncracies of make, can also be called without arguments:
|
||||
#
|
||||
# $(call CARGO_BUILD)
|
||||
define CARGO_BUILD
|
||||
env $(environment_cleaner) $(rustflags_override) \
|
||||
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \
|
||||
RUSTC=$(RUSTC) \
|
||||
MOZ_DIST=$(ABS_DIST) \
|
||||
@ -972,7 +980,29 @@ CARGO_BUILD = env $(environment_cleaner) $(rustflags_override) \
|
||||
PKG_CONFIG_ALLOW_CROSS=1 \
|
||||
RUST_BACKTRACE=1 \
|
||||
MOZ_TOPOBJDIR=$(topobjdir) \
|
||||
$(1) \
|
||||
$(CARGO) build $(cargo_build_flags)
|
||||
endef
|
||||
|
||||
cargo_linker_env_var := CARGO_TARGET_$(RUST_TARGET_ENV_NAME)_LINKER
|
||||
|
||||
# Don't define a custom linker on Windows, as it's difficult to have a
|
||||
# non-binary file that will get executed correctly by Cargo. We don't
|
||||
# have to worry about a cross-compiling (besides x86-64 -> x86, which
|
||||
# already works with the current setup) setup on Windows, and we don't
|
||||
# have to pass in any special linker options on Windows.
|
||||
ifneq (WINNT,$(OS_ARCH))
|
||||
|
||||
# Defining all of this for ASan builds results in crashes while running
|
||||
# some crates's build scripts (!), so disable it for now.
|
||||
ifndef MOZ_ASAN
|
||||
target_cargo_env_vars := \
|
||||
MOZ_CARGO_WRAP_LDFLAGS="$(LDFLAGS)" \
|
||||
MOZ_CARGO_WRAP_LD="$(CC)" \
|
||||
$(cargo_linker_env_var)=$(topsrcdir)/build/cargo-linker
|
||||
endif # MOZ_ASAN
|
||||
|
||||
endif # ifneq WINNT
|
||||
|
||||
ifdef RUST_LIBRARY_FILE
|
||||
|
||||
@ -987,7 +1017,7 @@ endif
|
||||
# build.
|
||||
force-cargo-library-build:
|
||||
$(REPORT_BUILD)
|
||||
$(CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag)
|
||||
$(call CARGO_BUILD,$(target_cargo_env_vars)) --lib $(cargo_target_flag) $(rust_features_flag)
|
||||
|
||||
$(RUST_LIBRARY_FILE): force-cargo-library-build
|
||||
endif # RUST_LIBRARY_FILE
|
||||
@ -1000,7 +1030,7 @@ endif
|
||||
|
||||
force-cargo-host-library-build:
|
||||
$(REPORT_BUILD)
|
||||
$(CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
|
||||
$(call CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
|
||||
|
||||
$(HOST_RUST_LIBRARY_FILE): force-cargo-host-library-build
|
||||
endif # HOST_RUST_LIBRARY_FILE
|
||||
@ -1008,14 +1038,14 @@ endif # HOST_RUST_LIBRARY_FILE
|
||||
ifdef RUST_PROGRAMS
|
||||
force-cargo-program-build:
|
||||
$(REPORT_BUILD)
|
||||
$(CARGO_BUILD) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
|
||||
$(call CARGO_BUILD,$(target_cargo_env_vars)) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
|
||||
|
||||
$(RUST_PROGRAMS): force-cargo-program-build
|
||||
endif # RUST_PROGRAMS
|
||||
ifdef HOST_RUST_PROGRAMS
|
||||
force-cargo-host-program-build:
|
||||
$(REPORT_BUILD)
|
||||
$(CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)
|
||||
$(call CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)
|
||||
|
||||
$(HOST_RUST_PROGRAMS): force-cargo-host-program-build
|
||||
endif # HOST_RUST_PROGRAMS
|
||||
|
@ -83,7 +83,7 @@ select {
|
||||
-moz-appearance: none; appearance: none;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-image: var(--viewport-selection-arrow);
|
||||
/* uncomment after bug 1350010 lands: context-properties: fill; */
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
color: var(--viewport-color);
|
||||
background-position: 100% 50%;
|
||||
|
@ -1519,9 +1519,9 @@ function getFontPreviewData(font, doc, options) {
|
||||
// Get the correct preview text measurements and set the canvas dimensions
|
||||
ctx.font = fontValue;
|
||||
ctx.fillStyle = fillStyle;
|
||||
let textWidth = ctx.measureText(previewText).width;
|
||||
let textWidth = Math.round(ctx.measureText(previewText).width);
|
||||
|
||||
canvas.width = textWidth * 2 + FONT_PREVIEW_OFFSET * 2;
|
||||
canvas.width = textWidth * 2 + FONT_PREVIEW_OFFSET * 4;
|
||||
canvas.height = previewFontSize * 3;
|
||||
|
||||
// we have to reset these after changing the canvas size
|
||||
|
@ -9,6 +9,7 @@ support-files =
|
||||
doc_force_gc.html
|
||||
doc_innerHTML.html
|
||||
doc_perf.html
|
||||
grid.html
|
||||
inspectedwindow-reload-target.sjs
|
||||
navigate-first.html
|
||||
navigate-second.html
|
||||
@ -53,6 +54,8 @@ skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still di
|
||||
skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still disabled in E10S
|
||||
[browser_canvasframe_helper_06.js]
|
||||
skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still disabled in E10S
|
||||
[browser_layout_getAllGrids.js]
|
||||
[browser_layout_simple.js]
|
||||
[browser_markers-cycle-collection.js]
|
||||
[browser_markers-docloading-01.js]
|
||||
[browser_markers-docloading-02.js]
|
||||
@ -91,4 +94,4 @@ skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still di
|
||||
[browser_timeline_actors.js]
|
||||
[browser_timeline_iframes.js]
|
||||
[browser_register_actor.js]
|
||||
[browser_webextension_inspected_window.js]
|
||||
[browser_webextension_inspected_window.js]
|
||||
|
133
devtools/server/tests/browser/browser_layout_getAllGrids.js
Normal file
133
devtools/server/tests/browser/browser_layout_getAllGrids.js
Normal file
@ -0,0 +1,133 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check the output of getAllGrids for the LayoutActor
|
||||
|
||||
const GRID_FRAGMENT_DATA = {
|
||||
areas: [
|
||||
{
|
||||
columnEnd: 3,
|
||||
columnStart: 2,
|
||||
name: "header",
|
||||
rowEnd: 2,
|
||||
rowStart: 1,
|
||||
type: "explicit"
|
||||
},
|
||||
{
|
||||
columnEnd: 2,
|
||||
columnStart: 1,
|
||||
name: "sidebar",
|
||||
rowEnd: 3,
|
||||
rowStart: 2,
|
||||
type: "explicit"
|
||||
},
|
||||
{
|
||||
columnEnd: 3,
|
||||
columnStart: 2,
|
||||
name: "content",
|
||||
rowEnd: 3,
|
||||
rowStart: 2,
|
||||
type: "explicit"
|
||||
}
|
||||
],
|
||||
cols: {
|
||||
lines: [
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["col-1", "col-start-1", "sidebar-start"],
|
||||
number: 1,
|
||||
start: 0
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["col-2", "header-start", "sidebar-end", "content-start"],
|
||||
number: 2,
|
||||
start: 100
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["header-end", "content-end"],
|
||||
number: 3,
|
||||
start: 200
|
||||
}
|
||||
],
|
||||
tracks: [
|
||||
{
|
||||
breadth: 100,
|
||||
start: 0,
|
||||
state: "static",
|
||||
type: "explicit"
|
||||
},
|
||||
{
|
||||
breadth: 100,
|
||||
start: 100,
|
||||
state: "static",
|
||||
type: "explicit"
|
||||
}
|
||||
]
|
||||
},
|
||||
rows: {
|
||||
lines: [
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["header-start"],
|
||||
number: 1,
|
||||
start: 0
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["header-end", "sidebar-start", "content-start"],
|
||||
number: 2,
|
||||
start: 100
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["sidebar-end", "content-end"],
|
||||
number: 3,
|
||||
start: 200
|
||||
}
|
||||
],
|
||||
tracks: [
|
||||
{
|
||||
breadth: 100,
|
||||
start: 0,
|
||||
state: "static",
|
||||
type: "explicit"
|
||||
},
|
||||
{
|
||||
breadth: 100,
|
||||
start: 100,
|
||||
state: "static",
|
||||
type: "explicit"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
add_task(function* () {
|
||||
let { client, walker, layout } = yield initLayoutFrontForUrl(MAIN_DOMAIN + "grid.html");
|
||||
let grids = yield layout.getAllGrids(walker.rootNode, true);
|
||||
let grid = grids[0];
|
||||
let { gridFragments } = grid;
|
||||
|
||||
is(grids.length, 1, "One grid was returned.");
|
||||
is(gridFragments.length, 1, "One grid fragment was returned.");
|
||||
ok(Array.isArray(gridFragments), "An array of grid fragments was returned.");
|
||||
Assert.deepEqual(gridFragments[0], GRID_FRAGMENT_DATA,
|
||||
"Got the correct grid fragment data.");
|
||||
|
||||
info("Get the grid container node front.");
|
||||
|
||||
try {
|
||||
let nodeFront = yield walker.getNodeFromActor(grids[0].actorID, ["containerEl"]);
|
||||
ok(nodeFront, "Got the grid container node front.");
|
||||
} catch (e) {
|
||||
ok(false, "Did not get grid container node front.");
|
||||
}
|
||||
|
||||
yield client.close();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
39
devtools/server/tests/browser/browser_layout_simple.js
Normal file
39
devtools/server/tests/browser/browser_layout_simple.js
Normal file
@ -0,0 +1,39 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Simple checks for the LayoutActor and GridActor
|
||||
|
||||
add_task(function* () {
|
||||
let {client, walker, layout} = yield initLayoutFrontForUrl(
|
||||
"data:text/html;charset=utf-8,<title>test</title><div></div>");
|
||||
|
||||
ok(layout, "The LayoutFront was created");
|
||||
ok(layout.getAllGrids, "The getAllGrids method exists");
|
||||
|
||||
let didThrow = false;
|
||||
try {
|
||||
yield layout.getGrids(null);
|
||||
} catch (e) {
|
||||
didThrow = true;
|
||||
}
|
||||
ok(didThrow, "An exception was thrown for a missing NodeActor in getGrids");
|
||||
|
||||
didThrow = false;
|
||||
try {
|
||||
yield layout.getAllGrids(null);
|
||||
} catch (e) {
|
||||
didThrow = true;
|
||||
}
|
||||
ok(didThrow, "An exception was thrown for a missing NodeActor in getAllGrids");
|
||||
|
||||
let invalidNode = yield walker.querySelector(walker.rootNode, "title");
|
||||
let grids = yield layout.getAllGrids(invalidNode, true);
|
||||
ok(Array.isArray(grids), "An array of grids was returned");
|
||||
is(grids.length, 0, "0 grids have been returned for the invalid node");
|
||||
|
||||
yield client.close();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
42
devtools/server/tests/browser/grid.html
Normal file
42
devtools/server/tests/browser/grid.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Grid test page</title>
|
||||
<style type='text/css'>
|
||||
#grid {
|
||||
display: grid;
|
||||
grid-template-columns: [col-1 col-start-1] 100px [col-2] 100px;
|
||||
grid-template-rows: 100px 100px;
|
||||
grid-template-areas: ". header"
|
||||
"sidebar content";
|
||||
}
|
||||
#cell1 {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
#cell2 {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
#cell3 {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
#cell4 {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="grid">
|
||||
<div id="cell1">cell1</div>
|
||||
<div id="cell2">cell2</div>
|
||||
<div id="cell3">cell3</div>
|
||||
<div id="cell4">cell4</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -65,6 +65,21 @@ function* initAnimationsFrontForUrl(url) {
|
||||
return {inspector, walker, animations, client};
|
||||
}
|
||||
|
||||
function* initLayoutFrontForUrl(url) {
|
||||
const {InspectorFront} = require("devtools/shared/fronts/inspector");
|
||||
|
||||
yield addTab(url);
|
||||
|
||||
initDebuggerServer();
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
let form = yield connectDebuggerClient(client);
|
||||
let inspector = InspectorFront(client, form);
|
||||
let walker = yield inspector.getWalker();
|
||||
let layout = yield walker.getLayoutInspector();
|
||||
|
||||
return {inspector, walker, layout, client};
|
||||
}
|
||||
|
||||
function initDebuggerServer() {
|
||||
try {
|
||||
// Sometimes debugger server does not get destroyed correctly by previous
|
||||
|
@ -925,6 +925,18 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"-moz-context-properties": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"-moz-context-properties"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"-moz-control-character-visibility": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@ -2941,6 +2953,7 @@ exports.CSS_PROPERTIES = {
|
||||
"column-width",
|
||||
"contain",
|
||||
"content",
|
||||
"-moz-context-properties",
|
||||
"-moz-control-character-visibility",
|
||||
"counter-increment",
|
||||
"counter-reset",
|
||||
@ -3370,6 +3383,7 @@ exports.CSS_PROPERTIES = {
|
||||
"geometricprecision",
|
||||
"grab",
|
||||
"grabbing",
|
||||
"grayscale",
|
||||
"grid",
|
||||
"groove",
|
||||
"groupbox",
|
||||
|
@ -1116,7 +1116,7 @@ protected:
|
||||
static nsGlobalWindow* GetOuterWindow(JSObject *proxy)
|
||||
{
|
||||
nsGlobalWindow* outerWindow = nsGlobalWindow::FromSupports(
|
||||
static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate()));
|
||||
static_cast<nsISupports*>(js::GetProxyReservedSlot(proxy, 0).toPrivate()));
|
||||
MOZ_ASSERT_IF(outerWindow, outerWindow->IsOuterWindow());
|
||||
return outerWindow;
|
||||
}
|
||||
@ -1738,7 +1738,7 @@ nsGlobalWindow::~nsGlobalWindow()
|
||||
if (IsOuterWindow()) {
|
||||
JSObject *proxy = GetWrapperMaybeDead();
|
||||
if (proxy) {
|
||||
js::SetProxyExtra(proxy, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyReservedSlot(proxy, 0, js::PrivateValue(nullptr));
|
||||
}
|
||||
|
||||
// An outer window is destroyed with inner windows still possibly
|
||||
@ -3160,7 +3160,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
|
||||
NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE);
|
||||
|
||||
js::SetProxyExtra(outer, 0, js::PrivateValue(ToSupports(this)));
|
||||
js::SetProxyReservedSlot(outer, 0, js::PrivateValue(ToSupports(this)));
|
||||
|
||||
// Inform the nsJSContext, which is the canonical holder of the outer.
|
||||
mContext->SetWindowProxy(outer);
|
||||
@ -3178,8 +3178,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, GetWrapperPreserveColor());
|
||||
|
||||
js::SetProxyExtra(obj, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyExtra(outerObject, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyReservedSlot(obj, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(nullptr));
|
||||
|
||||
outerObject = xpc::TransplantObject(cx, obj, outerObject);
|
||||
if (!outerObject) {
|
||||
@ -3187,7 +3187,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
js::SetProxyExtra(outerObject, 0, js::PrivateValue(ToSupports(this)));
|
||||
js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(ToSupports(this)));
|
||||
|
||||
SetWrapper(outerObject);
|
||||
|
||||
|
@ -2205,9 +2205,9 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg)
|
||||
// NB: It's important to do this _after_ copying the properties to
|
||||
// propertyHolder. Otherwise, an object with |foo.x === foo| will
|
||||
// crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
|
||||
js::SetReservedOrProxyPrivateSlot(newobj, DOM_OBJECT_SLOT,
|
||||
js::GetReservedOrProxyPrivateSlot(aObj, DOM_OBJECT_SLOT));
|
||||
js::SetReservedOrProxyPrivateSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
js::SetReservedSlot(newobj, DOM_OBJECT_SLOT,
|
||||
js::GetReservedSlot(aObj, DOM_OBJECT_SLOT));
|
||||
js::SetReservedSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
|
||||
aObj = xpc::TransplantObject(aCx, aObj, newobj);
|
||||
if (!aObj) {
|
||||
|
@ -135,7 +135,7 @@ UnwrapDOMObject(JSObject* obj)
|
||||
MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
|
||||
"Don't pass non-DOM objects to this function");
|
||||
|
||||
JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
|
||||
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
|
||||
return static_cast<T*>(val.toPrivate());
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ UnwrapPossiblyNotInitializedDOMObject(JSObject* obj)
|
||||
MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
|
||||
"Don't pass non-DOM objects to this function");
|
||||
|
||||
JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
|
||||
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
|
||||
if (val.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2679,8 +2679,7 @@ public:
|
||||
~BindingJSObjectCreator()
|
||||
{
|
||||
if (mReflector) {
|
||||
js::SetReservedOrProxyPrivateSlot(mReflector, DOM_OBJECT_SLOT,
|
||||
JS::UndefinedValue());
|
||||
js::SetReservedSlot(mReflector, DOM_OBJECT_SLOT, JS::UndefinedValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2688,14 +2687,15 @@ public:
|
||||
CreateProxyObject(JSContext* aCx, const js::Class* aClass,
|
||||
const DOMProxyHandler* aHandler,
|
||||
JS::Handle<JSObject*> aProto, T* aNative,
|
||||
JS::Handle<JS::Value> aExpandoValue,
|
||||
JS::MutableHandle<JSObject*> aReflector)
|
||||
{
|
||||
js::ProxyOptions options;
|
||||
options.setClass(aClass);
|
||||
JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
|
||||
aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
|
||||
aReflector.set(js::NewProxyObject(aCx, aHandler, aExpandoValue, aProto,
|
||||
options));
|
||||
if (aReflector) {
|
||||
js::SetProxyReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
|
||||
mNative = aNative;
|
||||
mReflector = aReflector;
|
||||
}
|
||||
|
@ -3499,21 +3499,21 @@ def CreateBindingJSObject(descriptor, properties):
|
||||
# We don't always need to root obj, but there are a variety
|
||||
# of cases where we do, so for simplicity, just always root it.
|
||||
if descriptor.proxy:
|
||||
create = dedent(
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
expandoValue = "JS::PrivateValue(&aObject->mExpandoAndGeneration)"
|
||||
else:
|
||||
expandoValue = "JS::UndefinedValue()"
|
||||
create = fill(
|
||||
"""
|
||||
JS::Rooted<JS::Value> expandoValue(aCx, ${expandoValue});
|
||||
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
|
||||
proto, aObject, aReflector);
|
||||
proto, aObject, expandoValue, aReflector);
|
||||
if (!aReflector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
""")
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
create += dedent("""
|
||||
js::SetProxyExtra(aReflector, JSPROXYSLOT_EXPANDO,
|
||||
JS::PrivateValue(&aObject->mExpandoAndGeneration));
|
||||
|
||||
""")
|
||||
""",
|
||||
expandoValue=expandoValue)
|
||||
else:
|
||||
create = dedent(
|
||||
"""
|
||||
@ -11507,7 +11507,7 @@ class CGProxyUnwrap(CGAbstractMethod):
|
||||
obj = js::UncheckedUnwrap(obj);
|
||||
}
|
||||
MOZ_ASSERT(IsProxy(obj));
|
||||
return static_cast<${type}*>(js::GetProxyPrivate(obj).toPrivate());
|
||||
return static_cast<${type}*>(js::GetProxyReservedSlot(obj, DOM_OBJECT_SLOT).toPrivate());
|
||||
""",
|
||||
type=self.descriptor.nativeType)
|
||||
|
||||
|
@ -34,7 +34,7 @@ js::DOMProxyShadowsResult
|
||||
DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
|
||||
{
|
||||
JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
|
||||
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(proxy);
|
||||
bool isOverrideBuiltins = !v.isObject() && !v.isUndefined();
|
||||
if (expando) {
|
||||
bool hasOwn;
|
||||
@ -64,7 +64,7 @@ struct SetDOMProxyInformation
|
||||
{
|
||||
SetDOMProxyInformation() {
|
||||
js::SetDOMProxyInformation((const void*) &DOMProxyHandler::family,
|
||||
JSPROXYSLOT_EXPANDO, DOMProxyShadows);
|
||||
DOMProxyShadows);
|
||||
}
|
||||
};
|
||||
|
||||
@ -75,7 +75,7 @@ void
|
||||
DOMProxyHandler::ClearExternalRefsForWrapperRelease(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
if (v.isUndefined()) {
|
||||
// No expando.
|
||||
return;
|
||||
@ -102,13 +102,13 @@ JSObject*
|
||||
DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
if (v.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (v.isObject()) {
|
||||
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue());
|
||||
js::SetProxyPrivate(obj, UndefinedValue());
|
||||
xpc::ObjectScope(obj)->RemoveDOMExpandoObject(obj);
|
||||
} else {
|
||||
js::ExpandoAndGeneration* expandoAndGeneration =
|
||||
@ -142,7 +142,7 @@ JSObject*
|
||||
DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
{
|
||||
NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
if (v.isObject()) {
|
||||
return &v.toObject();
|
||||
}
|
||||
@ -178,7 +178,7 @@ DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
}
|
||||
|
||||
cache->SetPreservingWrapper(true);
|
||||
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
|
||||
js::SetProxyPrivate(obj, ObjectValue(*expando));
|
||||
|
||||
return expando;
|
||||
}
|
||||
@ -322,7 +322,7 @@ JSObject *
|
||||
DOMProxyHandler::GetExpandoObject(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
if (v.isObject()) {
|
||||
return &v.toObject();
|
||||
}
|
||||
@ -343,14 +343,12 @@ ShadowingDOMProxyHandler::trace(JSTracer* trc, JSObject* proxy) const
|
||||
DOMProxyHandler::trace(trc, proxy);
|
||||
|
||||
MOZ_ASSERT(IsDOMProxy(proxy), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
|
||||
JS::Value v = js::GetProxyPrivate(proxy);
|
||||
MOZ_ASSERT(!v.isObject(), "Should not have expando object directly!");
|
||||
|
||||
if (v.isUndefined()) {
|
||||
// This can happen if we GC while creating our object, before we get a
|
||||
// chance to set up its JSPROXYSLOT_EXPANDO slot.
|
||||
return;
|
||||
}
|
||||
// The proxy's private slot is set when we allocate the proxy,
|
||||
// so it cannot be |undefined|.
|
||||
MOZ_ASSERT(!v.isUndefined());
|
||||
|
||||
js::ExpandoAndGeneration* expandoAndGeneration =
|
||||
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
||||
|
@ -14,35 +14,29 @@
|
||||
#include "js/Proxy.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
enum {
|
||||
/**
|
||||
* DOM proxies have an extra slot for the expando object at index
|
||||
* JSPROXYSLOT_EXPANDO.
|
||||
*
|
||||
* The expando object is a plain JSObject whose properties correspond to
|
||||
* "expandos" (custom properties set by the script author).
|
||||
*
|
||||
* The exact value stored in the JSPROXYSLOT_EXPANDO slot depends on whether
|
||||
* the interface is annotated with the [OverrideBuiltins] extended attribute.
|
||||
*
|
||||
* If it is, the proxy is initialized with a PrivateValue, which contains a
|
||||
* pointer to a js::ExpandoAndGeneration object; this contains a pointer to
|
||||
* the actual expando object as well as the "generation" of the object. The
|
||||
* proxy handler will trace the expando object stored in the
|
||||
* js::ExpandoAndGeneration while the proxy itself is alive.
|
||||
*
|
||||
* If it is not, the proxy is initialized with an UndefinedValue. In
|
||||
* EnsureExpandoObject, it is set to an ObjectValue that points to the
|
||||
* expando object directly. (It is set back to an UndefinedValue only when
|
||||
* the object is about to die.)
|
||||
*/
|
||||
JSPROXYSLOT_EXPANDO = 0
|
||||
};
|
||||
/**
|
||||
* DOM proxies store the expando object in the private slot.
|
||||
*
|
||||
* The expando object is a plain JSObject whose properties correspond to
|
||||
* "expandos" (custom properties set by the script author).
|
||||
*
|
||||
* The exact value stored in the proxy's private slot depends on whether the
|
||||
* interface is annotated with the [OverrideBuiltins] extended attribute.
|
||||
*
|
||||
* If it is, the proxy is initialized with a PrivateValue, which contains a
|
||||
* pointer to a js::ExpandoAndGeneration object; this contains a pointer to
|
||||
* the actual expando object as well as the "generation" of the object. The
|
||||
* proxy handler will trace the expando object stored in the
|
||||
* js::ExpandoAndGeneration while the proxy itself is alive.
|
||||
*
|
||||
* If it is not, the proxy is initialized with an UndefinedValue. In
|
||||
* EnsureExpandoObject, it is set to an ObjectValue that points to the
|
||||
* expando object directly. (It is set back to an UndefinedValue only when
|
||||
* the object is about to die.)
|
||||
*/
|
||||
|
||||
template<typename T> struct Prefable;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/ErrorNames.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -9468,6 +9469,7 @@ class Maintenance final
|
||||
RefPtr<DirectoryLock> mDirectoryLock;
|
||||
nsTArray<DirectoryInfo> mDirectoryInfos;
|
||||
nsDataHashtable<nsStringHashKey, DatabaseMaintenance*> mDatabaseMaintenances;
|
||||
nsresult mResultCode;
|
||||
Atomic<bool> mAborted;
|
||||
State mState;
|
||||
|
||||
@ -9475,6 +9477,7 @@ public:
|
||||
explicit Maintenance(QuotaClient* aQuotaClient)
|
||||
: mQuotaClient(aQuotaClient)
|
||||
, mStartTime(PR_Now())
|
||||
, mResultCode(NS_OK)
|
||||
, mAborted(false)
|
||||
, mState(State::Initial)
|
||||
{
|
||||
@ -18638,21 +18641,32 @@ Maintenance::DirectoryWork()
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(quotaManager->EnsureStorageIsInitialized()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
nsresult rv = quotaManager->EnsureStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> storageDir = GetFileForPath(quotaManager->GetStoragePath());
|
||||
MOZ_ASSERT(storageDir);
|
||||
if (NS_WARN_IF(!storageDir)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool exists;
|
||||
MOZ_ALWAYS_SUCCEEDS(storageDir->Exists(&exists));
|
||||
rv = storageDir->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool isDirectory;
|
||||
MOZ_ALWAYS_SUCCEEDS(storageDir->IsDirectory(&isDirectory));
|
||||
rv = storageDir->IsDirectory(&isDirectory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!isDirectory)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -18687,25 +18701,41 @@ Maintenance::DirectoryWork()
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> persistenceDir;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
storageDir->Clone(getter_AddRefs(persistenceDir)));
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
persistenceDir->Append(NS_ConvertASCIItoUTF16(persistenceTypeString)));
|
||||
rv = storageDir->Clone(getter_AddRefs(persistenceDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = persistenceDir->Append(NS_ConvertASCIItoUTF16(persistenceTypeString));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = persistenceDir->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(persistenceDir->Exists(&exists));
|
||||
if (!exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(persistenceDir->IsDirectory(&isDirectory));
|
||||
rv = persistenceDir->IsDirectory(&isDirectory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!isDirectory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> persistenceDirEntries;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
persistenceDir->GetDirectoryEntries(
|
||||
getter_AddRefs(persistenceDirEntries)));
|
||||
rv = persistenceDir->GetDirectoryEntries(
|
||||
getter_AddRefs(persistenceDirEntries));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!persistenceDirEntries) {
|
||||
continue;
|
||||
}
|
||||
@ -18717,46 +18747,76 @@ Maintenance::DirectoryWork()
|
||||
}
|
||||
|
||||
bool persistenceDirHasMoreEntries;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
persistenceDirEntries->HasMoreElements(&persistenceDirHasMoreEntries));
|
||||
rv = persistenceDirEntries->HasMoreElements(
|
||||
&persistenceDirHasMoreEntries);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!persistenceDirHasMoreEntries) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> persistenceDirEntry;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
persistenceDirEntries->GetNext(getter_AddRefs(persistenceDirEntry)));
|
||||
rv = persistenceDirEntries->GetNext(getter_AddRefs(persistenceDirEntry));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> originDir = do_QueryInterface(persistenceDirEntry);
|
||||
MOZ_ASSERT(originDir);
|
||||
|
||||
MOZ_ASSERT(NS_SUCCEEDED(originDir->Exists(&exists)));
|
||||
rv = originDir->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(exists);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(originDir->IsDirectory(&isDirectory));
|
||||
rv = originDir->IsDirectory(&isDirectory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!isDirectory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> idbDir;
|
||||
MOZ_ALWAYS_SUCCEEDS(originDir->Clone(getter_AddRefs(idbDir)));
|
||||
rv = originDir->Clone(getter_AddRefs(idbDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(idbDir->Append(idbDirName));
|
||||
rv = idbDir->Append(idbDirName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = idbDir->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(idbDir->Exists(&exists));
|
||||
if (!exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(idbDir->IsDirectory(&isDirectory));
|
||||
rv = idbDir->IsDirectory(&isDirectory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!isDirectory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> idbDirEntries;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
idbDir->GetDirectoryEntries(getter_AddRefs(idbDirEntries)));
|
||||
rv = idbDir->GetDirectoryEntries(getter_AddRefs(idbDirEntries));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!idbDirEntries) {
|
||||
continue;
|
||||
}
|
||||
@ -18772,31 +18832,46 @@ Maintenance::DirectoryWork()
|
||||
}
|
||||
|
||||
bool idbDirHasMoreEntries;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
idbDirEntries->HasMoreElements(&idbDirHasMoreEntries));
|
||||
rv = idbDirEntries->HasMoreElements(&idbDirHasMoreEntries);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!idbDirHasMoreEntries) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> idbDirEntry;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
idbDirEntries->GetNext(getter_AddRefs(idbDirEntry)));
|
||||
rv = idbDirEntries->GetNext(getter_AddRefs(idbDirEntry));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> idbDirFile = do_QueryInterface(idbDirEntry);
|
||||
MOZ_ASSERT(idbDirFile);
|
||||
|
||||
nsString idbFilePath;
|
||||
MOZ_ALWAYS_SUCCEEDS(idbDirFile->GetPath(idbFilePath));
|
||||
rv = idbDirFile->GetPath(idbFilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!StringEndsWith(idbFilePath, sqliteExtension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_SUCCEEDED(idbDirFile->Exists(&exists)));
|
||||
rv = idbDirFile->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(exists);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(idbDirFile->IsDirectory(&isDirectory));
|
||||
rv = idbDirFile->IsDirectory(&isDirectory);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (isDirectory) {
|
||||
continue;
|
||||
}
|
||||
@ -18925,8 +19000,19 @@ Maintenance::Finish()
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State::Finishing);
|
||||
|
||||
if (NS_FAILED(mResultCode)) {
|
||||
nsCString errorName;
|
||||
GetErrorName(mResultCode, errorName);
|
||||
|
||||
IDB_WARNING("Maintenance finished with error: %s", errorName.get());
|
||||
}
|
||||
|
||||
mDirectoryLock = nullptr;
|
||||
|
||||
// It can happen that we are only referenced by mCurrentMaintenance which is
|
||||
// cleared in NoteFinishedMaintenance()
|
||||
RefPtr<Maintenance> kungFuDeathGrip = this;
|
||||
|
||||
mQuotaClient->NoteFinishedMaintenance(this);
|
||||
|
||||
mState = State::Complete;
|
||||
@ -18971,6 +19057,10 @@ Maintenance::Run()
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) && mState != State::Finishing) {
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mResultCode = rv;
|
||||
}
|
||||
|
||||
// Must set mState before dispatching otherwise we will race with the owning
|
||||
// thread.
|
||||
mState = State::Finishing;
|
||||
@ -18997,6 +19087,10 @@ Maintenance::DirectoryLockAcquired(DirectoryLock* aLock)
|
||||
|
||||
nsresult rv = DirectoryOpen();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mResultCode = rv;
|
||||
}
|
||||
|
||||
mState = State::Finishing;
|
||||
Finish();
|
||||
|
||||
@ -19011,6 +19105,10 @@ Maintenance::DirectoryLockFailed()
|
||||
MOZ_ASSERT(mState == State::DirectoryOpenPending);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mResultCode = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mState = State::Finishing;
|
||||
Finish();
|
||||
}
|
||||
|
@ -11,9 +11,12 @@
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#define IDB_WARNING(x) \
|
||||
mozilla::dom::indexedDB::ReportInternalError(__FILE__, __LINE__, x); \
|
||||
NS_WARNING(x)
|
||||
#define IDB_WARNING(...) \
|
||||
do { \
|
||||
nsPrintfCString s(__VA_ARGS__); \
|
||||
mozilla::dom::indexedDB::ReportInternalError(__FILE__, __LINE__, s.get()); \
|
||||
NS_WARNING(s.get()); \
|
||||
} while (0)
|
||||
|
||||
#define IDB_REPORT_INTERNAL_ERR() \
|
||||
mozilla::dom::indexedDB::ReportInternalError(__FILE__, __LINE__, \
|
||||
|
@ -5055,10 +5055,9 @@ ContentParent::ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentParent::TransmitPermissionsFor(nsIChannel* aChannel)
|
||||
ContentParent::AboutToLoadDocumentForChild(nsIChannel* aChannel)
|
||||
{
|
||||
MOZ_ASSERT(aChannel);
|
||||
#ifdef MOZ_PERMISSIONS
|
||||
|
||||
nsresult rv;
|
||||
if (!aChannel->IsDocument()) {
|
||||
@ -5078,7 +5077,6 @@ ContentParent::TransmitPermissionsFor(nsIChannel* aChannel)
|
||||
|
||||
rv = TransmitPermissionsForPrincipal(principal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -652,7 +652,11 @@ public:
|
||||
// Use the PHangMonitor channel to ask the child to repaint a tab.
|
||||
void ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch);
|
||||
|
||||
nsresult TransmitPermissionsFor(nsIChannel* aChannel);
|
||||
// This function is called when we are about to load a document from an
|
||||
// HTTP(S), FTP or wyciwyg channel for a content process. It is a useful
|
||||
// place to start to kick off work as early as possible in response to such
|
||||
// document loads.
|
||||
nsresult AboutToLoadDocumentForChild(nsIChannel* aChannel);
|
||||
|
||||
nsresult TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
|
@ -46,6 +46,7 @@ AndroidDynamicToolbarAnimator::AndroidDynamicToolbarAnimator()
|
||||
, mControllerDragThresholdReached(false)
|
||||
, mControllerCancelTouchTracking(false)
|
||||
, mControllerDragChangedDirection(false)
|
||||
, mControllerResetOnNextMove(false)
|
||||
, mControllerStartTouch(0)
|
||||
, mControllerPreviousTouch(0)
|
||||
, mControllerTotalDistance(0)
|
||||
@ -54,6 +55,7 @@ AndroidDynamicToolbarAnimator::AndroidDynamicToolbarAnimator()
|
||||
, mControllerSurfaceHeight(0)
|
||||
, mControllerCompositionHeight(0)
|
||||
, mControllerLastDragDirection(0)
|
||||
, mControllerTouchCount(0)
|
||||
, mControllerLastEventTimeStamp(0)
|
||||
, mControllerState(eNothingPending)
|
||||
// Compositor thread only
|
||||
@ -102,6 +104,22 @@ AndroidDynamicToolbarAnimator::ReceiveInputEvent(InputData& aEvent)
|
||||
MultiTouchInput& multiTouch = aEvent.AsMultiTouchInput();
|
||||
ScreenIntCoord currentTouch = 0;
|
||||
|
||||
switch (multiTouch.mType) {
|
||||
case MultiTouchInput::MULTITOUCH_START:
|
||||
mControllerTouchCount = multiTouch.mTouches.Length();
|
||||
break;
|
||||
case MultiTouchInput::MULTITOUCH_END:
|
||||
case MultiTouchInput::MULTITOUCH_CANCEL:
|
||||
mControllerTouchCount -= multiTouch.mTouches.Length();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mControllerTouchCount > 1) {
|
||||
mControllerResetOnNextMove = true;
|
||||
}
|
||||
|
||||
if (mPinnedFlags || !GetTouchY(multiTouch, ¤tTouch)) {
|
||||
TranslateTouchEvent(multiTouch);
|
||||
return nsEventStatus_eIgnore;
|
||||
@ -121,6 +139,8 @@ AndroidDynamicToolbarAnimator::ReceiveInputEvent(InputData& aEvent)
|
||||
}
|
||||
break;
|
||||
case MultiTouchInput::MULTITOUCH_MOVE: {
|
||||
CheckForResetOnNextMove(currentTouch);
|
||||
|
||||
if ((mControllerState != eAnimationStartPending) &&
|
||||
(mControllerState != eAnimationStopPending) &&
|
||||
(currentToolbarState != eToolbarAnimating) &&
|
||||
@ -150,7 +170,10 @@ AndroidDynamicToolbarAnimator::ReceiveInputEvent(InputData& aEvent)
|
||||
}
|
||||
case MultiTouchInput::MULTITOUCH_END:
|
||||
case MultiTouchInput::MULTITOUCH_CANCEL:
|
||||
HandleTouchEnd(currentToolbarState, currentTouch);
|
||||
// last finger was lifted
|
||||
if (mControllerTouchCount == 0) {
|
||||
HandleTouchEnd(currentToolbarState, currentTouch);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -514,6 +537,9 @@ void
|
||||
AndroidDynamicToolbarAnimator::HandleTouchEnd(StaticToolbarState aCurrentToolbarState, ScreenIntCoord aCurrentTouch)
|
||||
{
|
||||
MOZ_ASSERT(APZThreadUtils::IsControllerThread());
|
||||
// If there was no move before the reset flag was set and the touch ended, check for it here.
|
||||
// if mControllerResetOnNextMove is true, it will be set to false here
|
||||
CheckForResetOnNextMove(aCurrentTouch);
|
||||
int32_t direction = mControllerLastDragDirection;
|
||||
mControllerLastDragDirection = 0;
|
||||
bool isRoot = mControllerScrollingRootContent;
|
||||
@ -530,23 +556,41 @@ AndroidDynamicToolbarAnimator::HandleTouchEnd(StaticToolbarState aCurrentToolbar
|
||||
|
||||
// If the last touch didn't have a drag direction, use start of touch to find direction
|
||||
if (!direction) {
|
||||
direction = ((aCurrentTouch - mControllerStartTouch) > 0 ? MOVE_TOOLBAR_DOWN : MOVE_TOOLBAR_UP);
|
||||
if (mControllerToolbarHeight == mControllerMaxToolbarHeight) {
|
||||
direction = MOVE_TOOLBAR_DOWN;
|
||||
} else if (mControllerToolbarHeight == 0) {
|
||||
direction = MOVE_TOOLBAR_UP;
|
||||
} else {
|
||||
direction = ((aCurrentTouch - mControllerStartTouch) > 0 ? MOVE_TOOLBAR_DOWN : MOVE_TOOLBAR_UP);
|
||||
}
|
||||
// If there still isn't a direction, default to show just to be safe
|
||||
if (!direction) {
|
||||
direction = MOVE_TOOLBAR_DOWN;
|
||||
}
|
||||
}
|
||||
bool dragThresholdReached = mControllerDragThresholdReached;
|
||||
mControllerStartTouch = 0;
|
||||
mControllerPreviousTouch = 0;
|
||||
mControllerTotalDistance = 0;
|
||||
mControllerDragThresholdReached = false;
|
||||
mControllerLastEventTimeStamp = 0;
|
||||
bool cancelTouchTracking = mControllerCancelTouchTracking;
|
||||
mControllerCancelTouchTracking = false;
|
||||
|
||||
// Animation is in progress, bail out.
|
||||
if (aCurrentToolbarState == eToolbarAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Received a UI thread request to show or hide the snapshot during a touch.
|
||||
// This overrides the touch event so just return
|
||||
if (mControllerCancelTouchTracking) {
|
||||
mControllerCancelTouchTracking = false;
|
||||
// This overrides the touch event so just return.
|
||||
if (cancelTouchTracking) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The toolbar is already where it needs to be so just return.
|
||||
if (((direction == MOVE_TOOLBAR_DOWN) && (mControllerToolbarHeight == mControllerMaxToolbarHeight)) ||
|
||||
((direction == MOVE_TOOLBAR_UP) && (mControllerToolbarHeight == 0))) {
|
||||
ShowToolbarIfNotVisible(aCurrentToolbarState);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -571,15 +615,7 @@ AndroidDynamicToolbarAnimator::HandleTouchEnd(StaticToolbarState aCurrentToolbar
|
||||
}
|
||||
}
|
||||
|
||||
// This makes sure the snapshot is not left partially visible at the end of a touch.
|
||||
if ((aCurrentToolbarState != eToolbarAnimating) && dragThresholdReached) {
|
||||
if (((direction == MOVE_TOOLBAR_DOWN) && (mControllerToolbarHeight != mControllerMaxToolbarHeight)) ||
|
||||
((direction == MOVE_TOOLBAR_UP) && (mControllerToolbarHeight != 0))) {
|
||||
StartCompositorAnimation(direction, eAnimate, mControllerToolbarHeight);
|
||||
}
|
||||
} else {
|
||||
ShowToolbarIfNotVisible(aCurrentToolbarState);
|
||||
}
|
||||
StartCompositorAnimation(direction, eAnimate, mControllerToolbarHeight);
|
||||
}
|
||||
|
||||
void
|
||||
@ -910,5 +946,17 @@ AndroidDynamicToolbarAnimator::NotifyControllerSnapshotFailed()
|
||||
UpdateCompositorToolbarHeight(mControllerToolbarHeight);
|
||||
}
|
||||
|
||||
void
|
||||
AndroidDynamicToolbarAnimator::CheckForResetOnNextMove(ScreenIntCoord aCurrentTouch) {
|
||||
MOZ_ASSERT(APZThreadUtils::IsControllerThread());
|
||||
if (mControllerResetOnNextMove) {
|
||||
mControllerTotalDistance = 0;
|
||||
mControllerLastDragDirection = 0;
|
||||
mControllerStartTouch = mControllerPreviousTouch = aCurrentTouch;
|
||||
mControllerDragThresholdReached = false;
|
||||
mControllerResetOnNextMove = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -150,6 +150,7 @@ protected:
|
||||
void TranslateTouchEvent(MultiTouchInput& aTouchEvent);
|
||||
ScreenIntCoord GetFixedLayerMarginsBottom();
|
||||
void NotifyControllerSnapshotFailed();
|
||||
void CheckForResetOnNextMove(ScreenIntCoord aCurrentTouch);
|
||||
|
||||
// Read only Compositor and Controller threads after Initialize()
|
||||
uint64_t mRootLayerTreeId;
|
||||
@ -163,6 +164,9 @@ protected:
|
||||
bool mControllerDragThresholdReached; // Set to true when the drag threshold has been passed in a single drag
|
||||
bool mControllerCancelTouchTracking; // Set to true when the UI thread requests the toolbar be made visible
|
||||
bool mControllerDragChangedDirection; // Set to true if the drag ever goes in more than one direction
|
||||
bool mControllerResetOnNextMove; // Set to true if transitioning from multiple touches to a single touch source
|
||||
// Causes mControllerStartTouch, mControllerPreviousTouch, mControllerTotalDistance,
|
||||
// mControllerDragThresholdReached, and mControllerLastDragDirection to be reset on next move
|
||||
ScreenIntCoord mControllerStartTouch; // The Y position where the touch started
|
||||
ScreenIntCoord mControllerPreviousTouch; // The previous Y position of the touch
|
||||
ScreenIntCoord mControllerTotalDistance; // Total distance travel during the current touch
|
||||
@ -171,6 +175,7 @@ protected:
|
||||
ScreenIntCoord mControllerSurfaceHeight; // Current height of the render surface
|
||||
ScreenIntCoord mControllerCompositionHeight; // Current height of the visible page
|
||||
int32_t mControllerLastDragDirection; // Direction of movement of the previous touch move event
|
||||
int32_t mControllerTouchCount; // Counts the number of current touches.
|
||||
uint32_t mControllerLastEventTimeStamp; // Time stamp for the previous touch event received
|
||||
ControllerThreadState mControllerState; // Contains the expected pending state of the mToolbarState
|
||||
|
||||
|
@ -1147,12 +1147,13 @@ LayerManagerComposite::RenderToolbar()
|
||||
|
||||
EffectChain effects;
|
||||
effects.mPrimaryEffect = animator->GetToolbarEffect(mCompositor->AsCompositorOGL());
|
||||
if (!effects.mPrimaryEffect) {
|
||||
// No toolbar texture so just draw a red square
|
||||
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 0, 0));
|
||||
// If GetToolbarEffect returns null, nothing is rendered for the static snapshot of the toolbar.
|
||||
// If the real toolbar chrome is not covering this portion of the surface, the clear color
|
||||
// of the surface will be visible. On Android the clear color is the background color of the page.
|
||||
if (effects.mPrimaryEffect) {
|
||||
mCompositor->DrawQuad(gfx::Rect(0, 0, mRenderBounds.width, toolbarHeight),
|
||||
IntRect(0, 0, mRenderBounds.width, toolbarHeight), effects, 1.0, gfx::Matrix4x4());
|
||||
}
|
||||
mCompositor->DrawQuad(gfx::Rect(0, 0, mRenderBounds.width, toolbarHeight),
|
||||
IntRect(0, 0, mRenderBounds.width, toolbarHeight), effects, 1.0, gfx::Matrix4x4());
|
||||
|
||||
// Move the content down the surface by the toolbar's height so they don't overlap
|
||||
gfx::Matrix4x4 mat = mCompositor->AsCompositorOGL()->GetProjMatrix();
|
||||
|
@ -123,7 +123,15 @@ CrossProcessCompositorBridgeParent::AllocPAPZCTreeManagerParent(const uint64_t&
|
||||
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
|
||||
MOZ_ASSERT(state.mParent);
|
||||
|
||||
// If the widget has shutdown its compositor, we may not have had a chance yet
|
||||
// to unmap our layers id, and we could get here without a parent compositor.
|
||||
// In this case return an empty APZCTM.
|
||||
if (!state.mParent) {
|
||||
RefPtr<APZCTreeManager> temp = new APZCTreeManager();
|
||||
return new APZCTreeManagerParent(aLayersId, temp);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!state.mApzcTreeManagerParent);
|
||||
state.mApzcTreeManagerParent = new APZCTreeManagerParent(aLayersId, state.mParent->GetAPZCTreeManager());
|
||||
|
||||
|
@ -2587,7 +2587,7 @@ gfxFont::GetShapedWord(DrawTarget *aDrawTarget,
|
||||
CacheHashKey key(aText, aLength, aHash,
|
||||
aRunScript,
|
||||
aAppUnitsPerDevUnit,
|
||||
aFlags);
|
||||
aFlags, aRounding);
|
||||
|
||||
CacheHashEntry *entry = mWordCache->PutEntry(key);
|
||||
if (!entry) {
|
||||
@ -2621,7 +2621,7 @@ gfxFont::GetShapedWord(DrawTarget *aDrawTarget,
|
||||
#endif
|
||||
|
||||
sw = gfxShapedWord::Create(aText, aLength, aRunScript, aAppUnitsPerDevUnit,
|
||||
aFlags);
|
||||
aFlags, aRounding);
|
||||
entry->mShapedWord.reset(sw);
|
||||
if (!sw) {
|
||||
NS_WARNING("failed to create gfxShapedWord - expect missing text");
|
||||
@ -2646,6 +2646,7 @@ gfxFont::CacheHashEntry::KeyEquals(const KeyTypePointer aKey) const
|
||||
}
|
||||
if (sw->GetLength() != aKey->mLength ||
|
||||
sw->GetFlags() != aKey->mFlags ||
|
||||
sw->GetRounding() != aKey->mRounding ||
|
||||
sw->GetAppUnitsPerDevUnit() != aKey->mAppUnitsPerDevUnit ||
|
||||
sw->GetScript() != aKey->mScript) {
|
||||
return false;
|
||||
|
@ -1190,7 +1190,8 @@ public:
|
||||
static gfxShapedWord* Create(const uint8_t *aText, uint32_t aLength,
|
||||
Script aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags) {
|
||||
uint32_t aFlags,
|
||||
gfxFontShaper::RoundingFlags aRounding) {
|
||||
NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
|
||||
"excessive length for gfxShapedWord!");
|
||||
|
||||
@ -1206,13 +1207,15 @@ public:
|
||||
|
||||
// Construct in the pre-allocated storage, using placement new
|
||||
return new (storage) gfxShapedWord(aText, aLength, aRunScript,
|
||||
aAppUnitsPerDevUnit, aFlags);
|
||||
aAppUnitsPerDevUnit, aFlags,
|
||||
aRounding);
|
||||
}
|
||||
|
||||
static gfxShapedWord* Create(const char16_t *aText, uint32_t aLength,
|
||||
Script aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags) {
|
||||
uint32_t aFlags,
|
||||
gfxFontShaper::RoundingFlags aRounding) {
|
||||
NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
|
||||
"excessive length for gfxShapedWord!");
|
||||
|
||||
@ -1224,7 +1227,8 @@ public:
|
||||
LossyAppendUTF16toASCII(nsDependentSubstring(aText, aLength),
|
||||
narrowText);
|
||||
return Create((const uint8_t*)(narrowText.BeginReading()),
|
||||
aLength, aRunScript, aAppUnitsPerDevUnit, aFlags);
|
||||
aLength, aRunScript, aAppUnitsPerDevUnit, aFlags,
|
||||
aRounding);
|
||||
}
|
||||
|
||||
uint32_t size =
|
||||
@ -1236,7 +1240,8 @@ public:
|
||||
}
|
||||
|
||||
return new (storage) gfxShapedWord(aText, aLength, aRunScript,
|
||||
aAppUnitsPerDevUnit, aFlags);
|
||||
aAppUnitsPerDevUnit, aFlags,
|
||||
aRounding);
|
||||
}
|
||||
|
||||
// Override operator delete to properly free the object that was
|
||||
@ -1272,6 +1277,10 @@ public:
|
||||
return mScript;
|
||||
}
|
||||
|
||||
gfxFontShaper::RoundingFlags GetRounding() const {
|
||||
return mRounding;
|
||||
}
|
||||
|
||||
void ResetAge() {
|
||||
mAgeCounter = 0;
|
||||
}
|
||||
@ -1292,10 +1301,12 @@ private:
|
||||
// Construct storage for a ShapedWord, ready to receive glyph data
|
||||
gfxShapedWord(const uint8_t *aText, uint32_t aLength,
|
||||
Script aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit, uint32_t aFlags)
|
||||
int32_t aAppUnitsPerDevUnit, uint32_t aFlags,
|
||||
gfxFontShaper::RoundingFlags aRounding)
|
||||
: gfxShapedText(aLength, aFlags | gfxTextRunFactory::TEXT_IS_8BIT,
|
||||
aAppUnitsPerDevUnit)
|
||||
, mScript(aRunScript)
|
||||
, mRounding(aRounding)
|
||||
, mAgeCounter(0)
|
||||
{
|
||||
memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
|
||||
@ -1305,9 +1316,11 @@ private:
|
||||
|
||||
gfxShapedWord(const char16_t *aText, uint32_t aLength,
|
||||
Script aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit, uint32_t aFlags)
|
||||
int32_t aAppUnitsPerDevUnit, uint32_t aFlags,
|
||||
gfxFontShaper::RoundingFlags aRounding)
|
||||
: gfxShapedText(aLength, aFlags, aAppUnitsPerDevUnit)
|
||||
, mScript(aRunScript)
|
||||
, mRounding(aRounding)
|
||||
, mAgeCounter(0)
|
||||
{
|
||||
memset(mCharGlyphsStorage, 0, aLength * sizeof(CompressedGlyph));
|
||||
@ -1318,6 +1331,8 @@ private:
|
||||
|
||||
Script mScript;
|
||||
|
||||
gfxFontShaper::RoundingFlags mRounding;
|
||||
|
||||
uint32_t mAgeCounter;
|
||||
|
||||
// The mCharGlyphsStorage array is actually a variable-size member;
|
||||
@ -2032,18 +2047,23 @@ protected:
|
||||
int32_t mAppUnitsPerDevUnit;
|
||||
PLDHashNumber mHashKey;
|
||||
bool mTextIs8Bit;
|
||||
RoundingFlags mRounding;
|
||||
|
||||
CacheHashKey(const uint8_t *aText, uint32_t aLength,
|
||||
uint32_t aStringHash,
|
||||
Script aScriptCode, int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags, RoundingFlags aRounding)
|
||||
: mLength(aLength),
|
||||
mFlags(aFlags),
|
||||
mScript(aScriptCode),
|
||||
mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
|
||||
mHashKey(aStringHash + static_cast<int32_t>(aScriptCode) +
|
||||
aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
|
||||
mTextIs8Bit(true)
|
||||
mHashKey(aStringHash
|
||||
+ static_cast<int32_t>(aScriptCode)
|
||||
+ aAppUnitsPerDevUnit * 0x100
|
||||
+ aFlags * 0x10000
|
||||
+ int(aRounding)),
|
||||
mTextIs8Bit(true),
|
||||
mRounding(aRounding)
|
||||
{
|
||||
NS_ASSERTION(aFlags & gfxTextRunFactory::TEXT_IS_8BIT,
|
||||
"8-bit flag should have been set");
|
||||
@ -2053,14 +2073,18 @@ protected:
|
||||
CacheHashKey(const char16_t *aText, uint32_t aLength,
|
||||
uint32_t aStringHash,
|
||||
Script aScriptCode, int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags, RoundingFlags aRounding)
|
||||
: mLength(aLength),
|
||||
mFlags(aFlags),
|
||||
mScript(aScriptCode),
|
||||
mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
|
||||
mHashKey(aStringHash + static_cast<int32_t>(aScriptCode) +
|
||||
aAppUnitsPerDevUnit * 0x100 + aFlags * 0x10000),
|
||||
mTextIs8Bit(false)
|
||||
mHashKey(aStringHash
|
||||
+ static_cast<int32_t>(aScriptCode)
|
||||
+ aAppUnitsPerDevUnit * 0x100
|
||||
+ aFlags * 0x10000
|
||||
+ int(aRounding)),
|
||||
mTextIs8Bit(false),
|
||||
mRounding(aRounding)
|
||||
{
|
||||
// We can NOT assert that TEXT_IS_8BIT is false in aFlags here,
|
||||
// because this might be an 8bit-only word from a 16-bit textrun,
|
||||
|
@ -995,7 +995,7 @@ close DATA_TABLES;
|
||||
|
||||
print HEADER "namespace mozilla {\n";
|
||||
print HEADER "namespace unicode {\n";
|
||||
print HEADER "enum class Script {\n";
|
||||
print HEADER "enum class Script : int16_t {\n";
|
||||
for (my $i = 0; $i < scalar @scriptCodeToName; ++$i) {
|
||||
print HEADER " ", $scriptCodeToName[$i], " = ", $i, ",\n";
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created on Tue Nov 15 16:39:42 2016 from UCD data files with version info:
|
||||
* Created on Tue Apr 4 21:22:17 2017 from UCD data files with version info:
|
||||
*
|
||||
|
||||
# Unicode Character Database
|
||||
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created on Tue Nov 15 16:39:42 2016 from UCD data files with version info:
|
||||
* Created on Tue Apr 4 21:22:17 2017 from UCD data files with version info:
|
||||
*
|
||||
|
||||
# Unicode Character Database
|
||||
@ -122,7 +122,7 @@ struct nsCharProps2 {
|
||||
|
||||
namespace mozilla {
|
||||
namespace unicode {
|
||||
enum class Script {
|
||||
enum class Script : int16_t {
|
||||
COMMON = 0,
|
||||
INHERITED = 1,
|
||||
ARABIC = 2,
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="*"
|
||||
name="plugin-container"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Firefox Runtime</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<comInterfaceExternalProxyStub
|
||||
iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
|
||||
name="IAccessible"
|
||||
tlbid="{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}"
|
||||
/>
|
||||
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:security>
|
||||
<ms_asmv3:requestedPrivileges>
|
||||
<ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</ms_asmv3:requestedPrivileges>
|
||||
</ms_asmv3:security>
|
||||
</ms_asmv3:trustInfo>
|
||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||
</ms_asmv3:windowsSettings>
|
||||
</ms_asmv3:application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
@ -59,14 +59,14 @@ static inline AuxCPOWData*
|
||||
AuxCPOWDataOf(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsCPOW(obj));
|
||||
return static_cast<AuxCPOWData*>(GetProxyExtra(obj, 1).toPrivate());
|
||||
return static_cast<AuxCPOWData*>(GetProxyReservedSlot(obj, 1).toPrivate());
|
||||
}
|
||||
|
||||
static inline WrapperOwner*
|
||||
OwnerOf(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsCPOW(obj));
|
||||
return reinterpret_cast<WrapperOwner*>(GetProxyExtra(obj, 0).toPrivate());
|
||||
return reinterpret_cast<WrapperOwner*>(GetProxyReservedSlot(obj, 0).toPrivate());
|
||||
}
|
||||
|
||||
ObjectId
|
||||
@ -1218,8 +1218,8 @@ WrapperOwner::fromRemoteObjectVariant(JSContext* cx, const RemoteObject& objVar)
|
||||
objVar.isDOMObject(),
|
||||
objVar.objectTag());
|
||||
|
||||
SetProxyExtra(obj, 0, PrivateValue(this));
|
||||
SetProxyExtra(obj, 1, PrivateValue(aux));
|
||||
SetProxyReservedSlot(obj, 0, PrivateValue(this));
|
||||
SetProxyReservedSlot(obj, 1, PrivateValue(aux));
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(cx, &obj))
|
||||
|
@ -367,30 +367,71 @@ inline bool IsProxy(const JSObject* obj)
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
const uint32_t PROXY_EXTRA_SLOTS = 2;
|
||||
|
||||
// Layout of the values stored by a proxy. Note that API clients require the
|
||||
// private slot to be the first slot in the proxy's values, so that the private
|
||||
// slot can be accessed in the same fashion as the first reserved slot, via
|
||||
// {Get,Set}ReservedOrProxyPrivateSlot.
|
||||
// Proxy slot layout
|
||||
// -----------------
|
||||
//
|
||||
// Every proxy has a ProxyValueArray that contains the following Values:
|
||||
//
|
||||
// - The private slot.
|
||||
// - The reserved slots. The number of slots is determined by the proxy's Class.
|
||||
//
|
||||
// Proxy objects store a pointer to the reserved slots (ProxyReservedSlots*).
|
||||
// The ProxyValueArray and the private slot can be accessed using
|
||||
// ProxyValueArray::fromReservedSlots or ProxyDataLayout::values.
|
||||
//
|
||||
// Storing a pointer to ProxyReservedSlots instead of ProxyValueArray has a
|
||||
// number of advantages. In particular, it means js::GetReservedSlot and
|
||||
// js::SetReservedSlot can be used with both proxies and native objects. This
|
||||
// works because the ProxyReservedSlots* pointer is stored where native objects
|
||||
// store their dynamic slots pointer.
|
||||
|
||||
struct ProxyReservedSlots
|
||||
{
|
||||
Value slots[1];
|
||||
|
||||
static inline int offsetOfPrivateSlot();
|
||||
|
||||
void init(size_t nreserved) {
|
||||
for (size_t i = 0; i < nreserved; i++)
|
||||
slots[i] = JS::UndefinedValue();
|
||||
}
|
||||
|
||||
ProxyReservedSlots(const ProxyReservedSlots&) = delete;
|
||||
void operator=(const ProxyReservedSlots&) = delete;
|
||||
};
|
||||
|
||||
struct ProxyValueArray
|
||||
{
|
||||
Value privateSlot;
|
||||
Value extraSlots[PROXY_EXTRA_SLOTS];
|
||||
ProxyReservedSlots reservedSlots;
|
||||
|
||||
ProxyValueArray()
|
||||
: privateSlot(JS::UndefinedValue())
|
||||
{
|
||||
for (size_t i = 0; i < PROXY_EXTRA_SLOTS; i++)
|
||||
extraSlots[i] = JS::UndefinedValue();
|
||||
void init(size_t nreserved) {
|
||||
privateSlot = JS::UndefinedValue();
|
||||
reservedSlots.init(nreserved);
|
||||
}
|
||||
|
||||
static size_t offsetOfPrivateSlot() {
|
||||
return offsetof(ProxyValueArray, privateSlot);
|
||||
static size_t sizeOf(size_t nreserved) {
|
||||
return offsetOfReservedSlots() + nreserved * sizeof(Value);
|
||||
}
|
||||
static MOZ_ALWAYS_INLINE ProxyValueArray* fromReservedSlots(ProxyReservedSlots* slots) {
|
||||
uintptr_t p = reinterpret_cast<uintptr_t>(slots);
|
||||
return reinterpret_cast<ProxyValueArray*>(p - offsetOfReservedSlots());
|
||||
}
|
||||
static size_t offsetOfReservedSlots() {
|
||||
return offsetof(ProxyValueArray, reservedSlots);
|
||||
}
|
||||
|
||||
ProxyValueArray(const ProxyValueArray&) = delete;
|
||||
void operator=(const ProxyValueArray&) = delete;
|
||||
};
|
||||
|
||||
/* static */ inline int
|
||||
ProxyReservedSlots::offsetOfPrivateSlot()
|
||||
{
|
||||
return -int(ProxyValueArray::offsetOfReservedSlots()) + offsetof(ProxyValueArray, privateSlot);
|
||||
}
|
||||
|
||||
// All proxies share the same data layout. Following the object's shape and
|
||||
// type, the proxy has a ProxyDataLayout structure with a pointer to an array
|
||||
// of values and the proxy's handler. This is designed both so that proxies can
|
||||
@ -401,8 +442,12 @@ struct ProxyValueArray
|
||||
// See GetReservedOrProxyPrivateSlot below.
|
||||
struct ProxyDataLayout
|
||||
{
|
||||
ProxyValueArray* values;
|
||||
ProxyReservedSlots* reservedSlots;
|
||||
const BaseProxyHandler* handler;
|
||||
|
||||
MOZ_ALWAYS_INLINE ProxyValueArray* values() const {
|
||||
return ProxyValueArray::fromReservedSlots(reservedSlots);
|
||||
}
|
||||
};
|
||||
|
||||
const uint32_t ProxyDataOffset = 2 * sizeof(void*);
|
||||
@ -432,7 +477,7 @@ GetProxyHandler(const JSObject* obj)
|
||||
inline const Value&
|
||||
GetProxyPrivate(const JSObject* obj)
|
||||
{
|
||||
return detail::GetProxyDataLayout(obj)->values->privateSlot;
|
||||
return detail::GetProxyDataLayout(obj)->values()->privateSlot;
|
||||
}
|
||||
|
||||
inline JSObject*
|
||||
@ -442,10 +487,10 @@ GetProxyTargetObject(JSObject* obj)
|
||||
}
|
||||
|
||||
inline const Value&
|
||||
GetProxyExtra(const JSObject* obj, size_t n)
|
||||
GetProxyReservedSlot(const JSObject* obj, size_t n)
|
||||
{
|
||||
MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
|
||||
return detail::GetProxyDataLayout(obj)->values->extraSlots[n];
|
||||
MOZ_ASSERT(n < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
|
||||
return detail::GetProxyDataLayout(obj)->reservedSlots->slots[n];
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -458,10 +503,10 @@ JS_FRIEND_API(void)
|
||||
SetValueInProxy(Value* slot, const Value& value);
|
||||
|
||||
inline void
|
||||
SetProxyExtra(JSObject* obj, size_t n, const Value& extra)
|
||||
SetProxyReservedSlot(JSObject* obj, size_t n, const Value& extra)
|
||||
{
|
||||
MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
|
||||
Value* vp = &detail::GetProxyDataLayout(obj)->values->extraSlots[n];
|
||||
MOZ_ASSERT(n < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
|
||||
Value* vp = &detail::GetProxyDataLayout(obj)->reservedSlots->slots[n];
|
||||
|
||||
// Trigger a barrier before writing the slot.
|
||||
if (vp->isGCThing() || extra.isGCThing())
|
||||
@ -470,32 +515,24 @@ SetProxyExtra(JSObject* obj, size_t n, const Value& extra)
|
||||
*vp = extra;
|
||||
}
|
||||
|
||||
inline void
|
||||
SetProxyPrivate(JSObject* obj, const Value& value)
|
||||
{
|
||||
Value* vp = &detail::GetProxyDataLayout(obj)->values()->privateSlot;
|
||||
|
||||
// Trigger a barrier before writing the slot.
|
||||
if (vp->isGCThing() || value.isGCThing())
|
||||
SetValueInProxy(vp, value);
|
||||
else
|
||||
*vp = value;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsScriptedProxy(const JSObject* obj)
|
||||
{
|
||||
return IsProxy(obj) && GetProxyHandler(obj)->isScripted();
|
||||
}
|
||||
|
||||
inline const Value&
|
||||
GetReservedOrProxyPrivateSlot(const JSObject* obj, size_t slot)
|
||||
{
|
||||
MOZ_ASSERT(slot == 0);
|
||||
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)) || IsProxy(obj));
|
||||
return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
SetReservedOrProxyPrivateSlot(JSObject* obj, size_t slot, const Value& value)
|
||||
{
|
||||
MOZ_ASSERT(slot == 0);
|
||||
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)) || IsProxy(obj));
|
||||
shadow::Object* sobj = reinterpret_cast<shadow::Object*>(obj);
|
||||
if (sobj->slotRef(slot).isGCThing() || value.isGCThing())
|
||||
SetReservedOrProxyPrivateSlotWithBarrier(obj, slot, value);
|
||||
else
|
||||
sobj->slotRef(slot) = value;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS ProxyOptions {
|
||||
protected:
|
||||
/* protected constructor for subclass */
|
||||
|
@ -9607,6 +9607,21 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
|
||||
return null();
|
||||
break;
|
||||
|
||||
case TOK_STRING: {
|
||||
propAtom.set(tokenStream.currentToken().atom());
|
||||
uint32_t index;
|
||||
if (propAtom->isIndex(&index)) {
|
||||
propName = handler.newNumber(index, NoDecimal, pos());
|
||||
if (!propName)
|
||||
return null();
|
||||
break;
|
||||
}
|
||||
propName = stringLiteral();
|
||||
if (!propName)
|
||||
return null();
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_LB:
|
||||
propName = computedPropertyName(yieldHandling, maybeDecl, propList);
|
||||
if (!propName)
|
||||
@ -9620,7 +9635,7 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
|
||||
}
|
||||
|
||||
propAtom.set(tokenStream.currentName());
|
||||
// Do not look for accessor syntax on generators
|
||||
// Do not look for accessor syntax on generator or async methods.
|
||||
if (isGenerator || isAsync || !(ltok == TOK_GET || ltok == TOK_SET)) {
|
||||
propName = handler.newObjectLiteralPropertyName(propAtom, pos());
|
||||
if (!propName)
|
||||
@ -9675,21 +9690,6 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
|
||||
return null();
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_STRING: {
|
||||
propAtom.set(tokenStream.currentToken().atom());
|
||||
uint32_t index;
|
||||
if (propAtom->isIndex(&index)) {
|
||||
propName = handler.newNumber(index, NoDecimal, pos());
|
||||
if (!propName)
|
||||
return null();
|
||||
break;
|
||||
}
|
||||
propName = stringLiteral();
|
||||
if (!propName)
|
||||
return null();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TokenKind tt;
|
||||
@ -9697,7 +9697,7 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
|
||||
return null();
|
||||
|
||||
if (tt == TOK_COLON) {
|
||||
if (isGenerator) {
|
||||
if (isGenerator || isAsync) {
|
||||
error(JSMSG_BAD_PROP_ID);
|
||||
return null();
|
||||
}
|
||||
@ -9708,7 +9708,7 @@ Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
|
||||
if (TokenKindIsPossibleIdentifierName(ltok) &&
|
||||
(tt == TOK_COMMA || tt == TOK_RC || tt == TOK_ASSIGN))
|
||||
{
|
||||
if (isGenerator) {
|
||||
if (isGenerator || isAsync) {
|
||||
error(JSMSG_BAD_PROP_ID);
|
||||
return null();
|
||||
}
|
||||
|
15
js/src/jit-test/tests/ion/recover-newarrayiterator-close.js
Normal file
15
js/src/jit-test/tests/ion/recover-newarrayiterator-close.js
Normal file
@ -0,0 +1,15 @@
|
||||
// |jit-test| --no-threads
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
for (var k = 0; k < 35; ++k) {
|
||||
try {
|
||||
(function (x) {
|
||||
(x ? 0 : ([y] = []));
|
||||
})();
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 35; i++)
|
||||
test();
|
@ -1826,8 +1826,8 @@ BaselineCacheIRCompiler::emitLoadDOMExpandoValueGuardGeneration()
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfValues()), scratch);
|
||||
Address expandoAddr(scratch, ProxyObject::offsetOfExtraSlotInValues(GetDOMProxyExpandoSlot()));
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
Address expandoAddr(scratch, detail::ProxyReservedSlots::offsetOfPrivateSlot());
|
||||
|
||||
// Load the ExpandoAndGeneration* in the output scratch register and guard
|
||||
// it matches the proxy's ExpandoAndGeneration.
|
||||
|
@ -803,7 +803,7 @@ GetPropIRGenerator::tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objI
|
||||
{
|
||||
MOZ_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
RootedValue expandoVal(cx_, GetProxyExtra(obj, GetDOMProxyExpandoSlot()));
|
||||
RootedValue expandoVal(cx_, GetProxyPrivate(obj));
|
||||
RootedObject expandoObj(cx_);
|
||||
if (expandoVal.isObject()) {
|
||||
expandoObj = &expandoVal.toObject();
|
||||
@ -873,7 +873,7 @@ CheckDOMProxyExpandoDoesNotShadow(CacheIRWriter& writer, JSObject* obj, jsid id,
|
||||
{
|
||||
MOZ_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
Value expandoVal = GetProxyExtra(obj, GetDOMProxyExpandoSlot());
|
||||
Value expandoVal = GetProxyPrivate(obj);
|
||||
|
||||
ValOperandId expandoId;
|
||||
if (!expandoVal.isObject() && !expandoVal.isUndefined()) {
|
||||
@ -3164,7 +3164,7 @@ SetPropIRGenerator::tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objI
|
||||
{
|
||||
MOZ_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
RootedValue expandoVal(cx_, GetProxyExtra(obj, GetDOMProxyExpandoSlot()));
|
||||
RootedValue expandoVal(cx_, GetProxyPrivate(obj));
|
||||
RootedObject expandoObj(cx_);
|
||||
if (expandoVal.isObject()) {
|
||||
expandoObj = &expandoVal.toObject();
|
||||
|
@ -1576,8 +1576,8 @@ CacheIRCompiler::emitLoadWrapperTarget()
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
Register reg = allocator.defineRegister(masm, reader.objOperandId());
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfValues()), reg);
|
||||
masm.unboxObject(Address(reg, detail::ProxyValueArray::offsetOfPrivateSlot()), reg);
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), reg);
|
||||
masm.unboxObject(Address(reg, detail::ProxyReservedSlots::offsetOfPrivateSlot()), reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1587,9 +1587,9 @@ CacheIRCompiler::emitLoadDOMExpandoValue()
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
ValueOperand val = allocator.defineValueRegister(masm, reader.valOperandId());
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfValues()), val.scratchReg());
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), val.scratchReg());
|
||||
masm.loadValue(Address(val.scratchReg(),
|
||||
ProxyObject::offsetOfExtraSlotInValues(GetDOMProxyExpandoSlot())),
|
||||
detail::ProxyReservedSlots::offsetOfPrivateSlot()),
|
||||
val);
|
||||
return true;
|
||||
}
|
||||
@ -1602,8 +1602,8 @@ CacheIRCompiler::emitLoadDOMExpandoValueIgnoreGeneration()
|
||||
|
||||
// Determine the expando's Address.
|
||||
Register scratch = output.scratchReg();
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfValues()), scratch);
|
||||
Address expandoAddr(scratch, ProxyObject::offsetOfExtraSlotInValues(GetDOMProxyExpandoSlot()));
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
Address expandoAddr(scratch, detail::ProxyReservedSlots::offsetOfPrivateSlot());
|
||||
|
||||
#ifdef DEBUG
|
||||
// Private values are stored as doubles, so assert we have a double.
|
||||
|
@ -1985,8 +1985,8 @@ IonCacheIRCompiler::emitLoadDOMExpandoValueGuardGeneration()
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfValues()), scratch1);
|
||||
Address expandoAddr(scratch1, ProxyObject::offsetOfExtraSlotInValues(GetDOMProxyExpandoSlot()));
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch1);
|
||||
Address expandoAddr(scratch1, detail::ProxyReservedSlots::offsetOfPrivateSlot());
|
||||
|
||||
// Guard the ExpandoAndGeneration* matches the proxy's ExpandoAndGeneration.
|
||||
masm.loadValue(expandoAddr, output);
|
||||
|
@ -348,7 +348,8 @@ CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, JSTryNote*
|
||||
for (unsigned i = 0; i < skipSlots; i++)
|
||||
si.skip();
|
||||
|
||||
Value v = si.read();
|
||||
MaybeReadFallback recover(cx, cx->activation()->asJit(), &frame.frame(), MaybeReadFallback::Fallback_DoNothing);
|
||||
Value v = si.maybeRead(recover);
|
||||
RootedObject iterObject(cx, &v.toObject());
|
||||
|
||||
if (isDestructuring) {
|
||||
|
@ -74,15 +74,15 @@ BEGIN_TEST(testBug604087)
|
||||
|
||||
JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
|
||||
CHECK(c2wrapper);
|
||||
c2wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(2));
|
||||
c2wrapper->as<js::ProxyObject>().setReservedSlot(0, js::Int32Value(2));
|
||||
|
||||
JS::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3));
|
||||
CHECK(c3wrapper);
|
||||
c3wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(3));
|
||||
c3wrapper->as<js::ProxyObject>().setReservedSlot(0, js::Int32Value(3));
|
||||
|
||||
JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
|
||||
CHECK(c4wrapper);
|
||||
c4wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(4));
|
||||
c4wrapper->as<js::ProxyObject>().setReservedSlot(0, js::Int32Value(4));
|
||||
compartment4 = c4wrapper = nullptr;
|
||||
|
||||
JS::RootedObject next(cx);
|
||||
|
@ -2824,10 +2824,10 @@ GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj, uint32_t begin, uin
|
||||
for (; !r.empty(); r.popFront()) {
|
||||
Shape& shape = r.front();
|
||||
jsid id = shape.propid();
|
||||
if (!JSID_IS_INT(id))
|
||||
uint32_t i;
|
||||
if (!IdIsIndex(id, &i))
|
||||
continue;
|
||||
|
||||
uint32_t i = uint32_t(JSID_TO_INT(id));
|
||||
if (!(begin <= i && i < end))
|
||||
continue;
|
||||
|
||||
|
@ -546,14 +546,12 @@ js::GetOriginalEval(JSContext* cx, HandleObject scope, MutableHandleObject eval)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetReservedOrProxyPrivateSlotWithBarrier(JSObject* obj, size_t slot, const js::Value& value)
|
||||
js::SetReservedSlotWithBarrier(JSObject* obj, size_t slot, const js::Value& value)
|
||||
{
|
||||
if (IsProxy(obj)) {
|
||||
MOZ_ASSERT(slot == 0);
|
||||
obj->as<ProxyObject>().setSameCompartmentPrivate(value);
|
||||
} else {
|
||||
if (IsProxy(obj))
|
||||
obj->as<ProxyObject>().setReservedSlot(slot, value);
|
||||
else
|
||||
obj->as<NativeObject>().setSlot(slot, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1298,15 +1296,13 @@ js::GetDOMCallbacks(JSContext* cx)
|
||||
}
|
||||
|
||||
static const void* gDOMProxyHandlerFamily = nullptr;
|
||||
static uint32_t gDOMProxyExpandoSlot = 0;
|
||||
static DOMProxyShadowsCheck gDOMProxyShadowsCheck;
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetDOMProxyInformation(const void* domProxyHandlerFamily, uint32_t domProxyExpandoSlot,
|
||||
js::SetDOMProxyInformation(const void* domProxyHandlerFamily,
|
||||
DOMProxyShadowsCheck domProxyShadowsCheck)
|
||||
{
|
||||
gDOMProxyHandlerFamily = domProxyHandlerFamily;
|
||||
gDOMProxyExpandoSlot = domProxyExpandoSlot;
|
||||
gDOMProxyShadowsCheck = domProxyShadowsCheck;
|
||||
}
|
||||
|
||||
@ -1316,12 +1312,6 @@ js::GetDOMProxyHandlerFamily()
|
||||
return gDOMProxyHandlerFamily;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::GetDOMProxyExpandoSlot()
|
||||
{
|
||||
return gDOMProxyExpandoSlot;
|
||||
}
|
||||
|
||||
DOMProxyShadowsCheck
|
||||
js::GetDOMProxyShadowsCheck()
|
||||
{
|
||||
|
@ -365,6 +365,7 @@ extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
|
||||
js::Class::NON_NATIVE | \
|
||||
JSCLASS_IS_PROXY | \
|
||||
JSCLASS_DELAY_METADATA_BUILDER | \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2) | \
|
||||
flags, \
|
||||
&js::ProxyClassOps, \
|
||||
JS_NULL_CLASS_SPEC, \
|
||||
@ -722,6 +723,11 @@ GetObjectPrivate(JSObject* obj)
|
||||
return *addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value stored in an object's reserved slot. This can be used with
|
||||
* both native objects and proxies, but if |obj| is known to be a proxy
|
||||
* GetProxyReservedSlot is a bit more efficient.
|
||||
*/
|
||||
inline const JS::Value&
|
||||
GetReservedSlot(JSObject* obj, size_t slot)
|
||||
{
|
||||
@ -730,15 +736,20 @@ GetReservedSlot(JSObject* obj, size_t slot)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
SetReservedOrProxyPrivateSlotWithBarrier(JSObject* obj, size_t slot, const JS::Value& value);
|
||||
SetReservedSlotWithBarrier(JSObject* obj, size_t slot, const JS::Value& value);
|
||||
|
||||
/**
|
||||
* Store a value in an object's reserved slot. This can be used with
|
||||
* both native objects and proxies, but if |obj| is known to be a proxy
|
||||
* SetProxyReservedSlot is a bit more efficient.
|
||||
*/
|
||||
inline void
|
||||
SetReservedSlot(JSObject* obj, size_t slot, const JS::Value& value)
|
||||
{
|
||||
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
|
||||
shadow::Object* sobj = reinterpret_cast<shadow::Object*>(obj);
|
||||
if (sobj->slotRef(slot).isGCThing() || value.isGCThing())
|
||||
SetReservedOrProxyPrivateSlotWithBarrier(obj, slot, value);
|
||||
SetReservedSlotWithBarrier(obj, slot, value);
|
||||
else
|
||||
sobj->slotRef(slot) = value;
|
||||
}
|
||||
@ -1289,11 +1300,10 @@ typedef enum DOMProxyShadowsResult {
|
||||
typedef DOMProxyShadowsResult
|
||||
(* DOMProxyShadowsCheck)(JSContext* cx, JS::HandleObject object, JS::HandleId id);
|
||||
JS_FRIEND_API(void)
|
||||
SetDOMProxyInformation(const void* domProxyHandlerFamily, uint32_t domProxyExpandoSlot,
|
||||
SetDOMProxyInformation(const void* domProxyHandlerFamily,
|
||||
DOMProxyShadowsCheck domProxyShadowsCheck);
|
||||
|
||||
const void* GetDOMProxyHandlerFamily();
|
||||
uint32_t GetDOMProxyExpandoSlot();
|
||||
DOMProxyShadowsCheck GetDOMProxyShadowsCheck();
|
||||
inline bool DOMProxyIsShadowing(DOMProxyShadowsResult result) {
|
||||
return result == Shadows ||
|
||||
|
@ -4677,7 +4677,7 @@ IsGrayListObject(JSObject* obj)
|
||||
}
|
||||
|
||||
/* static */ unsigned
|
||||
ProxyObject::grayLinkExtraSlot(JSObject* obj)
|
||||
ProxyObject::grayLinkReservedSlot(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsGrayListObject(obj));
|
||||
return 1;
|
||||
@ -4688,7 +4688,7 @@ static void
|
||||
AssertNotOnGrayList(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT_IF(IsGrayListObject(obj),
|
||||
GetProxyExtra(obj, ProxyObject::grayLinkExtraSlot(obj)).isUndefined());
|
||||
GetProxyReservedSlot(obj, ProxyObject::grayLinkReservedSlot(obj)).isUndefined());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4716,12 +4716,12 @@ CrossCompartmentPointerReferent(JSObject* obj)
|
||||
static JSObject*
|
||||
NextIncomingCrossCompartmentPointer(JSObject* prev, bool unlink)
|
||||
{
|
||||
unsigned slot = ProxyObject::grayLinkExtraSlot(prev);
|
||||
JSObject* next = GetProxyExtra(prev, slot).toObjectOrNull();
|
||||
unsigned slot = ProxyObject::grayLinkReservedSlot(prev);
|
||||
JSObject* next = GetProxyReservedSlot(prev, slot).toObjectOrNull();
|
||||
MOZ_ASSERT_IF(next, IsGrayListObject(next));
|
||||
|
||||
if (unlink)
|
||||
SetProxyExtra(prev, slot, UndefinedValue());
|
||||
SetProxyReservedSlot(prev, slot, UndefinedValue());
|
||||
|
||||
return next;
|
||||
}
|
||||
@ -4732,15 +4732,15 @@ js::DelayCrossCompartmentGrayMarking(JSObject* src)
|
||||
MOZ_ASSERT(IsGrayListObject(src));
|
||||
|
||||
/* Called from MarkCrossCompartmentXXX functions. */
|
||||
unsigned slot = ProxyObject::grayLinkExtraSlot(src);
|
||||
unsigned slot = ProxyObject::grayLinkReservedSlot(src);
|
||||
JSObject* dest = CrossCompartmentPointerReferent(src);
|
||||
JSCompartment* comp = dest->compartment();
|
||||
|
||||
if (GetProxyExtra(src, slot).isUndefined()) {
|
||||
SetProxyExtra(src, slot, ObjectOrNullValue(comp->gcIncomingGrayPointers));
|
||||
if (GetProxyReservedSlot(src, slot).isUndefined()) {
|
||||
SetProxyReservedSlot(src, slot, ObjectOrNullValue(comp->gcIncomingGrayPointers));
|
||||
comp->gcIncomingGrayPointers = src;
|
||||
} else {
|
||||
MOZ_ASSERT(GetProxyExtra(src, slot).isObjectOrNull());
|
||||
MOZ_ASSERT(GetProxyReservedSlot(src, slot).isObjectOrNull());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -4809,12 +4809,12 @@ RemoveFromGrayList(JSObject* wrapper)
|
||||
if (!IsGrayListObject(wrapper))
|
||||
return false;
|
||||
|
||||
unsigned slot = ProxyObject::grayLinkExtraSlot(wrapper);
|
||||
if (GetProxyExtra(wrapper, slot).isUndefined())
|
||||
unsigned slot = ProxyObject::grayLinkReservedSlot(wrapper);
|
||||
if (GetProxyReservedSlot(wrapper, slot).isUndefined())
|
||||
return false; /* Not on our list. */
|
||||
|
||||
JSObject* tail = GetProxyExtra(wrapper, slot).toObjectOrNull();
|
||||
SetProxyExtra(wrapper, slot, UndefinedValue());
|
||||
JSObject* tail = GetProxyReservedSlot(wrapper, slot).toObjectOrNull();
|
||||
SetProxyReservedSlot(wrapper, slot, UndefinedValue());
|
||||
|
||||
JSCompartment* comp = CrossCompartmentPointerReferent(wrapper)->compartment();
|
||||
JSObject* obj = comp->gcIncomingGrayPointers;
|
||||
@ -4824,10 +4824,10 @@ RemoveFromGrayList(JSObject* wrapper)
|
||||
}
|
||||
|
||||
while (obj) {
|
||||
unsigned slot = ProxyObject::grayLinkExtraSlot(obj);
|
||||
JSObject* next = GetProxyExtra(obj, slot).toObjectOrNull();
|
||||
unsigned slot = ProxyObject::grayLinkReservedSlot(obj);
|
||||
JSObject* next = GetProxyReservedSlot(obj, slot).toObjectOrNull();
|
||||
if (next == wrapper) {
|
||||
SetProxyExtra(obj, slot, ObjectOrNullValue(tail));
|
||||
SetProxyReservedSlot(obj, slot, ObjectOrNullValue(tail));
|
||||
return true;
|
||||
}
|
||||
obj = next;
|
||||
|
@ -1125,12 +1125,14 @@ CopyProxyObject(JSContext* cx, Handle<ProxyObject*> from, Handle<ProxyObject*> t
|
||||
to->setSameCompartmentPrivate(v);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(from->numReservedSlots() == to->numReservedSlots());
|
||||
|
||||
RootedValue v(cx);
|
||||
for (size_t n = 0; n < js::detail::PROXY_EXTRA_SLOTS; n++) {
|
||||
v = GetProxyExtra(from, n);
|
||||
for (size_t n = 0; n < from->numReservedSlots(); n++) {
|
||||
v = GetProxyReservedSlot(from, n);
|
||||
if (!cx->compartment()->wrap(cx, &v))
|
||||
return false;
|
||||
SetProxyExtra(to, n, v);
|
||||
SetProxyReservedSlot(to, n, v);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1528,13 +1530,58 @@ JSObject::fixDictionaryShapeAfterSwap()
|
||||
as<NativeObject>().shape_->listp = &as<NativeObject>().shape_;
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveFromStoreBuffer(JSContext* cx, js::detail::ProxyValueArray* values)
|
||||
static MOZ_MUST_USE bool
|
||||
CopyProxyValuesBeforeSwap(ProxyObject* proxy, Vector<Value>& values)
|
||||
{
|
||||
StoreBuffer& sb = cx->zone()->group()->storeBuffer();
|
||||
sb.unputValue(&values->privateSlot);
|
||||
for (size_t i = 0; i < js::detail::PROXY_EXTRA_SLOTS; i++)
|
||||
sb.unputValue(&values->extraSlots[i]);
|
||||
MOZ_ASSERT(values.empty());
|
||||
|
||||
// Remove the GCPtrValues we're about to swap from the store buffer, to
|
||||
// ensure we don't trace bogus values.
|
||||
StoreBuffer& sb = proxy->zone()->group()->storeBuffer();
|
||||
|
||||
// Reserve space for the private slot and the reserved slots.
|
||||
if (!values.reserve(1 + proxy->numReservedSlots()))
|
||||
return false;
|
||||
|
||||
js::detail::ProxyValueArray* valArray = js::detail::GetProxyDataLayout(proxy)->values();
|
||||
sb.unputValue(&valArray->privateSlot);
|
||||
values.infallibleAppend(valArray->privateSlot);
|
||||
|
||||
for (size_t i = 0; i < proxy->numReservedSlots(); i++) {
|
||||
sb.unputValue(&valArray->reservedSlots.slots[i]);
|
||||
values.infallibleAppend(valArray->reservedSlots.slots[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyObject::initExternalValueArrayAfterSwap(JSContext* cx, const Vector<Value>& values)
|
||||
{
|
||||
MOZ_ASSERT(getClass()->isProxy());
|
||||
|
||||
size_t nreserved = numReservedSlots();
|
||||
|
||||
// |values| contains the private slot and the reserved slots.
|
||||
MOZ_ASSERT(values.length() == 1 + nreserved);
|
||||
|
||||
size_t nbytes = js::detail::ProxyValueArray::sizeOf(nreserved);
|
||||
|
||||
auto* valArray =
|
||||
reinterpret_cast<js::detail::ProxyValueArray*>(cx->zone()->pod_malloc<uint8_t>(nbytes));
|
||||
if (!valArray)
|
||||
return false;
|
||||
|
||||
valArray->privateSlot = values[0];
|
||||
|
||||
for (size_t i = 0; i < nreserved; i++)
|
||||
valArray->reservedSlots.slots[i] = values[i + 1];
|
||||
|
||||
// Note: we allocate external slots iff the proxy had an inline
|
||||
// ProxyValueArray, so at this point reservedSlots points into the
|
||||
// old object and we don't have to free anything.
|
||||
data.reservedSlots = &valArray->reservedSlots;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Use this method with extreme caution. It trades the guts of two objects. */
|
||||
@ -1640,16 +1687,13 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
|
||||
ProxyObject* proxyA = a->is<ProxyObject>() ? &a->as<ProxyObject>() : nullptr;
|
||||
ProxyObject* proxyB = b->is<ProxyObject>() ? &b->as<ProxyObject>() : nullptr;
|
||||
|
||||
Maybe<js::detail::ProxyValueArray> proxyAVals, proxyBVals;
|
||||
if (aIsProxyWithInlineValues) {
|
||||
js::detail::ProxyValueArray* values = js::detail::GetProxyDataLayout(proxyA)->values;
|
||||
proxyAVals.emplace(*values);
|
||||
RemoveFromStoreBuffer(cx, values);
|
||||
if (!CopyProxyValuesBeforeSwap(proxyA, avals))
|
||||
oomUnsafe.crash("CopyProxyValuesBeforeSwap");
|
||||
}
|
||||
if (bIsProxyWithInlineValues) {
|
||||
js::detail::ProxyValueArray* values = js::detail::GetProxyDataLayout(proxyB)->values;
|
||||
proxyBVals.emplace(*values);
|
||||
RemoveFromStoreBuffer(cx, values);
|
||||
if (!CopyProxyValuesBeforeSwap(proxyB, bvals))
|
||||
oomUnsafe.crash("CopyProxyValuesBeforeSwap");
|
||||
}
|
||||
|
||||
// Swap the main fields of the objects, whether they are native objects or proxies.
|
||||
@ -1670,11 +1714,11 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
|
||||
oomUnsafe.crash("fillInAfterSwap");
|
||||
}
|
||||
if (aIsProxyWithInlineValues) {
|
||||
if (!b->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, proxyAVals.ref()))
|
||||
if (!b->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, avals))
|
||||
oomUnsafe.crash("initExternalValueArray");
|
||||
}
|
||||
if (bIsProxyWithInlineValues) {
|
||||
if (!a->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, proxyBVals.ref()))
|
||||
if (!a->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, bvals))
|
||||
oomUnsafe.crash("initExternalValueArray");
|
||||
}
|
||||
}
|
||||
@ -4078,11 +4122,11 @@ JSObject::debugCheckNewObject(ObjectGroup* group, Shape* shape, js::gc::AllocKin
|
||||
|
||||
MOZ_ASSERT(!group->compartment()->hasObjectPendingMetadata());
|
||||
|
||||
// Non-native classes cannot have reserved slots or private data, and the
|
||||
// objects can't have any fixed slots, for compatibility with
|
||||
// GetReservedOrProxyPrivateSlot.
|
||||
// Non-native classes manage their own data and slots, so numFixedSlots and
|
||||
// slotSpan are always 0. Note that proxy classes can have reserved slots
|
||||
// but they're also not included in numFixedSlots/slotSpan.
|
||||
if (!clasp->isNative()) {
|
||||
MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(clasp) == 0);
|
||||
MOZ_ASSERT_IF(!clasp->isProxy(), JSCLASS_RESERVED_SLOTS(clasp) == 0);
|
||||
MOZ_ASSERT(!clasp->hasPrivate());
|
||||
MOZ_ASSERT_IF(shape, shape->numFixedSlots() == 0);
|
||||
MOZ_ASSERT_IF(shape, shape->slotSpan() == 0);
|
||||
|
@ -685,14 +685,17 @@ ProxyObject::trace(JSTracer* trc, JSObject* obj)
|
||||
// Note: If you add new slots here, make sure to change
|
||||
// nuke() to cope.
|
||||
TraceCrossCompartmentEdge(trc, obj, proxy->slotOfPrivate(), "private");
|
||||
TraceEdge(trc, proxy->slotOfExtra(0), "extra0");
|
||||
|
||||
/*
|
||||
* The GC can use the second reserved slot to link the cross compartment
|
||||
* wrappers into a linked list, in which case we don't want to trace it.
|
||||
*/
|
||||
if (!proxy->is<CrossCompartmentWrapperObject>())
|
||||
TraceEdge(trc, proxy->slotOfExtra(1), "extra1");
|
||||
size_t nreserved = proxy->numReservedSlots();
|
||||
for (size_t i = 0; i < nreserved; i++) {
|
||||
/*
|
||||
* The GC can use the second reserved slot to link the cross compartment
|
||||
* wrappers into a linked list, in which case we don't want to trace it.
|
||||
*/
|
||||
if (proxy->is<CrossCompartmentWrapperObject>() && i == 1)
|
||||
continue;
|
||||
TraceEdge(trc, proxy->reservedSlotPtr(i), "proxy_reserved");
|
||||
}
|
||||
|
||||
Proxy::trace(trc, obj);
|
||||
}
|
||||
@ -714,7 +717,7 @@ proxy_Finalize(FreeOp* fop, JSObject* obj)
|
||||
obj->as<ProxyObject>().handler()->finalize(fop, obj);
|
||||
|
||||
if (!obj->as<ProxyObject>().usingInlineValueArray())
|
||||
js_free(js::detail::GetProxyDataLayout(obj)->values);
|
||||
js_free(js::detail::GetProxyDataLayout(obj)->values());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -803,8 +806,8 @@ ProxyObject::renew(const BaseProxyHandler* handler, const Value& priv)
|
||||
|
||||
setHandler(handler);
|
||||
setCrossCompartmentPrivate(priv);
|
||||
setExtra(0, UndefinedValue());
|
||||
setExtra(1, UndefinedValue());
|
||||
for (size_t i = 0; i < numReservedSlots(); i++)
|
||||
setReservedSlot(i, UndefinedValue());
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject*)
|
||||
|
@ -130,7 +130,7 @@ IsCompatiblePropertyDescriptor(JSContext* cx, bool extensible, Handle<PropertyDe
|
||||
ScriptedProxyHandler::handlerObject(const JSObject* proxy)
|
||||
{
|
||||
MOZ_ASSERT(proxy->as<ProxyObject>().handler() == &ScriptedProxyHandler::singleton);
|
||||
return proxy->as<ProxyObject>().extra(ScriptedProxyHandler::HANDLER_EXTRA).toObjectOrNull();
|
||||
return proxy->as<ProxyObject>().reservedSlot(ScriptedProxyHandler::HANDLER_EXTRA).toObjectOrNull();
|
||||
}
|
||||
|
||||
// ES8 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 7.3.9 GetMethod,
|
||||
@ -1287,7 +1287,7 @@ bool
|
||||
ScriptedProxyHandler::isCallable(JSObject* obj) const
|
||||
{
|
||||
MOZ_ASSERT(obj->as<ProxyObject>().handler() == &ScriptedProxyHandler::singleton);
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().extra(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().reservedSlot(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
return !!(callConstruct & IS_CALLABLE);
|
||||
}
|
||||
|
||||
@ -1295,7 +1295,7 @@ bool
|
||||
ScriptedProxyHandler::isConstructor(JSObject* obj) const
|
||||
{
|
||||
MOZ_ASSERT(obj->as<ProxyObject>().handler() == &ScriptedProxyHandler::singleton);
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().extra(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
uint32_t callConstruct = obj->as<ProxyObject>().reservedSlot(IS_CALLCONSTRUCT_EXTRA).toPrivateUint32();
|
||||
return !!(callConstruct & IS_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
@ -1350,13 +1350,13 @@ ProxyCreate(JSContext* cx, CallArgs& args, const char* callerName)
|
||||
|
||||
// Step 9 (reordered).
|
||||
Rooted<ProxyObject*> proxy(cx, &proxy_->as<ProxyObject>());
|
||||
proxy->setExtra(ScriptedProxyHandler::HANDLER_EXTRA, ObjectValue(*handler));
|
||||
proxy->setReservedSlot(ScriptedProxyHandler::HANDLER_EXTRA, ObjectValue(*handler));
|
||||
|
||||
// Step 7.
|
||||
uint32_t callable = target->isCallable() ? ScriptedProxyHandler::IS_CALLABLE : 0;
|
||||
uint32_t constructor = target->isConstructor() ? ScriptedProxyHandler::IS_CONSTRUCTOR : 0;
|
||||
proxy->setExtra(ScriptedProxyHandler::IS_CALLCONSTRUCT_EXTRA,
|
||||
PrivateUint32Value(callable | constructor));
|
||||
proxy->setReservedSlot(ScriptedProxyHandler::IS_CALLCONSTRUCT_EXTRA,
|
||||
PrivateUint32Value(callable | constructor));
|
||||
|
||||
// Step 10.
|
||||
args.rval().setObject(*proxy);
|
||||
@ -1388,7 +1388,7 @@ RevokeProxy(JSContext* cx, unsigned argc, Value* vp)
|
||||
MOZ_ASSERT(p->is<ProxyObject>());
|
||||
|
||||
p->as<ProxyObject>().setSameCompartmentPrivate(NullValue());
|
||||
p->as<ProxyObject>().setExtra(ScriptedProxyHandler::HANDLER_EXTRA, NullValue());
|
||||
p->as<ProxyObject>().setReservedSlot(ScriptedProxyHandler::HANDLER_EXTRA, NullValue());
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
|
@ -0,0 +1,21 @@
|
||||
function assertSyntaxError(code) {
|
||||
assertThrowsInstanceOf(() => { Function(code); }, SyntaxError, "Function:" + code);
|
||||
assertThrowsInstanceOf(() => { eval(code); }, SyntaxError, "eval:" + code);
|
||||
var ieval = eval;
|
||||
assertThrowsInstanceOf(() => { ieval(code); }, SyntaxError, "indirect eval:" + code);
|
||||
}
|
||||
|
||||
assertSyntaxError(`({async async: 0})`);
|
||||
assertSyntaxError(`({async async})`);
|
||||
assertSyntaxError(`({async async, })`);
|
||||
assertSyntaxError(`({async async = 0} = {})`);
|
||||
|
||||
for (let decl of ["var", "let", "const"]) {
|
||||
assertSyntaxError(`${decl} {async async: a} = {}`);
|
||||
assertSyntaxError(`${decl} {async async} = {}`);
|
||||
assertSyntaxError(`${decl} {async async, } = {}`);
|
||||
assertSyntaxError(`${decl} {async async = 0} = {}`);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
18
js/src/tests/ecma_7/Array/slice-sparse-with-large-index.js
Normal file
18
js/src/tests/ecma_7/Array/slice-sparse-with-large-index.js
Normal file
@ -0,0 +1,18 @@
|
||||
var array = [];
|
||||
array[2**31 - 2] = "INT32_MAX - 1";
|
||||
array[2**31 - 1] = "INT32_MAX";
|
||||
array[2**31 - 0] = "INT32_MAX + 1";
|
||||
array[2**32 - 2] = "UINT32_MAX - 1";
|
||||
array[2**32 - 1] = "UINT32_MAX";
|
||||
array[2**32 - 0] = "UINT32_MAX + 1";
|
||||
|
||||
var copy = array.slice();
|
||||
assertEq(copy[2**31 - 2], "INT32_MAX - 1");
|
||||
assertEq(copy[2**31 - 1], "INT32_MAX");
|
||||
assertEq(copy[2**31 - 0], "INT32_MAX + 1");
|
||||
assertEq(copy[2**32 - 2], "UINT32_MAX - 1");
|
||||
assertEq(copy[2**32 - 1], undefined);
|
||||
assertEq(copy[2**32 - 0], undefined);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -2268,8 +2268,8 @@ DebugEnvironmentProxy::create(JSContext* cx, EnvironmentObject& env, HandleObjec
|
||||
return nullptr;
|
||||
|
||||
DebugEnvironmentProxy* debugEnv = &obj->as<DebugEnvironmentProxy>();
|
||||
debugEnv->setExtra(ENCLOSING_EXTRA, ObjectValue(*enclosing));
|
||||
debugEnv->setExtra(SNAPSHOT_EXTRA, NullValue());
|
||||
debugEnv->setReservedSlot(ENCLOSING_SLOT, ObjectValue(*enclosing));
|
||||
debugEnv->setReservedSlot(SNAPSHOT_SLOT, NullValue());
|
||||
|
||||
return debugEnv;
|
||||
}
|
||||
@ -2283,13 +2283,13 @@ DebugEnvironmentProxy::environment() const
|
||||
JSObject&
|
||||
DebugEnvironmentProxy::enclosingEnvironment() const
|
||||
{
|
||||
return extra(ENCLOSING_EXTRA).toObject();
|
||||
return reservedSlot(ENCLOSING_SLOT).toObject();
|
||||
}
|
||||
|
||||
ArrayObject*
|
||||
DebugEnvironmentProxy::maybeSnapshot() const
|
||||
{
|
||||
JSObject* obj = extra(SNAPSHOT_EXTRA).toObjectOrNull();
|
||||
JSObject* obj = reservedSlot(SNAPSHOT_SLOT).toObjectOrNull();
|
||||
return obj ? &obj->as<ArrayObject>() : nullptr;
|
||||
}
|
||||
|
||||
@ -2297,7 +2297,7 @@ void
|
||||
DebugEnvironmentProxy::initSnapshot(ArrayObject& o)
|
||||
{
|
||||
MOZ_ASSERT(maybeSnapshot() == nullptr);
|
||||
setExtra(SNAPSHOT_EXTRA, ObjectValue(o));
|
||||
setReservedSlot(SNAPSHOT_SLOT, ObjectValue(o));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -872,13 +872,13 @@ class DebugEnvironmentProxy : public ProxyObject
|
||||
* The enclosing environment on the dynamic environment chain. This slot is analogous
|
||||
* to the ENCLOSING_ENV_SLOT of a EnvironmentObject.
|
||||
*/
|
||||
static const unsigned ENCLOSING_EXTRA = 0;
|
||||
static const unsigned ENCLOSING_SLOT = 0;
|
||||
|
||||
/*
|
||||
* NullValue or a dense array holding the unaliased variables of a function
|
||||
* frame that has been popped.
|
||||
*/
|
||||
static const unsigned SNAPSHOT_EXTRA = 1;
|
||||
static const unsigned SNAPSHOT_SLOT = 1;
|
||||
|
||||
public:
|
||||
static DebugEnvironmentProxy* create(JSContext* cx, EnvironmentObject& env,
|
||||
|
@ -15,12 +15,18 @@
|
||||
using namespace js;
|
||||
|
||||
static gc::AllocKind
|
||||
GetProxyGCObjectKind(const BaseProxyHandler* handler, const Value& priv)
|
||||
GetProxyGCObjectKind(const Class* clasp, const BaseProxyHandler* handler, const Value& priv)
|
||||
{
|
||||
static_assert(sizeof(js::detail::ProxyValueArray) % sizeof(js::HeapSlot) == 0,
|
||||
"ProxyValueArray must be a multiple of HeapSlot");
|
||||
MOZ_ASSERT(clasp->isProxy());
|
||||
|
||||
uint32_t nslots = sizeof(js::detail::ProxyValueArray) / sizeof(HeapSlot);
|
||||
uint32_t nreserved = JSCLASS_RESERVED_SLOTS(clasp);
|
||||
MOZ_ASSERT(nreserved > 0);
|
||||
|
||||
MOZ_ASSERT(js::detail::ProxyValueArray::sizeOf(nreserved) % sizeof(Value) == 0,
|
||||
"ProxyValueArray must be a multiple of Value");
|
||||
|
||||
uint32_t nslots = js::detail::ProxyValueArray::sizeOf(nreserved) / sizeof(Value);
|
||||
MOZ_ASSERT(nslots <= NativeObject::MAX_FIXED_SLOTS);
|
||||
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(nslots);
|
||||
if (handler->finalizeInBackground(priv))
|
||||
@ -68,7 +74,7 @@ ProxyObject::New(JSContext* cx, const BaseProxyHandler* handler, HandleValue pri
|
||||
newKind = TenuredObject;
|
||||
}
|
||||
|
||||
gc::AllocKind allocKind = GetProxyGCObjectKind(handler, priv);
|
||||
gc::AllocKind allocKind = GetProxyGCObjectKind(clasp, handler, priv);
|
||||
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
// Note: this will initialize the object's |data| to strange values, but we
|
||||
@ -77,7 +83,10 @@ ProxyObject::New(JSContext* cx, const BaseProxyHandler* handler, HandleValue pri
|
||||
JS_TRY_VAR_OR_RETURN_NULL(cx, proxy, create(cx, clasp, proto, allocKind, newKind));
|
||||
|
||||
proxy->setInlineValueArray();
|
||||
new (proxy->data.values) detail::ProxyValueArray;
|
||||
|
||||
detail::ProxyValueArray* values = detail::GetProxyDataLayout(proxy)->values();
|
||||
values->init(proxy->numReservedSlots());
|
||||
|
||||
proxy->data.handler = handler;
|
||||
proxy->setCrossCompartmentPrivate(priv);
|
||||
|
||||
@ -93,7 +102,7 @@ ProxyObject::allocKindForTenure() const
|
||||
{
|
||||
MOZ_ASSERT(usingInlineValueArray());
|
||||
Value priv = const_cast<ProxyObject*>(this)->private_();
|
||||
return GetProxyGCObjectKind(data.handler, priv);
|
||||
return GetProxyGCObjectKind(getClass(), data.handler, priv);
|
||||
}
|
||||
|
||||
void
|
||||
@ -133,7 +142,7 @@ ProxyObject::nuke()
|
||||
setHandler(DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton());
|
||||
}
|
||||
|
||||
// The proxy's extra slots are not cleared and will continue to be
|
||||
// The proxy's reserved slots are not cleared and will continue to be
|
||||
// traced. This avoids the possibility of triggering write barriers while
|
||||
// nuking proxies in dead compartments which could otherwise cause those
|
||||
// compartments to be kept alive. Note that these are slots cannot hold
|
||||
@ -190,19 +199,6 @@ ProxyObject::create(JSContext* cx, const Class* clasp, Handle<TaggedProto> proto
|
||||
return pobj;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyObject::initExternalValueArrayAfterSwap(JSContext* cx, const detail::ProxyValueArray& src)
|
||||
{
|
||||
MOZ_ASSERT(getClass()->isProxy());
|
||||
|
||||
auto* values = cx->zone()->new_<detail::ProxyValueArray>(src);
|
||||
if (!values)
|
||||
return false;
|
||||
|
||||
data.values = values;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetValueInProxy(Value* slot, const Value& value)
|
||||
{
|
||||
|
@ -29,6 +29,8 @@ class ProxyObject : public ShapedObject
|
||||
"proxy object size must match GC thing size");
|
||||
static_assert(offsetof(ProxyObject, data) == detail::ProxyDataOffset,
|
||||
"proxy object layout must match shadow interface");
|
||||
static_assert(offsetof(ProxyObject, data.reservedSlots) == offsetof(shadow::Object, slots),
|
||||
"Proxy reservedSlots must overlay native object slots field");
|
||||
}
|
||||
|
||||
static JS::Result<ProxyObject*, JS::OOM&>
|
||||
@ -46,12 +48,12 @@ class ProxyObject : public ShapedObject
|
||||
return (void*)(uintptr_t(this) + sizeof(ProxyObject));
|
||||
}
|
||||
bool usingInlineValueArray() const {
|
||||
return data.values == inlineDataStart();
|
||||
return data.values() == inlineDataStart();
|
||||
}
|
||||
void setInlineValueArray() {
|
||||
data.values = reinterpret_cast<detail::ProxyValueArray*>(inlineDataStart());
|
||||
data.reservedSlots = &reinterpret_cast<detail::ProxyValueArray*>(inlineDataStart())->reservedSlots;
|
||||
}
|
||||
MOZ_MUST_USE bool initExternalValueArrayAfterSwap(JSContext* cx, const detail::ProxyValueArray& src);
|
||||
MOZ_MUST_USE bool initExternalValueArrayAfterSwap(JSContext* cx, const Vector<Value>& values);
|
||||
|
||||
const Value& private_() {
|
||||
return GetProxyPrivate(this);
|
||||
@ -61,7 +63,7 @@ class ProxyObject : public ShapedObject
|
||||
void setSameCompartmentPrivate(const Value& priv);
|
||||
|
||||
GCPtrValue* slotOfPrivate() {
|
||||
return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->values->privateSlot);
|
||||
return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->values()->privateSlot);
|
||||
}
|
||||
|
||||
JSObject* target() const {
|
||||
@ -76,31 +78,29 @@ class ProxyObject : public ShapedObject
|
||||
SetProxyHandler(this, handler);
|
||||
}
|
||||
|
||||
static size_t offsetOfValues() {
|
||||
return offsetof(ProxyObject, data.values);
|
||||
static size_t offsetOfReservedSlots() {
|
||||
return offsetof(ProxyObject, data.reservedSlots);
|
||||
}
|
||||
static size_t offsetOfHandler() {
|
||||
return offsetof(ProxyObject, data.handler);
|
||||
}
|
||||
static size_t offsetOfExtraSlotInValues(size_t slot) {
|
||||
MOZ_ASSERT(slot < detail::PROXY_EXTRA_SLOTS);
|
||||
return offsetof(detail::ProxyValueArray, extraSlots) + slot * sizeof(Value);
|
||||
|
||||
size_t numReservedSlots() const {
|
||||
return JSCLASS_RESERVED_SLOTS(getClass());
|
||||
}
|
||||
const Value& reservedSlot(size_t n) const {
|
||||
return GetProxyReservedSlot(const_cast<ProxyObject*>(this), n);
|
||||
}
|
||||
|
||||
const Value& extra(size_t n) const {
|
||||
return GetProxyExtra(const_cast<ProxyObject*>(this), n);
|
||||
}
|
||||
|
||||
void setExtra(size_t n, const Value& extra) {
|
||||
SetProxyExtra(this, n, extra);
|
||||
void setReservedSlot(size_t n, const Value& extra) {
|
||||
SetProxyReservedSlot(this, n, extra);
|
||||
}
|
||||
|
||||
gc::AllocKind allocKindForTenure() const;
|
||||
|
||||
private:
|
||||
GCPtrValue* slotOfExtra(size_t n) {
|
||||
MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
|
||||
return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->values->extraSlots[n]);
|
||||
GCPtrValue* reservedSlotPtr(size_t n) {
|
||||
return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->reservedSlots->slots[n]);
|
||||
}
|
||||
|
||||
static bool isValidProxyClass(const Class* clasp) {
|
||||
@ -116,7 +116,7 @@ class ProxyObject : public ShapedObject
|
||||
}
|
||||
|
||||
public:
|
||||
static unsigned grayLinkExtraSlot(JSObject* obj);
|
||||
static unsigned grayLinkReservedSlot(JSObject* obj);
|
||||
|
||||
void renew(const BaseProxyHandler* handler, const Value& priv);
|
||||
|
||||
|
@ -114,7 +114,14 @@
|
||||
* a single BaseShape.
|
||||
*/
|
||||
|
||||
#define JSSLOT_FREE(clasp) JSCLASS_RESERVED_SLOTS(clasp)
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
JSSLOT_FREE(const js::Class* clasp)
|
||||
{
|
||||
// Proxy classes have reserved slots, but proxies manage their own slot
|
||||
// layout.
|
||||
MOZ_ASSERT(!clasp->isProxy());
|
||||
return JSCLASS_RESERVED_SLOTS(clasp);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -919,7 +926,10 @@ class Shape : public gc::TenuredCell
|
||||
|
||||
uint32_t slotSpan(const Class* clasp) const {
|
||||
MOZ_ASSERT(!inDictionary());
|
||||
uint32_t free = JSSLOT_FREE(clasp);
|
||||
// Proxy classes have reserved slots, but proxies manage their own slot
|
||||
// layout. This means all non-native object shapes have nfixed == 0 and
|
||||
// slotSpan == 0.
|
||||
uint32_t free = clasp->isProxy() ? 0 : JSSLOT_FREE(clasp);
|
||||
return hasMissingSlot() ? free : Max(free, maybeSlot() + 1);
|
||||
}
|
||||
|
||||
@ -1324,11 +1334,6 @@ struct StackShape
|
||||
uint32_t slot() const { MOZ_ASSERT(hasSlot() && !hasMissingSlot()); return slot_; }
|
||||
uint32_t maybeSlot() const { return slot_; }
|
||||
|
||||
uint32_t slotSpan() const {
|
||||
uint32_t free = JSSLOT_FREE(base->clasp_);
|
||||
return hasMissingSlot() ? free : (maybeSlot() + 1);
|
||||
}
|
||||
|
||||
void setSlot(uint32_t slot) {
|
||||
MOZ_ASSERT(slot <= SHAPE_INVALID_SLOT);
|
||||
slot_ = slot;
|
||||
|
@ -716,8 +716,8 @@ WrapCallable(JSContext* cx, HandleObject callable, HandleObject sandboxProtoProx
|
||||
JSObject* obj = js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
|
||||
priv, nullptr, options);
|
||||
if (obj) {
|
||||
js::SetProxyExtra(obj, SandboxCallableProxyHandler::SandboxProxySlot,
|
||||
ObjectValue(*sandboxProtoProxy));
|
||||
js::SetProxyReservedSlot(obj, SandboxCallableProxyHandler::SandboxProxySlot,
|
||||
ObjectValue(*sandboxProtoProxy));
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -1318,14 +1318,14 @@ bool CloneExpandoChain(JSContext* cx, JSObject* dstArg, JSObject* srcArg)
|
||||
static JSObject*
|
||||
GetHolder(JSObject* obj)
|
||||
{
|
||||
return &js::GetProxyExtra(obj, 0).toObject();
|
||||
return &js::GetProxyReservedSlot(obj, 0).toObject();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
XrayTraits::getHolder(JSObject* wrapper)
|
||||
{
|
||||
MOZ_ASSERT(WrapperFactory::IsXrayWrapper(wrapper));
|
||||
js::Value v = js::GetProxyExtra(wrapper, 0);
|
||||
js::Value v = js::GetProxyReservedSlot(wrapper, 0);
|
||||
return v.isObject() ? &v.toObject() : nullptr;
|
||||
}
|
||||
|
||||
@ -1337,7 +1337,7 @@ XrayTraits::ensureHolder(JSContext* cx, HandleObject wrapper)
|
||||
return holder;
|
||||
holder = createHolder(cx, wrapper); // virtual trap.
|
||||
if (holder)
|
||||
js::SetProxyExtra(wrapper, 0, ObjectValue(*holder));
|
||||
js::SetProxyReservedSlot(wrapper, 0, ObjectValue(*holder));
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
@ -588,7 +588,7 @@ public:
|
||||
|
||||
static inline JSObject* getSandboxProxy(JS::Handle<JSObject*> proxy)
|
||||
{
|
||||
return &js::GetProxyExtra(proxy, SandboxProxySlot).toObject();
|
||||
return &js::GetProxyReservedSlot(proxy, SandboxProxySlot).toObject();
|
||||
}
|
||||
};
|
||||
|
||||
|
31
layout/reftests/canvas/1353000-1-ref.html
Normal file
31
layout/reftests/canvas/1353000-1-ref.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function draw(id, r, c) {
|
||||
var txt = "TryToTaLLY-" + id + "__________" + r;
|
||||
var ctx = document.getElementById(id).getContext('2d');
|
||||
ctx.font = '15px Arial';
|
||||
ctx.fillStyle = c;
|
||||
if (r) {
|
||||
ctx.save();
|
||||
ctx.rotate(Math.PI / 4);
|
||||
ctx.fillText(txt, 200, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.fillText(txt, 10, 20);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
canvas { border: 1px solid silver; margin: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="float:left; transform: translate(300px, 150px) scale(3)">
|
||||
<canvas id="c1" width="120" height="50"></canvas>
|
||||
</div>
|
||||
<script>
|
||||
draw("c1", false, "red");
|
||||
draw("c1", false, "green");
|
||||
</script>
|
||||
</body>
|
31
layout/reftests/canvas/1353000-1.html
Normal file
31
layout/reftests/canvas/1353000-1.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function draw(id, r, c) {
|
||||
var txt = "TryToTaLLY-" + id + "__________" + r;
|
||||
var ctx = document.getElementById(id).getContext('2d');
|
||||
ctx.font = '15px Arial';
|
||||
ctx.fillStyle = c;
|
||||
if (r) {
|
||||
ctx.save();
|
||||
ctx.rotate(Math.PI / 4);
|
||||
ctx.fillText(txt, 200, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.fillText(txt, 10, 20);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
canvas { border: 1px solid silver; margin: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="float:left; transform: translate(300px, 150px) scale(3)">
|
||||
<canvas id="c1" width="120" height="50"></canvas>
|
||||
</div>
|
||||
<script>
|
||||
draw("c1", true, "red");
|
||||
draw("c1", false, "green");
|
||||
</script>
|
||||
</body>
|
@ -113,3 +113,4 @@ fuzzy-if(winWidget,94,1575) fuzzy-if(cocoaWidget,1,24) == 1304353-text-global-co
|
||||
== text-indent-1b.html text-indent-1-ref.html
|
||||
|
||||
== 1347147-1.html 1347147-1-ref.html
|
||||
== 1353000-1.html 1353000-1-ref.html
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
fill: lime;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
fill: lime;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
fill: rgb(0% 100% 0% / 50%);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
fill: lime;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
||||
#img1 {
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: fill;
|
||||
fill: lime;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test context-fill when no context fill is provided</title>
|
||||
<title>Test context-fill when no context fill value is provided</title>
|
||||
<style>
|
||||
|
||||
img {
|
||||
-moz-context-properties: fill;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ div {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' fill='context-fill red'/></svg>");
|
||||
-moz-context-properties: fill;
|
||||
fill: blue;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
stroke: lime;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
stroke: lime;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
stroke: rgb(0% 100% 0% / 50%);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
stroke: lime;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
}
|
||||
|
||||
#img1 {
|
||||
|
@ -7,6 +7,7 @@
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
-moz-context-properties: stroke;
|
||||
stroke: lime;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test context-stroke when no context stroke is provided</title>
|
||||
<title>Test context-stroke when no context stroke value is provided</title>
|
||||
<style>
|
||||
|
||||
img {
|
||||
-moz-context-properties: fill;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border: 1px solid black;
|
||||
|
@ -8,6 +8,7 @@ div {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><rect x='5' y='5' width='90' height='90' fill='none' stroke='context-stroke red' stroke-width='10'/></svg>");
|
||||
-moz-context-properties: stroke;
|
||||
stroke: blue;
|
||||
}
|
||||
|
||||
|
@ -56,29 +56,29 @@ fuzzy(1,2) fuzzy-if(azureSkia,1,40000) == canvas-drawImage-alpha-2.html canvas-d
|
||||
|
||||
# Context paint tests (this feature is currently not part of any spec.)
|
||||
# context-fill:
|
||||
== context-fill-01.html blue100x100-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-01.html lime100x100-ref.html
|
||||
== context-fill-02.html transparent100x100-w-border-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-02.html lime100x100-w-border-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-03.html lime100x100-50pct-ref.html
|
||||
skip-if(stylo) == context-fill-01.html blue100x100-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-01.html lime100x100-ref.html
|
||||
skip-if(stylo) == context-fill-02.html transparent100x100-w-border-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-02.html lime100x100-w-border-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-03.html lime100x100-50pct-ref.html
|
||||
# fuzz because on win8 the r & b components are off by one
|
||||
fuzzy-if(winWidget,1,10000) test-pref(svg.context-properties.content.enabled,true) == context-fill-04.html lime100x100-50pct-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-05.html context-fill-or-stroke-05-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-06.html lime100x100-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-07.html context-fill-07-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-fill-bg-image-01.html blue100x100-ref.html
|
||||
skip-if(stylo) fuzzy-if(winWidget,1,10000) test-pref(svg.context-properties.content.enabled,true) == context-fill-04.html lime100x100-50pct-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-05.html context-fill-or-stroke-05-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-06.html lime100x100-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-07.html context-fill-07-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-fill-bg-image-01.html blue100x100-ref.html
|
||||
# context-stroke:
|
||||
== context-stroke-01.html blue100x100-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-01.html lime100x100-ref.html
|
||||
== context-stroke-02.html transparent100x100-w-border-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-02.html lime100x100-w-border-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-03.html lime100x100-50pct-ref.html
|
||||
skip-if(stylo) == context-stroke-01.html blue100x100-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-01.html lime100x100-ref.html
|
||||
skip-if(stylo) == context-stroke-02.html transparent100x100-w-border-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-02.html lime100x100-w-border-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-03.html lime100x100-50pct-ref.html
|
||||
# fuzz because on win8 the r & b components are off by one
|
||||
fuzzy-if(winWidget,1,10000) test-pref(svg.context-properties.content.enabled,true) == context-stroke-04.html lime100x100-50pct-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-05.html context-fill-or-stroke-05-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-06.html lime100x100-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-07.html context-stroke-07-ref.html
|
||||
test-pref(svg.context-properties.content.enabled,true) == context-stroke-bg-image-01.html blue100x100-border-ref.html
|
||||
skip-if(stylo) fuzzy-if(winWidget,1,10000) test-pref(svg.context-properties.content.enabled,true) == context-stroke-04.html lime100x100-50pct-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-05.html context-fill-or-stroke-05-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-06.html lime100x100-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-07.html context-stroke-07-ref.html
|
||||
skip-if(stylo) test-pref(svg.context-properties.content.enabled,true) == context-stroke-bg-image-01.html blue100x100-border-ref.html
|
||||
|
||||
# Simple <img> tests
|
||||
== img-simple-1.html lime100x100-ref.html
|
||||
|
@ -49,6 +49,7 @@ CSS_KEY(-moz-cellhighlighttext, _moz_cellhighlighttext)
|
||||
CSS_KEY(-moz-center, _moz_center)
|
||||
CSS_KEY(-moz-combobox, _moz_combobox)
|
||||
CSS_KEY(-moz-comboboxtext, _moz_comboboxtext)
|
||||
CSS_KEY(-moz-context-properties, _moz_context_properties)
|
||||
CSS_KEY(-moz-block-height, _moz_block_height)
|
||||
CSS_KEY(-moz-deck, _moz_deck)
|
||||
CSS_KEY(-moz-default-background-color, _moz_default_background_color)
|
||||
|
@ -924,6 +924,7 @@ protected:
|
||||
uint32_t& aVariantMask,
|
||||
bool *aHadFinalWS);
|
||||
bool ParseCalcTerm(nsCSSValue& aValue, uint32_t& aVariantMask);
|
||||
bool ParseContextProperties();
|
||||
bool RequireWhitespace();
|
||||
|
||||
// For "flex" shorthand property, defined in CSS Flexbox spec
|
||||
@ -8064,6 +8065,50 @@ CSSParserImpl::ParseCounter(nsCSSValue& aValue)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseContextProperties()
|
||||
{
|
||||
nsCSSValue listValue;
|
||||
nsCSSValueList* currentListValue = listValue.SetListValue();
|
||||
bool first = true;
|
||||
for (;;) {
|
||||
const uint32_t variantMask = VARIANT_IDENTIFIER |
|
||||
VARIANT_INHERIT |
|
||||
VARIANT_NONE;
|
||||
nsCSSValue value;
|
||||
if (!ParseSingleTokenVariant(value, variantMask, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.GetUnit() != eCSSUnit_Ident) {
|
||||
if (first) {
|
||||
AppendValue(eCSSProperty__moz_context_properties, value);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
value.AtomizeIdentValue();
|
||||
nsIAtom* atom = value.GetAtomValue();
|
||||
if (atom == nsGkAtoms::_default) {
|
||||
return false;
|
||||
}
|
||||
|
||||
currentListValue->mValue = Move(value);
|
||||
|
||||
if (!ExpectSymbol(',', true)) {
|
||||
break;
|
||||
}
|
||||
currentListValue->mNext = new nsCSSValueList;
|
||||
currentListValue = currentListValue->mNext;
|
||||
first = false;
|
||||
}
|
||||
|
||||
AppendValue(eCSSProperty__moz_context_properties, listValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseAttr(nsCSSValue& aValue)
|
||||
{
|
||||
@ -11708,6 +11753,8 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSPropertyID aPropID)
|
||||
return ParseBorderSide(kColumnRuleIDs, false);
|
||||
case eCSSProperty_content:
|
||||
return ParseContent();
|
||||
case eCSSProperty__moz_context_properties:
|
||||
return ParseContextProperties();
|
||||
case eCSSProperty_counter_increment:
|
||||
case eCSSProperty_counter_reset:
|
||||
return ParseCounterData(aPropID);
|
||||
|
@ -1616,6 +1616,19 @@ CSS_PROP_CONTENT(
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
|
||||
CSS_PROP_SVG(
|
||||
// Only intended to be used internally by Mozilla, so prefixed.
|
||||
-moz-context-properties,
|
||||
_moz_context_properties,
|
||||
CSS_PROP_DOMPROP_PREFIXED(ContextProperties),
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
|
||||
CSS_PROPERTY_INTERNAL,
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_None)
|
||||
CSS_PROP_TEXT(
|
||||
-moz-control-character-visibility,
|
||||
_moz_control_character_visibility,
|
||||
|
@ -6463,6 +6463,27 @@ nsComputedDOMStyle::DoGetMaskType()
|
||||
return val.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetContextProperties()
|
||||
{
|
||||
const nsTArray<nsCOMPtr<nsIAtom>>& contextProps = StyleSVG()->mContextProps;
|
||||
|
||||
if (contextProps.IsEmpty()) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(eCSSKeyword_none);
|
||||
return val.forget();
|
||||
}
|
||||
|
||||
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
|
||||
for (const nsIAtom* ident : contextProps) {
|
||||
RefPtr<nsROCSSPrimitiveValue> property = new nsROCSSPrimitiveValue;
|
||||
property->SetString(nsDependentAtomString(ident));
|
||||
valueList->AppendCSSValue(property.forget());
|
||||
}
|
||||
|
||||
return valueList.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetPaintOrder()
|
||||
{
|
||||
|
@ -600,6 +600,8 @@ private:
|
||||
already_AddRefed<CSSValue> DoGetMaskType();
|
||||
already_AddRefed<CSSValue> DoGetPaintOrder();
|
||||
|
||||
already_AddRefed<CSSValue> DoGetContextProperties();
|
||||
|
||||
/* Custom properties */
|
||||
already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName);
|
||||
|
||||
|
@ -287,6 +287,7 @@ COMPUTED_STYLE_PROP(_moz_box_flex, BoxFlex)
|
||||
COMPUTED_STYLE_PROP(_moz_box_ordinal_group, BoxOrdinalGroup)
|
||||
COMPUTED_STYLE_PROP(_moz_box_orient, BoxOrient)
|
||||
COMPUTED_STYLE_PROP(_moz_box_pack, BoxPack)
|
||||
COMPUTED_STYLE_PROP(_moz_context_properties, ContextProperties)
|
||||
COMPUTED_STYLE_PROP(_moz_float_edge, FloatEdge)
|
||||
COMPUTED_STYLE_PROP(_moz_force_broken_image_icon, ForceBrokenImageIcon)
|
||||
COMPUTED_STYLE_PROP(_moz_image_region, ImageRegion)
|
||||
|
@ -9729,6 +9729,48 @@ nsRuleNode::ComputeSVGData(void* aStartStruct,
|
||||
parentSVG->mTextAnchor,
|
||||
NS_STYLE_TEXT_ANCHOR_START);
|
||||
|
||||
// -moz-context-properties:
|
||||
const nsCSSValue* contextPropsValue = aRuleData->ValueForContextProperties();
|
||||
switch (contextPropsValue->GetUnit()) {
|
||||
case eCSSUnit_Null:
|
||||
break;
|
||||
|
||||
case eCSSUnit_List:
|
||||
case eCSSUnit_ListDep: {
|
||||
svg->mContextProps.Clear();
|
||||
svg->mContextPropsBits = 0;
|
||||
for (const nsCSSValueList* item = contextPropsValue->GetListValue();
|
||||
item; item = item->mNext)
|
||||
{
|
||||
nsIAtom* atom = item->mValue.GetAtomValue();
|
||||
svg->mContextProps.AppendElement(atom);
|
||||
if (atom == nsGkAtoms::fill) {
|
||||
svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_FILL;
|
||||
} else if (atom == nsGkAtoms::stroke) {
|
||||
svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_STROKE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eCSSUnit_Inherit:
|
||||
svg->mContextProps.Clear();
|
||||
svg->mContextProps.AppendElements(parentSVG->mContextProps);
|
||||
svg->mContextPropsBits = parentSVG->mContextPropsBits;
|
||||
conditions.SetUncacheable();
|
||||
break;
|
||||
|
||||
case eCSSUnit_Initial:
|
||||
case eCSSUnit_None:
|
||||
case eCSSUnit_Unset:
|
||||
svg->mContextProps.Clear();
|
||||
svg->mContextPropsBits = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "unrecognized -moz-context-properties value");
|
||||
}
|
||||
|
||||
COMPUTE_END_INHERITED(SVG, svg)
|
||||
}
|
||||
|
||||
|
@ -1053,6 +1053,10 @@ enum class StyleGridTrackBreadth : uint8_t {
|
||||
|
||||
// See nsStyleSVG
|
||||
|
||||
// -moz-context-properties
|
||||
#define NS_STYLE_CONTEXT_PROPERTY_FILL (1 << 0)
|
||||
#define NS_STYLE_CONTEXT_PROPERTY_STROKE (1 << 1)
|
||||
|
||||
// dominant-baseline
|
||||
#define NS_STYLE_DOMINANT_BASELINE_AUTO 0
|
||||
#define NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT 1
|
||||
|
@ -876,6 +876,7 @@ nsStyleSVG::nsStyleSVG(const nsPresContext* aContext)
|
||||
, mStrokeLinecap(NS_STYLE_STROKE_LINECAP_BUTT)
|
||||
, mStrokeLinejoin(NS_STYLE_STROKE_LINEJOIN_MITER)
|
||||
, mTextAnchor(NS_STYLE_TEXT_ANCHOR_START)
|
||||
, mContextPropsBits(0)
|
||||
, mContextFlags((eStyleSVGOpacitySource_Normal << FILL_OPACITY_SOURCE_SHIFT) |
|
||||
(eStyleSVGOpacitySource_Normal << STROKE_OPACITY_SOURCE_SHIFT))
|
||||
{
|
||||
@ -894,6 +895,7 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
|
||||
, mMarkerMid(aSource.mMarkerMid)
|
||||
, mMarkerStart(aSource.mMarkerStart)
|
||||
, mStrokeDasharray(aSource.mStrokeDasharray)
|
||||
, mContextProps(aSource.mContextProps)
|
||||
, mStrokeDashoffset(aSource.mStrokeDashoffset)
|
||||
, mStrokeWidth(aSource.mStrokeWidth)
|
||||
, mFillOpacity(aSource.mFillOpacity)
|
||||
@ -908,6 +910,7 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
|
||||
, mStrokeLinecap(aSource.mStrokeLinecap)
|
||||
, mStrokeLinejoin(aSource.mStrokeLinejoin)
|
||||
, mTextAnchor(aSource.mTextAnchor)
|
||||
, mContextPropsBits(aSource.mContextPropsBits)
|
||||
, mContextFlags(aSource.mContextFlags)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsStyleSVG);
|
||||
@ -992,10 +995,17 @@ nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
|
||||
mPaintOrder != aNewData.mPaintOrder ||
|
||||
mShapeRendering != aNewData.mShapeRendering ||
|
||||
mStrokeDasharray != aNewData.mStrokeDasharray ||
|
||||
mContextFlags != aNewData.mContextFlags) {
|
||||
mContextFlags != aNewData.mContextFlags ||
|
||||
mContextPropsBits != aNewData.mContextPropsBits) {
|
||||
return hint | nsChangeHint_RepaintFrame;
|
||||
}
|
||||
|
||||
if (!hint) {
|
||||
if (mContextProps != aNewData.mContextProps) {
|
||||
hint = nsChangeHint_NeutralChange;
|
||||
}
|
||||
}
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
|
@ -3468,6 +3468,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
|
||||
RefPtr<mozilla::css::URLValue> mMarkerMid; // [inherited]
|
||||
RefPtr<mozilla::css::URLValue> mMarkerStart; // [inherited]
|
||||
nsTArray<nsStyleCoord> mStrokeDasharray; // [inherited] coord, percent, factor
|
||||
nsTArray<nsCOMPtr<nsIAtom>> mContextProps;
|
||||
|
||||
nsStyleCoord mStrokeDashoffset; // [inherited] coord, percent, factor
|
||||
nsStyleCoord mStrokeWidth; // [inherited] coord, percent, factor
|
||||
@ -3485,6 +3486,15 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
|
||||
uint8_t mStrokeLinecap; // [inherited] see nsStyleConsts.h
|
||||
uint8_t mStrokeLinejoin; // [inherited] see nsStyleConsts.h
|
||||
uint8_t mTextAnchor; // [inherited] see nsStyleConsts.h
|
||||
uint8_t mContextPropsBits; // [inherited] see nsStyleConsts.h.
|
||||
// Stores a bitfield representation of
|
||||
// the specified properties.
|
||||
|
||||
/// Returns true if style has been set to expose the computed values of
|
||||
/// certain properties (such as 'fill') to the contents of any linked images.
|
||||
bool ExposesContextProperties() const {
|
||||
return bool(mContextPropsBits);
|
||||
}
|
||||
|
||||
nsStyleSVGOpacitySource FillOpacitySource() const {
|
||||
uint8_t value = (mContextFlags & FILL_OPACITY_SOURCE_MASK) >>
|
||||
|
@ -106,6 +106,7 @@ const char *gInaccessibleProperties[] = {
|
||||
"-x-span",
|
||||
"-x-system-font",
|
||||
"-x-text-zoom",
|
||||
"-moz-context-properties",
|
||||
"-moz-control-character-visibility",
|
||||
"-moz-script-level", // parsed by UA sheets only
|
||||
"-moz-script-size-multiplier",
|
||||
|
@ -7872,4 +7872,13 @@ if (false) {
|
||||
other_values: [ "none", "menu", "tooltip", "sheet" ],
|
||||
invalid_values: []
|
||||
};
|
||||
|
||||
gCSSProperties["-moz-context-properties"] = {
|
||||
//domProp: "MozContextProperties",
|
||||
inherited: true,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "none" ],
|
||||
other_values: [ "fill", "stroke", "fill, stroke", "fill, stroke, fill", "fill, foo", "foo" ],
|
||||
invalid_values: [ "default", "fill, auto", "all, stroke", "none, fill", "fill, none", "fill, default", "2px" ]
|
||||
};
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleStruct.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -30,6 +31,12 @@ SVGImageContext::MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
|
||||
sEnabledForContentCached = true;
|
||||
}
|
||||
|
||||
if (!aFromFrame->StyleSVG()->ExposesContextProperties()) {
|
||||
// Content must have '-moz-context-properties' set to the names of the
|
||||
// properties it wants to expose to images it links to.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sEnabledForContent &&
|
||||
!nsContentUtils::IsChromeDoc(aFromFrame->PresContext()->Document())) {
|
||||
// Context paint is pref'ed off for content and this is a content doc.
|
||||
@ -41,8 +48,6 @@ SVGImageContext::MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX return early if the 'context-properties' property is not set.
|
||||
|
||||
bool haveContextPaint = false;
|
||||
|
||||
RefPtr<SVGEmbeddingContextPaint> contextPaint = new SVGEmbeddingContextPaint();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user