mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
b25476080d
@ -1007,16 +1007,8 @@ pref("security.exthelperapp.disable_background_handling", true);
|
|||||||
// Inactivity time in milliseconds after which we shut down the OS.File worker.
|
// Inactivity time in milliseconds after which we shut down the OS.File worker.
|
||||||
pref("osfile.reset_worker_delay", 5000);
|
pref("osfile.reset_worker_delay", 5000);
|
||||||
|
|
||||||
// APZC preferences.
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
pref("apz.allow_zooming", true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Gaia relies heavily on scroll events for now, so lets fire them
|
|
||||||
// more often than the default value (100).
|
|
||||||
pref("apz.pan_repaint_interval", 16);
|
|
||||||
|
|
||||||
// APZ physics settings, tuned by UX designers
|
// APZ physics settings, tuned by UX designers
|
||||||
|
pref("apz.axis_lock.mode", 2); // Use "sticky" axis locking
|
||||||
pref("apz.fling_curve_function_x1", "0.41");
|
pref("apz.fling_curve_function_x1", "0.41");
|
||||||
pref("apz.fling_curve_function_y1", "0.0");
|
pref("apz.fling_curve_function_y1", "0.0");
|
||||||
pref("apz.fling_curve_function_x2", "0.80");
|
pref("apz.fling_curve_function_x2", "0.80");
|
||||||
@ -1024,29 +1016,7 @@ pref("apz.fling_curve_function_y2", "1.0");
|
|||||||
pref("apz.fling_curve_threshold_inches_per_ms", "0.01");
|
pref("apz.fling_curve_threshold_inches_per_ms", "0.01");
|
||||||
pref("apz.fling_friction", "0.0019");
|
pref("apz.fling_friction", "0.0019");
|
||||||
pref("apz.max_velocity_inches_per_ms", "0.07");
|
pref("apz.max_velocity_inches_per_ms", "0.07");
|
||||||
pref("apz.touch_start_tolerance", "0.1");
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
pref("apz.touch_move_tolerance", "0.03");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Tweak default displayport values to reduce the risk of running out of
|
|
||||||
// memory when zooming in
|
|
||||||
pref("apz.x_skate_size_multiplier", "1.25");
|
|
||||||
pref("apz.y_skate_size_multiplier", "1.5");
|
|
||||||
pref("apz.x_stationary_size_multiplier", "1.5");
|
|
||||||
pref("apz.y_stationary_size_multiplier", "1.8");
|
|
||||||
pref("apz.enlarge_displayport_when_clipped", true);
|
|
||||||
// Use "sticky" axis locking
|
|
||||||
pref("apz.axis_lock.mode", 2);
|
|
||||||
|
|
||||||
// Overscroll-related settings
|
|
||||||
pref("apz.overscroll.enabled", true);
|
pref("apz.overscroll.enabled", true);
|
||||||
pref("apz.overscroll.stretch_factor", "0.35");
|
|
||||||
pref("apz.overscroll.spring_stiffness", "0.0018");
|
|
||||||
pref("apz.overscroll.spring_friction", "0.015");
|
|
||||||
pref("apz.overscroll.stop_distance_threshold", "5.0");
|
|
||||||
pref("apz.overscroll.stop_velocity_threshold", "0.01");
|
|
||||||
|
|
||||||
// For event-regions based hit-testing
|
// For event-regions based hit-testing
|
||||||
pref("layout.event-regions.enabled", true);
|
pref("layout.event-regions.enabled", true);
|
||||||
|
@ -29,17 +29,12 @@ function serializeServiceWorkerInfo(aServiceWorkerInfo) {
|
|||||||
|
|
||||||
let result = {};
|
let result = {};
|
||||||
|
|
||||||
Object.keys(aServiceWorkerInfo).forEach(property => {
|
result.principal = {
|
||||||
if (typeof aServiceWorkerInfo[property] == "function") {
|
origin: aServiceWorkerInfo.principal.originNoSuffix,
|
||||||
return;
|
originAttributes: aServiceWorkerInfo.principal.originAttributes
|
||||||
}
|
};
|
||||||
if (property === "principal") {
|
|
||||||
result.principal = {
|
["scope", "scriptSpec"].forEach(property => {
|
||||||
origin: aServiceWorkerInfo.principal.originNoSuffix,
|
|
||||||
originAttributes: aServiceWorkerInfo.principal.originAttributes
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result[property] = aServiceWorkerInfo[property];
|
result[property] = aServiceWorkerInfo[property];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -761,7 +761,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the browser was playing audio, we should remove the playing state.
|
// If the browser was playing audio, we should remove the playing state.
|
||||||
if (this.mTab.hasAttribute("soundplaying")) {
|
if (this.mTab.hasAttribute("soundplaying") && this.mBrowser.lastURI != aLocation) {
|
||||||
this.mTab.removeAttribute("soundplaying");
|
this.mTab.removeAttribute("soundplaying");
|
||||||
this.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
|
this.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,6 @@ skip-if = buildapp == 'mulet'
|
|||||||
[browser_identity_UI.js]
|
[browser_identity_UI.js]
|
||||||
[browser_insecureLoginForms.js]
|
[browser_insecureLoginForms.js]
|
||||||
[browser_keywordBookmarklets.js]
|
[browser_keywordBookmarklets.js]
|
||||||
skip-if = e10s # Bug 1102025 - different principals for the bookmarklet only in e10s mode (unclear if test or 'real' issue)
|
|
||||||
[browser_keywordSearch.js]
|
[browser_keywordSearch.js]
|
||||||
[browser_keywordSearch_postData.js]
|
[browser_keywordSearch_postData.js]
|
||||||
[browser_lastAccessedTab.js]
|
[browser_lastAccessedTab.js]
|
||||||
|
@ -12,6 +12,14 @@ add_task(function* test_keyword_bookmarklet() {
|
|||||||
yield promisePageShow();
|
yield promisePageShow();
|
||||||
let originalPrincipal = gBrowser.contentPrincipal;
|
let originalPrincipal = gBrowser.contentPrincipal;
|
||||||
|
|
||||||
|
function getPrincipalURI() {
|
||||||
|
return ContentTask.spawn(tab.linkedBrowser, null, function() {
|
||||||
|
return content.document.nodePrincipal.URI.spec;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let originalPrincipalURI = yield getPrincipalURI();
|
||||||
|
|
||||||
yield PlacesUtils.keywords.insert({ keyword: "bm", url: "javascript:1;" })
|
yield PlacesUtils.keywords.insert({ keyword: "bm", url: "javascript:1;" })
|
||||||
|
|
||||||
// Enter bookmarklet keyword in the URL bar
|
// Enter bookmarklet keyword in the URL bar
|
||||||
@ -21,7 +29,19 @@ add_task(function* test_keyword_bookmarklet() {
|
|||||||
|
|
||||||
yield promisePageShow();
|
yield promisePageShow();
|
||||||
|
|
||||||
ok(gBrowser.contentPrincipal.equals(originalPrincipal), "javascript bookmarklet should inherit principal");
|
let newPrincipalURI = yield getPrincipalURI();
|
||||||
|
is(newPrincipalURI, originalPrincipalURI, "content has the same principal");
|
||||||
|
|
||||||
|
// In e10s, null principals don't round-trip so the same null principal sent
|
||||||
|
// from the child will be a new null principal. Verify that this is the
|
||||||
|
// case.
|
||||||
|
if (tab.linkedBrowser.isRemoteBrowser) {
|
||||||
|
ok(originalPrincipal.isNullPrincipal && gBrowser.contentPrincipal.isNullPrincipal,
|
||||||
|
"both principals should be null principals in the parent");
|
||||||
|
} else {
|
||||||
|
ok(gBrowser.contentPrincipal.equals(originalPrincipal),
|
||||||
|
"javascript bookmarklet should inherit principal");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function* promisePageShow() {
|
function* promisePageShow() {
|
||||||
|
@ -4224,7 +4224,6 @@ cairo-uikit)
|
|||||||
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
|
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
|
||||||
MOZ_USER_DIR="Mozilla"
|
MOZ_USER_DIR="Mozilla"
|
||||||
MOZ_FS_LAYOUT=bundle
|
MOZ_FS_LAYOUT=bundle
|
||||||
AC_DEFINE(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
cairo-android)
|
cairo-android)
|
||||||
@ -4798,11 +4797,8 @@ MOZ_ARG_ENABLE_BOOL(android-apz,
|
|||||||
MOZ_ANDROID_APZ=1,
|
MOZ_ANDROID_APZ=1,
|
||||||
MOZ_ANDROID_APZ=)
|
MOZ_ANDROID_APZ=)
|
||||||
if test -n "$MOZ_ANDROID_APZ"; then
|
if test -n "$MOZ_ANDROID_APZ"; then
|
||||||
dnl Do this if defined in confvars.sh
|
dnl Do this if defined in confvars.sh
|
||||||
AC_DEFINE(MOZ_ANDROID_APZ)
|
AC_DEFINE(MOZ_ANDROID_APZ)
|
||||||
if test -z "$MOZ_B2GDROID"; then
|
|
||||||
AC_DEFINE(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
@ -229,7 +229,7 @@ function installCache(app) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
let principal =
|
let principal =
|
||||||
Services.scriptSecurityManager.createCodebasePrincipal(app.origin, {appId: aApp.localId});
|
Services.scriptSecurityManager.createCodebasePrincipal(app.origin, {appId: app.localId});
|
||||||
|
|
||||||
// If the build has been correctly configured, this should not happen!
|
// If the build has been correctly configured, this should not happen!
|
||||||
// If we install the cache anyway, it won't be updateable. If we don't install
|
// If we install the cache anyway, it won't be updateable. If we don't install
|
||||||
|
@ -7509,7 +7509,9 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
|||||||
if (IsFileImage(file, type)) {
|
if (IsFileImage(file, type)) {
|
||||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||||
item->flavor() = type;
|
item->flavor() = type;
|
||||||
SlurpFileToString(file, item->data());
|
nsAutoCString data;
|
||||||
|
SlurpFileToString(file, data);
|
||||||
|
item->data() = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -7669,11 +7671,10 @@ nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
|
|||||||
const nsPoint& aOffset,
|
const nsPoint& aOffset,
|
||||||
nsPresContext* aPresContext)
|
nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
nsPoint point = CSSPoint::ToAppUnits(aPoint) + aOffset;
|
return LayoutDeviceIntPoint::FromAppUnitsRounded(
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
(CSSPoint::ToAppUnits(aPoint) +
|
||||||
point = point.ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
|
aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()),
|
||||||
#endif
|
aPresContext->AppUnitsPerDevPixel());
|
||||||
return LayoutDeviceIntPoint::FromAppUnitsRounded(point, aPresContext->AppUnitsPerDevPixel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsView*
|
nsView*
|
||||||
|
@ -286,11 +286,10 @@ already_AddRefed<nsIScriptTimeoutHandler>
|
|||||||
NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
|
||||||
const nsAString& aExpression, ErrorResult& aError)
|
const nsAString& aExpression, ErrorResult& aError)
|
||||||
{
|
{
|
||||||
ErrorResult rv;
|
|
||||||
bool allowEval = false;
|
bool allowEval = false;
|
||||||
RefPtr<nsJSScriptTimeoutHandler> handler =
|
RefPtr<nsJSScriptTimeoutHandler> handler =
|
||||||
new nsJSScriptTimeoutHandler(aCx, aWindow, aExpression, &allowEval, rv);
|
new nsJSScriptTimeoutHandler(aCx, aWindow, aExpression, &allowEval, aError);
|
||||||
if (rv.Failed() || !allowEval) {
|
if (aError.Failed() || !allowEval) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,61 +5,66 @@
|
|||||||
* loads. The policy we are enforcing is outlined here:
|
* loads. The policy we are enforcing is outlined here:
|
||||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=593387#c17
|
* https://bugzilla.mozilla.org/show_bug.cgi?id=593387#c17
|
||||||
*/
|
*/
|
||||||
var newBrowser;
|
|
||||||
|
|
||||||
function test() {
|
add_task(function* test() {
|
||||||
waitForExplicitFinish();
|
yield BrowserTestUtils.withNewTab({ gBrowser,
|
||||||
|
url: "chrome://global/content/mozilla.xhtml" },
|
||||||
|
function* (newBrowser) {
|
||||||
|
// NB: We load the chrome:// page in the parent process.
|
||||||
|
yield testXFOFrameInChrome(newBrowser);
|
||||||
|
|
||||||
var newTab = gBrowser.addTab();
|
// Run next test (try the same with a content top-level context)
|
||||||
gBrowser.selectedTab = newTab;
|
yield BrowserTestUtils.loadURI(newBrowser, "http://example.com/");
|
||||||
newBrowser = gBrowser.getBrowserForTab(newTab);
|
yield BrowserTestUtils.browserLoaded(newBrowser);
|
||||||
//alert(newBrowser.contentWindow);
|
|
||||||
|
|
||||||
newBrowser.addEventListener("load", testXFOFrameInChrome, true);
|
yield ContentTask.spawn(newBrowser, null, testXFOFrameInContent);
|
||||||
newBrowser.contentWindow.location = "chrome://global/content/mozilla.xhtml";
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
function testXFOFrameInChrome() {
|
|
||||||
newBrowser.removeEventListener("load", testXFOFrameInChrome, true);
|
|
||||||
|
|
||||||
|
function testXFOFrameInChrome(newBrowser) {
|
||||||
// Insert an iframe that specifies "X-Frame-Options: DENY" and verify
|
// Insert an iframe that specifies "X-Frame-Options: DENY" and verify
|
||||||
// that it loads, since the top context is chrome
|
// that it loads, since the top context is chrome
|
||||||
|
var deferred = {};
|
||||||
|
deferred.promise = new Promise((resolve) => {
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
var frame = newBrowser.contentDocument.createElement("iframe");
|
var frame = newBrowser.contentDocument.createElement("iframe");
|
||||||
frame.src = "http://mochi.test:8888/tests/dom/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny";
|
frame.src = "http://mochi.test:8888/tests/dom/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny";
|
||||||
frame.addEventListener("load", function() {
|
frame.addEventListener("load", function loaded() {
|
||||||
frame.removeEventListener("load", arguments.callee, true);
|
frame.removeEventListener("load", loaded, true);
|
||||||
|
|
||||||
// Test that the frame loaded
|
// Test that the frame loaded
|
||||||
var test = this.contentDocument.getElementById("test");
|
var test = this.contentDocument.getElementById("test");
|
||||||
is(test.tagName, "H1", "wrong element type");
|
is(test.tagName, "H1", "wrong element type");
|
||||||
is(test.textContent, "deny", "wrong textContent");
|
is(test.textContent, "deny", "wrong textContent");
|
||||||
|
deferred.resolve();
|
||||||
// Run next test (try the same with a content top-level context)
|
|
||||||
newBrowser.addEventListener("load", testXFOFrameInContent, true);
|
|
||||||
newBrowser.contentWindow.location = "http://example.com/";
|
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
newBrowser.contentDocument.body.appendChild(frame);
|
newBrowser.contentDocument.body.appendChild(frame);
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testXFOFrameInContent() {
|
function testXFOFrameInContent(newBrowser) {
|
||||||
newBrowser.removeEventListener("load", testXFOFrameInContent, true);
|
|
||||||
|
|
||||||
// Insert an iframe that specifies "X-Frame-Options: DENY" and verify that it
|
// Insert an iframe that specifies "X-Frame-Options: DENY" and verify that it
|
||||||
// is blocked from loading since the top browsing context is another site
|
// is blocked from loading since the top browsing context is another site
|
||||||
var frame = newBrowser.contentDocument.createElement("iframe");
|
var deferred = {};
|
||||||
|
deferred.promise = new Promise((resolve) => {
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
var frame = content.document.createElement("iframe");
|
||||||
frame.src = "http://mochi.test:8888/tests/dom/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny";
|
frame.src = "http://mochi.test:8888/tests/dom/base/test/file_x-frame-options_page.sjs?testid=deny&xfo=deny";
|
||||||
frame.addEventListener("load", function() {
|
frame.addEventListener("load", function loaded() {
|
||||||
frame.removeEventListener("load", arguments.callee, true);
|
frame.removeEventListener("load", loaded, true);
|
||||||
|
|
||||||
// Test that the frame DID NOT load
|
// Test that the frame DID NOT load
|
||||||
var test = this.contentDocument.getElementById("test");
|
var test = this.contentDocument.getElementById("test");
|
||||||
is(test, undefined, "should be about:blank");
|
is(test, null, "should be about:blank");
|
||||||
|
|
||||||
// Finalize the test
|
deferred.resolve();
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
finish();
|
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
newBrowser.contentDocument.body.appendChild(frame);
|
content.document.body.appendChild(frame);
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
@ -2487,14 +2487,24 @@ CanvasRenderingContext2D::UpdateFilter()
|
|||||||
// rects
|
// rects
|
||||||
//
|
//
|
||||||
|
|
||||||
// bug 1074733
|
static bool
|
||||||
// The canvas spec does not forbid rects with negative w or h, so given
|
ValidateRect(double& aX, double& aY, double& aWidth, double& aHeight)
|
||||||
// corners (x, y), (x+w, y), (x+w, y+h), and (x, y+h) we must generate
|
|
||||||
// the appropriate rect by flipping negative dimensions. This prevents
|
|
||||||
// draw targets from receiving "empty" rects later on.
|
|
||||||
static void
|
|
||||||
NormalizeRect(double& aX, double& aY, double& aWidth, double& aHeight)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// bug 1018527
|
||||||
|
// The values of canvas API input are in double precision, but Moz2D APIs are
|
||||||
|
// using float precision. Bypass canvas API calls when the input is out of
|
||||||
|
// float precision to avoid precision problem
|
||||||
|
if (!std::isfinite((float)aX) | !std::isfinite((float)aY) |
|
||||||
|
!std::isfinite((float)aWidth) | !std::isfinite((float)aHeight)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bug 1074733
|
||||||
|
// The canvas spec does not forbid rects with negative w or h, so given
|
||||||
|
// corners (x, y), (x+w, y), (x+w, y+h), and (x, y+h) we must generate
|
||||||
|
// the appropriate rect by flipping negative dimensions. This prevents
|
||||||
|
// draw targets from receiving "empty" rects later on.
|
||||||
if (aWidth < 0) {
|
if (aWidth < 0) {
|
||||||
aWidth = -aWidth;
|
aWidth = -aWidth;
|
||||||
aX -= aWidth;
|
aX -= aWidth;
|
||||||
@ -2503,13 +2513,16 @@ NormalizeRect(double& aX, double& aY, double& aWidth, double& aHeight)
|
|||||||
aHeight = -aHeight;
|
aHeight = -aHeight;
|
||||||
aY -= aHeight;
|
aY -= aHeight;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
|
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
|
||||||
double h)
|
double h)
|
||||||
{
|
{
|
||||||
NormalizeRect(x, y, w, h);
|
if(!ValidateRect(x, y, w, h)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EnsureTarget();
|
EnsureTarget();
|
||||||
|
|
||||||
@ -2524,7 +2537,9 @@ CanvasRenderingContext2D::FillRect(double x, double y, double w,
|
|||||||
{
|
{
|
||||||
const ContextState &state = CurrentState();
|
const ContextState &state = CurrentState();
|
||||||
|
|
||||||
NormalizeRect(x, y, w, h);
|
if(!ValidateRect(x, y, w, h)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (state.patternStyles[Style::FILL]) {
|
if (state.patternStyles[Style::FILL]) {
|
||||||
CanvasPattern::RepeatMode repeat =
|
CanvasPattern::RepeatMode repeat =
|
||||||
@ -2599,7 +2614,10 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
|
|||||||
if (!w && !h) {
|
if (!w && !h) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NormalizeRect(x, y, w, h);
|
|
||||||
|
if(!ValidateRect(x, y, w, h)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EnsureTarget();
|
EnsureTarget();
|
||||||
if (!IsTargetValid()) {
|
if (!IsTargetValid()) {
|
||||||
@ -4375,8 +4393,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
|||||||
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
||||||
|
|
||||||
if (optional_argc == 6) {
|
if (optional_argc == 6) {
|
||||||
NormalizeRect(sx, sy, sw, sh);
|
if (!ValidateRect(sx, sy, sw, sh) ||
|
||||||
NormalizeRect(dx, dy, dw, dh);
|
!ValidateRect(dx, dy, dw, dh)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<SourceSurface> srcSurf;
|
RefPtr<SourceSurface> srcSurf;
|
||||||
|
@ -21536,6 +21536,20 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- [[[ test_2d.clearRect.testdoubleprecision.html ]]] -->
|
||||||
|
|
||||||
|
<p>Canvas test: 2d.clearRect.testdoubleprecision</p>
|
||||||
|
<canvas id="c690" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function test_2d_clearRect_testdoubleprecision() {
|
||||||
|
var canvas = document.getElementById('c690');
|
||||||
|
ctx = canvas.getContext('2d');
|
||||||
|
ctx.setTransform(1, 1, 1, 1, 0, 0);
|
||||||
|
ctx.clearRect(-1.79e+308, 0, 1.79e+308, 8);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function asyncTestsDone() {
|
function asyncTestsDone() {
|
||||||
@ -24835,7 +24849,13 @@ try {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
ok(false, "unexpected exception thrown in: test_type_replace");
|
ok(false, "unexpected exception thrown in: test_type_replace");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
test_2d_clearRect_testdoubleprecision();
|
||||||
|
} catch(e) {
|
||||||
|
throw e;
|
||||||
|
ok(false, "unexpected exception thrown in: test_2d_clearRect_testdoubleprecision");
|
||||||
|
}
|
||||||
|
|
||||||
//run the asynchronous tests
|
//run the asynchronous tests
|
||||||
try {
|
try {
|
||||||
test_2d_drawImage_animated_apng();
|
test_2d_drawImage_animated_apng();
|
||||||
|
@ -935,11 +935,9 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
|
|||||||
nsPoint pt =
|
nsPoint pt =
|
||||||
LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
|
LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
|
||||||
|
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
if (aPresContext->PresShell()) {
|
if (aPresContext->PresShell()) {
|
||||||
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
|
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),
|
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),
|
||||||
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
|
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
|
||||||
|
@ -760,15 +760,17 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||||||
if (content)
|
if (content)
|
||||||
mCurrentTargetContent = content;
|
mCurrentTargetContent = content;
|
||||||
|
|
||||||
// NOTE: Don't refer TextComposition::IsComposing() since DOM Level 3
|
// NOTE: Don't refer TextComposition::IsComposing() since UI Events
|
||||||
// Events defines that KeyboardEvent.isComposing is true when it's
|
// defines that KeyboardEvent.isComposing is true when it's
|
||||||
// dispatched after compositionstart and compositionend.
|
// dispatched after compositionstart and compositionend.
|
||||||
// TextComposition::IsComposing() is false even before
|
// TextComposition::IsComposing() is false even before
|
||||||
// compositionend if there is no composing string.
|
// compositionend if there is no composing string.
|
||||||
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
|
// And also don't expose other document's composition state.
|
||||||
|
// A native IME context is typically shared by multiple documents.
|
||||||
|
// So, don't use GetTextCompositionFor(nsIWidget*) here.
|
||||||
RefPtr<TextComposition> composition =
|
RefPtr<TextComposition> composition =
|
||||||
IMEStateManager::GetTextCompositionFor(keyEvent);
|
IMEStateManager::GetTextCompositionFor(aPresContext);
|
||||||
keyEvent->mIsComposing = !!composition;
|
aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eWheel:
|
case eWheel:
|
||||||
|
@ -1144,11 +1144,21 @@ IMEStateManager::DispatchCompositionEvent(
|
|||||||
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
|
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
|
||||||
"aPresContext=0x%p, aCompositionEvent={ message=%s, "
|
"aPresContext=0x%p, aCompositionEvent={ mMessage=%s, "
|
||||||
|
"mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||||
|
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||||
|
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||||
|
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||||
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
|
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
|
||||||
"aIsSynthesized=%s), tabParent=%p",
|
"aIsSynthesized=%s), tabParent=%p",
|
||||||
aEventTargetNode, aPresContext,
|
aEventTargetNode, aPresContext,
|
||||||
ToChar(aCompositionEvent->mMessage),
|
ToChar(aCompositionEvent->mMessage),
|
||||||
|
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||||
|
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||||
|
aCompositionEvent->widget.get(),
|
||||||
|
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||||
|
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||||
|
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
|
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
|
||||||
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
|
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
|
||||||
GetBoolName(aIsSynthesized), tabParent.get()));
|
GetBoolName(aIsSynthesized), tabParent.get()));
|
||||||
@ -1164,7 +1174,7 @@ IMEStateManager::DispatchCompositionEvent(
|
|||||||
EnsureTextCompositionArray();
|
EnsureTextCompositionArray();
|
||||||
|
|
||||||
RefPtr<TextComposition> composition =
|
RefPtr<TextComposition> composition =
|
||||||
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
|
sTextCompositions->GetCompositionFor(aCompositionEvent);
|
||||||
if (!composition) {
|
if (!composition) {
|
||||||
// If synthesized event comes after delayed native composition events
|
// If synthesized event comes after delayed native composition events
|
||||||
// for request of commit or cancel, we should ignore it.
|
// for request of commit or cancel, we should ignore it.
|
||||||
@ -1278,8 +1288,18 @@ IMEStateManager::OnCompositionEventDiscarded(
|
|||||||
|
|
||||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||||
("ISM: IMEStateManager::OnCompositionEventDiscarded(aCompositionEvent={ "
|
("ISM: IMEStateManager::OnCompositionEventDiscarded(aCompositionEvent={ "
|
||||||
"mMessage=%s, mFlags={ mIsTrusted=%s } })",
|
"mMessage=%s, mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||||
|
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||||
|
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||||
|
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||||
|
"mFlags={ mIsTrusted=%s } })",
|
||||||
ToChar(aCompositionEvent->mMessage),
|
ToChar(aCompositionEvent->mMessage),
|
||||||
|
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||||
|
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||||
|
aCompositionEvent->widget.get(),
|
||||||
|
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||||
|
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||||
|
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
|
GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
|
||||||
|
|
||||||
if (!aCompositionEvent->mFlags.mIsTrusted) {
|
if (!aCompositionEvent->mFlags.mIsTrusted) {
|
||||||
@ -1649,11 +1669,27 @@ IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
already_AddRefed<TextComposition>
|
already_AddRefed<TextComposition>
|
||||||
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aGUIEvent)
|
IMEStateManager::GetTextCompositionFor(
|
||||||
|
const WidgetCompositionEvent* aCompositionEvent)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aGUIEvent->AsCompositionEvent() || aGUIEvent->AsKeyboardEvent(),
|
if (!sTextCompositions) {
|
||||||
"aGUIEvent has to be WidgetCompositionEvent or WidgetKeyboardEvent");
|
return nullptr;
|
||||||
return GetTextCompositionFor(aGUIEvent->widget);
|
}
|
||||||
|
RefPtr<TextComposition> textComposition =
|
||||||
|
sTextCompositions->GetCompositionFor(aCompositionEvent);
|
||||||
|
return textComposition.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
already_AddRefed<TextComposition>
|
||||||
|
IMEStateManager::GetTextCompositionFor(nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
if (!sTextCompositions) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
RefPtr<TextComposition> textComposition =
|
||||||
|
sTextCompositions->GetCompositionFor(aPresContext);
|
||||||
|
return textComposition.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -181,11 +181,17 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns TextComposition instance for the event.
|
* Returns TextComposition instance for the event.
|
||||||
*
|
|
||||||
* @param aGUIEvent Should be a composition event which is being dispatched.
|
|
||||||
*/
|
*/
|
||||||
static already_AddRefed<TextComposition>
|
static already_AddRefed<TextComposition>
|
||||||
GetTextCompositionFor(WidgetGUIEvent* aGUIEvent);
|
GetTextCompositionFor(const WidgetCompositionEvent* aCompositionEvent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TextComposition instance for the pres context.
|
||||||
|
* Be aware, even if another pres context which shares native IME context with
|
||||||
|
* specified pres context has composition, this returns nullptr.
|
||||||
|
*/
|
||||||
|
static already_AddRefed<TextComposition>
|
||||||
|
GetTextCompositionFor(nsPresContext* aPresContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a notification to IME. It depends on the IME or platform spec what
|
* Send a notification to IME. It depends on the IME or platform spec what
|
||||||
|
@ -39,8 +39,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
|
|||||||
: mPresContext(aPresContext)
|
: mPresContext(aPresContext)
|
||||||
, mNode(aNode)
|
, mNode(aNode)
|
||||||
, mTabParent(aTabParent)
|
, mTabParent(aTabParent)
|
||||||
, mNativeContext(
|
, mNativeContext(aCompositionEvent->mNativeIMEContext)
|
||||||
aCompositionEvent->widget->GetInputContext().mNativeIMEContext)
|
|
||||||
, mCompositionStartOffset(0)
|
, mCompositionStartOffset(0)
|
||||||
, mCompositionTargetOffset(0)
|
, mCompositionTargetOffset(0)
|
||||||
, mIsSynthesizedForTests(aCompositionEvent->mFlags.mIsSynthesizedForTests)
|
, mIsSynthesizedForTests(aCompositionEvent->mFlags.mIsSynthesizedForTests)
|
||||||
@ -54,6 +53,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
|
|||||||
Preferences::GetBool("dom.compositionevent.allow_control_characters",
|
Preferences::GetBool("dom.compositionevent.allow_control_characters",
|
||||||
false))
|
false))
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aCompositionEvent->mNativeIMEContext.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -66,12 +66,6 @@ TextComposition::Destroy()
|
|||||||
// this being destroyed for cleaning up the stuff.
|
// this being destroyed for cleaning up the stuff.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
|
|
||||||
{
|
|
||||||
return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TextComposition::IsValidStateForComposition(nsIWidget* aWidget) const
|
TextComposition::IsValidStateForComposition(nsIWidget* aWidget) const
|
||||||
{
|
{
|
||||||
@ -114,6 +108,7 @@ TextComposition::CloneAndDispatchAs(
|
|||||||
compositionEvent.time = aCompositionEvent->time;
|
compositionEvent.time = aCompositionEvent->time;
|
||||||
compositionEvent.timeStamp = aCompositionEvent->timeStamp;
|
compositionEvent.timeStamp = aCompositionEvent->timeStamp;
|
||||||
compositionEvent.mData = aCompositionEvent->mData;
|
compositionEvent.mData = aCompositionEvent->mData;
|
||||||
|
compositionEvent.mNativeIMEContext = aCompositionEvent->mNativeIMEContext;
|
||||||
compositionEvent.mOriginalMessage = aCompositionEvent->mMessage;
|
compositionEvent.mOriginalMessage = aCompositionEvent->mMessage;
|
||||||
compositionEvent.mFlags.mIsSynthesizedForTests =
|
compositionEvent.mFlags.mIsSynthesizedForTests =
|
||||||
aCompositionEvent->mFlags.mIsSynthesizedForTests;
|
aCompositionEvent->mFlags.mIsSynthesizedForTests;
|
||||||
@ -613,6 +608,7 @@ TextComposition::CompositionEventDispatcher::Run()
|
|||||||
switch (mEventMessage) {
|
switch (mEventMessage) {
|
||||||
case eCompositionStart: {
|
case eCompositionStart: {
|
||||||
WidgetCompositionEvent compStart(true, eCompositionStart, widget);
|
WidgetCompositionEvent compStart(true, eCompositionStart, widget);
|
||||||
|
compStart.mNativeIMEContext = mTextComposition->mNativeContext;
|
||||||
WidgetQueryContentEvent selectedText(true, eQuerySelectedText, widget);
|
WidgetQueryContentEvent selectedText(true, eQuerySelectedText, widget);
|
||||||
ContentEventHandler handler(presContext);
|
ContentEventHandler handler(presContext);
|
||||||
handler.OnQuerySelectedText(&selectedText);
|
handler.OnQuerySelectedText(&selectedText);
|
||||||
@ -629,6 +625,7 @@ TextComposition::CompositionEventDispatcher::Run()
|
|||||||
case eCompositionCommitAsIs:
|
case eCompositionCommitAsIs:
|
||||||
case eCompositionCommit: {
|
case eCompositionCommit: {
|
||||||
WidgetCompositionEvent compEvent(true, mEventMessage, widget);
|
WidgetCompositionEvent compEvent(true, mEventMessage, widget);
|
||||||
|
compEvent.mNativeIMEContext = mTextComposition->mNativeContext;
|
||||||
if (mEventMessage != eCompositionCommitAsIs) {
|
if (mEventMessage != eCompositionCommitAsIs) {
|
||||||
compEvent.mData = mData;
|
compEvent.mData = mData;
|
||||||
}
|
}
|
||||||
@ -650,16 +647,25 @@ TextComposition::CompositionEventDispatcher::Run()
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
TextCompositionArray::index_type
|
TextCompositionArray::index_type
|
||||||
TextCompositionArray::IndexOf(nsIWidget* aWidget)
|
TextCompositionArray::IndexOf(const NativeIMEContext& aNativeIMEContext)
|
||||||
{
|
{
|
||||||
|
if (!aNativeIMEContext.IsValid()) {
|
||||||
|
return NoIndex;
|
||||||
|
}
|
||||||
for (index_type i = Length(); i > 0; --i) {
|
for (index_type i = Length(); i > 0; --i) {
|
||||||
if (ElementAt(i - 1)->MatchesNativeContext(aWidget)) {
|
if (ElementAt(i - 1)->GetNativeIMEContext() == aNativeIMEContext) {
|
||||||
return i - 1;
|
return i - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoIndex;
|
return NoIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextCompositionArray::index_type
|
||||||
|
TextCompositionArray::IndexOf(nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
return IndexOf(aWidget->GetNativeIMEContext());
|
||||||
|
}
|
||||||
|
|
||||||
TextCompositionArray::index_type
|
TextCompositionArray::index_type
|
||||||
TextCompositionArray::IndexOf(nsPresContext* aPresContext)
|
TextCompositionArray::IndexOf(nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@ -693,6 +699,27 @@ TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
|
|||||||
return ElementAt(i);
|
return ElementAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextComposition*
|
||||||
|
TextCompositionArray::GetCompositionFor(
|
||||||
|
const WidgetCompositionEvent* aCompositionEvent)
|
||||||
|
{
|
||||||
|
index_type i = IndexOf(aCompositionEvent->mNativeIMEContext);
|
||||||
|
if (i == NoIndex) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ElementAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextComposition*
|
||||||
|
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
index_type i = IndexOf(aPresContext);
|
||||||
|
if (i == NoIndex) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ElementAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
TextComposition*
|
TextComposition*
|
||||||
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
|
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
|
||||||
nsINode* aNode)
|
nsINode* aNode)
|
||||||
|
@ -76,7 +76,10 @@ public:
|
|||||||
// came from nsDOMWindowUtils.
|
// came from nsDOMWindowUtils.
|
||||||
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
||||||
|
|
||||||
bool MatchesNativeContext(nsIWidget* aWidget) const;
|
const widget::NativeIMEContext& GetNativeIMEContext() const
|
||||||
|
{
|
||||||
|
return mNativeContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when IMEStateManager stops managing the instance.
|
* This is called when IMEStateManager stops managing the instance.
|
||||||
@ -191,7 +194,7 @@ private:
|
|||||||
|
|
||||||
// mNativeContext stores a opaque pointer. This works as the "ID" for this
|
// mNativeContext stores a opaque pointer. This works as the "ID" for this
|
||||||
// composition. Don't access the instance, it may not be available.
|
// composition. Don't access the instance, it may not be available.
|
||||||
void* mNativeContext;
|
widget::NativeIMEContext mNativeContext;
|
||||||
|
|
||||||
// mEditorWeak is a weak reference to the focused editor handling composition.
|
// mEditorWeak is a weak reference to the focused editor handling composition.
|
||||||
nsWeakPtr mEditorWeak;
|
nsWeakPtr mEditorWeak;
|
||||||
@ -400,11 +403,19 @@ class TextCompositionArray final :
|
|||||||
public nsAutoTArray<RefPtr<TextComposition>, 2>
|
public nsAutoTArray<RefPtr<TextComposition>, 2>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Looking for per native IME context.
|
||||||
|
index_type IndexOf(const widget::NativeIMEContext& aNativeIMEContext);
|
||||||
index_type IndexOf(nsIWidget* aWidget);
|
index_type IndexOf(nsIWidget* aWidget);
|
||||||
|
|
||||||
|
TextComposition* GetCompositionFor(nsIWidget* aWidget);
|
||||||
|
TextComposition* GetCompositionFor(
|
||||||
|
const WidgetCompositionEvent* aCompositionEvent);
|
||||||
|
|
||||||
|
// Looking for per nsPresContext
|
||||||
index_type IndexOf(nsPresContext* aPresContext);
|
index_type IndexOf(nsPresContext* aPresContext);
|
||||||
index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
|
index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
|
||||||
|
|
||||||
TextComposition* GetCompositionFor(nsIWidget* aWidget);
|
TextComposition* GetCompositionFor(nsPresContext* aPresContext);
|
||||||
TextComposition* GetCompositionFor(nsPresContext* aPresContext,
|
TextComposition* GetCompositionFor(nsPresContext* aPresContext,
|
||||||
nsINode* aNode);
|
nsINode* aNode);
|
||||||
TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
|
TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
|
||||||
|
@ -4980,7 +4980,7 @@ HTMLMediaElement::GetTopLevelPrincipal()
|
|||||||
|
|
||||||
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mAudioChannelAgent);
|
MOZ_ASSERT(mAudioChannelAgent);
|
||||||
|
|
||||||
if (!OwnerDoc()->GetInnerWindow()) {
|
if (!OwnerDoc()->GetInnerWindow()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -4995,7 +4995,7 @@ NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
|||||||
uint64_t id = window->WindowID();
|
uint64_t id = window->WindowID();
|
||||||
MediaStreamGraph* msg =
|
MediaStreamGraph* msg =
|
||||||
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
|
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
|
||||||
AudioChannel::Normal);
|
mAudioChannel);
|
||||||
|
|
||||||
if (GetSrcMediaStream()) {
|
if (GetSrcMediaStream()) {
|
||||||
mCaptureStreamPort = msg->ConnectToCaptureStream(id, GetSrcMediaStream());
|
mCaptureStreamPort = msg->ConnectToCaptureStream(id, GetSrcMediaStream());
|
||||||
|
@ -235,20 +235,19 @@ parent:
|
|||||||
IMENotification notification);
|
IMENotification notification);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs chrome to end any pending composition
|
* Requests chrome to commit or cancel composition of IME.
|
||||||
*
|
*
|
||||||
* cancel true if composition should be cancelled
|
* cancel Set true if composition should be cancelled.
|
||||||
* noCompositionEvent true if no composition event is fired by commit or
|
|
||||||
* cancel
|
|
||||||
* composition Text to commit before ending the composition
|
|
||||||
*
|
*
|
||||||
* if cancel is true,
|
* isCommitted Returns true if the request causes composition
|
||||||
* widget should return empty string for composition
|
* being committed synchronously.
|
||||||
* if cancel is false,
|
* committedString Returns committed string. The may be non-empty
|
||||||
* widget should return the current composition text
|
* string even if cancel is true because IME may
|
||||||
|
* try to restore selected string which was
|
||||||
|
* replaced with the composition.
|
||||||
*/
|
*/
|
||||||
prio(urgent) sync EndIMEComposition(bool cancel)
|
prio(urgent) sync RequestIMEToCommitComposition(bool cancel)
|
||||||
returns (bool noCompositionEvent, nsString composition);
|
returns (bool isCommitted, nsString committedString);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OnEventNeedingAckHandled() is called after a child process dispatches a
|
* OnEventNeedingAckHandled() is called after a child process dispatches a
|
||||||
@ -296,8 +295,7 @@ parent:
|
|||||||
nsCString[] disabledCommands);
|
nsCString[] disabledCommands);
|
||||||
|
|
||||||
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
|
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
|
||||||
int32_t IMEOpen,
|
int32_t IMEOpen);
|
||||||
intptr_t NativeIMEContext);
|
|
||||||
|
|
||||||
prio(urgent) async SetInputContext(int32_t IMEEnabled,
|
prio(urgent) async SetInputContext(int32_t IMEEnabled,
|
||||||
int32_t IMEOpen,
|
int32_t IMEOpen,
|
||||||
|
@ -2321,16 +2321,19 @@ TabParent::GetRenderFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TabParent::RecvEndIMEComposition(const bool& aCancel,
|
TabParent::RecvRequestIMEToCommitComposition(const bool& aCancel,
|
||||||
bool* aNoCompositionEvent,
|
bool* aIsCommitted,
|
||||||
nsString* aComposition)
|
nsString* aCommittedString)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
|
*aIsCommitted = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*aNoCompositionEvent =
|
|
||||||
!mContentCache.RequestToCommitComposition(widget, aCancel, *aComposition);
|
*aIsCommitted =
|
||||||
|
mContentCache.RequestIMEToCommitComposition(widget, aCancel,
|
||||||
|
*aCommittedString);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2363,21 +2366,18 @@ TabParent::RecvSetPluginFocused(const bool& aFocused)
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
|
TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
|
||||||
int32_t* aIMEOpen,
|
int32_t* aIMEOpen)
|
||||||
intptr_t* aNativeIMEContext)
|
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
*aIMEEnabled = IMEState::DISABLED;
|
*aIMEEnabled = IMEState::DISABLED;
|
||||||
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
||||||
*aNativeIMEContext = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputContext context = widget->GetInputContext();
|
InputContext context = widget->GetInputContext();
|
||||||
*aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
|
*aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
|
||||||
*aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
|
*aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
|
||||||
*aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,17 +187,16 @@ public:
|
|||||||
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
|
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
|
||||||
const widget::IMENotification& aEventMessage) override;
|
const widget::IMENotification& aEventMessage) override;
|
||||||
virtual bool RecvOnEventNeedingAckHandled(const EventMessage& aMessage) override;
|
virtual bool RecvOnEventNeedingAckHandled(const EventMessage& aMessage) override;
|
||||||
virtual bool RecvEndIMEComposition(const bool& aCancel,
|
virtual bool RecvRequestIMEToCommitComposition(const bool& aCancel,
|
||||||
bool* aNoCompositionEvent,
|
bool* aIsCommitted,
|
||||||
nsString* aComposition) override;
|
nsString* aCommittedString) override;
|
||||||
virtual bool RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
|
virtual bool RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||||
const int32_t& aPanelX,
|
const int32_t& aPanelX,
|
||||||
const int32_t& aPanelY,
|
const int32_t& aPanelY,
|
||||||
nsString* aCommitted) override;
|
nsString* aCommitted) override;
|
||||||
virtual bool RecvSetPluginFocused(const bool& aFocused) override;
|
virtual bool RecvSetPluginFocused(const bool& aFocused) override;
|
||||||
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
|
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
|
||||||
int32_t* aIMEOpen,
|
int32_t* aIMEOpen) override;
|
||||||
intptr_t* aNativeIMEContext) override;
|
|
||||||
virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
|
virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
|
||||||
const int32_t& aIMEOpen,
|
const int32_t& aIMEOpen,
|
||||||
const nsString& aType,
|
const nsString& aType,
|
||||||
|
@ -2112,22 +2112,17 @@ MediaDecoderStateMachine::SeekCompleted()
|
|||||||
newCurrentTime = video ? video->mTime : seekTime;
|
newCurrentTime = video ? video->mTime : seekTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDecodingFirstFrame) {
|
|
||||||
// We were resuming from dormant, or initiated a seek early.
|
|
||||||
// We can fire loadeddata now.
|
|
||||||
FinishDecodeFirstFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change state to DECODING or COMPLETED now. SeekingStopped will
|
// Change state to DECODING or COMPLETED now. SeekingStopped will
|
||||||
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
|
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
|
||||||
// if we need to seek again.
|
// if we need to seek again.
|
||||||
|
|
||||||
bool isLiveStream = mResource->IsLiveStream();
|
bool isLiveStream = mResource->IsLiveStream();
|
||||||
|
State nextState;
|
||||||
if (mPendingSeek.Exists()) {
|
if (mPendingSeek.Exists()) {
|
||||||
// A new seek target came in while we were processing the old one. No rest
|
// A new seek target came in while we were processing the old one. No rest
|
||||||
// for the seeking.
|
// for the seeking.
|
||||||
DECODER_LOG("A new seek came along while we were finishing the old one - staying in SEEKING");
|
DECODER_LOG("A new seek came along while we were finishing the old one - staying in SEEKING");
|
||||||
SetState(DECODER_STATE_SEEKING);
|
nextState = DECODER_STATE_SEEKING;
|
||||||
} else if (GetMediaTime() == Duration().ToMicroseconds() && !isLiveStream) {
|
} else if (GetMediaTime() == Duration().ToMicroseconds() && !isLiveStream) {
|
||||||
// Seeked to end of media, move to COMPLETED state. Note we don't do
|
// Seeked to end of media, move to COMPLETED state. Note we don't do
|
||||||
// this when playing a live stream, since the end of media will advance
|
// this when playing a live stream, since the end of media will advance
|
||||||
@ -2135,11 +2130,26 @@ MediaDecoderStateMachine::SeekCompleted()
|
|||||||
DECODER_LOG("Changed state from SEEKING (to %lld) to COMPLETED", seekTime);
|
DECODER_LOG("Changed state from SEEKING (to %lld) to COMPLETED", seekTime);
|
||||||
// Explicitly set our state so we don't decode further, and so
|
// Explicitly set our state so we don't decode further, and so
|
||||||
// we report playback ended to the media element.
|
// we report playback ended to the media element.
|
||||||
SetState(DECODER_STATE_COMPLETED);
|
nextState = DECODER_STATE_COMPLETED;
|
||||||
DispatchDecodeTasksIfNeeded();
|
|
||||||
} else {
|
} else {
|
||||||
DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime);
|
DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime);
|
||||||
|
nextState = DECODER_STATE_DECODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to resolve the seek request prior finishing the first frame
|
||||||
|
// to ensure that the seeked event is fired prior loadeded.
|
||||||
|
mCurrentSeek.Resolve(nextState == DECODER_STATE_COMPLETED, __func__);
|
||||||
|
|
||||||
|
if (mDecodingFirstFrame) {
|
||||||
|
// We were resuming from dormant, or initiated a seek early.
|
||||||
|
// We can fire loadeddata now.
|
||||||
|
FinishDecodeFirstFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextState == DECODER_STATE_DECODING) {
|
||||||
StartDecoding();
|
StartDecoding();
|
||||||
|
} else {
|
||||||
|
SetState(nextState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure timestamps are up to date.
|
// Ensure timestamps are up to date.
|
||||||
@ -2153,7 +2163,6 @@ MediaDecoderStateMachine::SeekCompleted()
|
|||||||
// if we need to buffer after the seek.
|
// if we need to buffer after the seek.
|
||||||
mQuickBuffering = false;
|
mQuickBuffering = false;
|
||||||
|
|
||||||
mCurrentSeek.Resolve(mState == DECODER_STATE_COMPLETED, __func__);
|
|
||||||
ScheduleStateMachine();
|
ScheduleStateMachine();
|
||||||
|
|
||||||
if (video) {
|
if (video) {
|
||||||
|
@ -81,6 +81,8 @@ skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac"))
|
|||||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||||
[test_SeekNoData_mp4.html]
|
[test_SeekNoData_mp4.html]
|
||||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||||
|
[test_SeekedEvent_mp4.html]
|
||||||
|
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||||
[test_SeekTwice_mp4.html]
|
[test_SeekTwice_mp4.html]
|
||||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||||
[test_Sequence_mp4.html]
|
[test_Sequence_mp4.html]
|
||||||
|
75
dom/media/mediasource/test/test_SeekedEvent_mp4.html
Normal file
75
dom/media/mediasource/test/test_SeekedEvent_mp4.html
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>MSE: Check that seeked event is fired prior loadeddata</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="mediasource.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
runWithMSE(function(ms, el) {
|
||||||
|
el.controls = true;
|
||||||
|
el._seeked = false;
|
||||||
|
el._loadeddata = false;
|
||||||
|
el._playing = false;
|
||||||
|
el.addEventListener("seeked", function() {
|
||||||
|
ok(true, "got seeked event");
|
||||||
|
is(el._loadeddata, false, "can't have received loadeddata prior seeked");
|
||||||
|
is(el._playing, false, "can't be playing prior seeked");
|
||||||
|
el._seeked = true;
|
||||||
|
});
|
||||||
|
el.addEventListener("loadeddata", function() {
|
||||||
|
ok(true, "got loadeddata event");
|
||||||
|
is(el._seeked, true, "must have received seeked prior loadeddata");
|
||||||
|
is(el._playing, false, "can't be playing prior playing");
|
||||||
|
el._loadeddata = true;
|
||||||
|
});
|
||||||
|
el.addEventListener("playing", function() {
|
||||||
|
ok(true, "got playing");
|
||||||
|
is(el._seeked, true, "must have received seeked prior playing");
|
||||||
|
is(el._loadeddata, true, "must have received loadeddata prior playing");
|
||||||
|
el._playing = true;
|
||||||
|
});
|
||||||
|
once(ms, 'sourceopen').then(function() {
|
||||||
|
ok(true, "Receive a sourceopen event");
|
||||||
|
var videosb = ms.addSourceBuffer("video/mp4");
|
||||||
|
is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
|
||||||
|
fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
|
||||||
|
.then(once.bind(null, el, "loadedmetadata"))
|
||||||
|
.then(function() {
|
||||||
|
el.play();
|
||||||
|
videosb.timestampOffset = 2;
|
||||||
|
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
|
||||||
|
// Load [2, 3.606).
|
||||||
|
var promises = [];
|
||||||
|
promises.push(once(el, "play"));
|
||||||
|
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', ['1'], '.m4s'));
|
||||||
|
return Promise.all(promises);
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
return fetchAndLoad(videosb, 'bipbop/bipbop_video', ['2'], '.m4s');
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
|
||||||
|
el.currentTime = 2;
|
||||||
|
var promises = [];
|
||||||
|
promises.push(once(el, "seeked"));
|
||||||
|
promises.push(once(el, "playing"));
|
||||||
|
return Promise.all(promises);
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
ok(true, "completed seek");
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -22,6 +22,8 @@ extern "C" {
|
|||||||
#include "MediaMetadataManager.h"
|
#include "MediaMetadataManager.h"
|
||||||
#include "nsISeekableStream.h"
|
#include "nsISeekableStream.h"
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
|
#include "mozilla/Telemetry.h"
|
||||||
|
#include "nsPrintfCString.h"
|
||||||
|
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
using namespace mozilla::media;
|
using namespace mozilla::media;
|
||||||
@ -148,6 +150,17 @@ OggReader::~OggReader()
|
|||||||
{
|
{
|
||||||
ogg_sync_clear(&mOggState);
|
ogg_sync_clear(&mOggState);
|
||||||
MOZ_COUNT_DTOR(OggReader);
|
MOZ_COUNT_DTOR(OggReader);
|
||||||
|
if (HasAudio() || HasVideo()) {
|
||||||
|
// If we were able to initialize our decoders, report whether we encountered
|
||||||
|
// a chained stream or not.
|
||||||
|
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||||
|
bool isChained = mIsChained;
|
||||||
|
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
|
||||||
|
LOG(LogLevel::Debug, (nsPrintfCString("Reporting telemetry MEDIA_OGG_LOADED_IS_CHAINED=%d", isChained).get()));
|
||||||
|
Telemetry::Accumulate(Telemetry::ID::MEDIA_OGG_LOADED_IS_CHAINED, isChained);
|
||||||
|
});
|
||||||
|
AbstractThread::MainThread()->Dispatch(task.forget());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult OggReader::Init() {
|
nsresult OggReader::Init() {
|
||||||
@ -704,10 +717,13 @@ bool OggReader::DecodeAudioData()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OggReader::SetChained(bool aIsChained) {
|
void OggReader::SetChained() {
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||||
mIsChained = aIsChained;
|
if (mIsChained) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mIsChained = true;
|
||||||
}
|
}
|
||||||
mOnMediaNotSeekable.Notify();
|
mOnMediaNotSeekable.Notify();
|
||||||
}
|
}
|
||||||
@ -800,7 +816,7 @@ bool OggReader::ReadOggChain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chained) {
|
if (chained) {
|
||||||
SetChained(true);
|
SetChained();
|
||||||
{
|
{
|
||||||
auto t = mDecodedAudioFrames * USECS_PER_S / mInfo.mAudio.mRate;
|
auto t = mDecodedAudioFrames * USECS_PER_S / mInfo.mAudio.mRate;
|
||||||
mTimedMetadataEvent.Notify(
|
mTimedMetadataEvent.Notify(
|
||||||
@ -1139,7 +1155,7 @@ int64_t OggReader::RangeEndTime(int64_t aStartOffset,
|
|||||||
// This page is from a bitstream which we haven't encountered yet.
|
// This page is from a bitstream which we haven't encountered yet.
|
||||||
// It's probably from a new "link" in a "chained" ogg. Don't
|
// It's probably from a new "link" in a "chained" ogg. Don't
|
||||||
// bother even trying to find a duration...
|
// bother even trying to find a duration...
|
||||||
SetChained(true);
|
SetChained();
|
||||||
endTime = -1;
|
endTime = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1913,7 +1929,7 @@ media::TimeIntervals OggReader::GetBuffered()
|
|||||||
// ogg), return OK to abort the finding any further ranges. This
|
// ogg), return OK to abort the finding any further ranges. This
|
||||||
// prevents us searching through the rest of the media when we
|
// prevents us searching through the rest of the media when we
|
||||||
// may not be able to extract timestamps from it.
|
// may not be able to extract timestamps from it.
|
||||||
SetChained(true);
|
SetChained();
|
||||||
return buffered;
|
return buffered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ private:
|
|||||||
|
|
||||||
// Set this media as being a chain and notifies the state machine that the
|
// Set this media as being a chain and notifies the state machine that the
|
||||||
// media is no longer seekable.
|
// media is no longer seekable.
|
||||||
void SetChained(bool aIsChained);
|
void SetChained();
|
||||||
|
|
||||||
// Returns the next Ogg packet for an bitstream/codec state. Returns a
|
// Returns the next Ogg packet for an bitstream/codec state. Returns a
|
||||||
// pointer to an ogg_packet on success, or nullptr if the read failed.
|
// pointer to an ogg_packet on success, or nullptr if the read failed.
|
||||||
|
@ -280,21 +280,23 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create D3D9DeviceEx.
|
// Create D3D9DeviceEx. We pass null HWNDs here even though the documentation
|
||||||
|
// suggests that one of them should not be. At this point in time Chromium
|
||||||
|
// does the same thing for video acceleration.
|
||||||
D3DPRESENT_PARAMETERS params = {0};
|
D3DPRESENT_PARAMETERS params = {0};
|
||||||
params.BackBufferWidth = 1;
|
params.BackBufferWidth = 1;
|
||||||
params.BackBufferHeight = 1;
|
params.BackBufferHeight = 1;
|
||||||
params.BackBufferFormat = D3DFMT_UNKNOWN;
|
params.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||||
params.BackBufferCount = 1;
|
params.BackBufferCount = 1;
|
||||||
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||||
params.hDeviceWindow = ::GetShellWindow();
|
params.hDeviceWindow = nullptr;
|
||||||
params.Windowed = TRUE;
|
params.Windowed = TRUE;
|
||||||
params.Flags = D3DPRESENTFLAG_VIDEO;
|
params.Flags = D3DPRESENTFLAG_VIDEO;
|
||||||
|
|
||||||
RefPtr<IDirect3DDevice9Ex> device;
|
RefPtr<IDirect3DDevice9Ex> device;
|
||||||
hr = d3d9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
|
hr = d3d9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
|
||||||
D3DDEVTYPE_HAL,
|
D3DDEVTYPE_HAL,
|
||||||
::GetShellWindow(),
|
nullptr,
|
||||||
D3DCREATE_FPU_PRESERVE |
|
D3DCREATE_FPU_PRESERVE |
|
||||||
D3DCREATE_MULTITHREADED |
|
D3DCREATE_MULTITHREADED |
|
||||||
D3DCREATE_MIXED_VERTEXPROCESSING,
|
D3DCREATE_MIXED_VERTEXPROCESSING,
|
||||||
|
@ -79,6 +79,11 @@ SpeechTaskCallback::OnPause()
|
|||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
[mSpeechSynthesizer pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
|
[mSpeechSynthesizer pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
|
||||||
|
if (!mTask) {
|
||||||
|
// When calling pause() on child porcess, it may not receive end event
|
||||||
|
// from chrome process yet.
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
mTask->DispatchPause(GetTimeDurationFromStart(), mCurrentIndex);
|
mTask->DispatchPause(GetTimeDurationFromStart(), mCurrentIndex);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
@ -91,6 +96,11 @@ SpeechTaskCallback::OnResume()
|
|||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
[mSpeechSynthesizer continueSpeaking];
|
[mSpeechSynthesizer continueSpeaking];
|
||||||
|
if (!mTask) {
|
||||||
|
// When calling resume() on child porcess, it may not receive end event
|
||||||
|
// from chrome process yet.
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
mTask->DispatchResume(GetTimeDurationFromStart(), mCurrentIndex);
|
mTask->DispatchResume(GetTimeDurationFromStart(), mCurrentIndex);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
@ -120,6 +130,9 @@ void
|
|||||||
SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
|
SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
|
||||||
{
|
{
|
||||||
mCurrentIndex = aIndex;
|
mCurrentIndex = aIndex;
|
||||||
|
if (!mTask) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
|
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
|
||||||
GetTimeDurationFromStart(), mCurrentIndex);
|
GetTimeDurationFromStart(), mCurrentIndex);
|
||||||
}
|
}
|
||||||
@ -127,6 +140,9 @@ SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
|
|||||||
void
|
void
|
||||||
SpeechTaskCallback::OnError(uint32_t aIndex)
|
SpeechTaskCallback::OnError(uint32_t aIndex)
|
||||||
{
|
{
|
||||||
|
if (!mTask) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mTask->DispatchError(GetTimeDurationFromStart(), aIndex);
|
mTask->DispatchError(GetTimeDurationFromStart(), aIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,11 @@ SapiCallback::OnPause()
|
|||||||
if (FAILED(mSapiClient->Pause())) {
|
if (FAILED(mSapiClient->Pause())) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (!mTask) {
|
||||||
|
// When calling pause() on child porcess, it may not receive end event
|
||||||
|
// from chrome process yet.
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
mTask->DispatchPause(GetTickCount() - mStartingTime, mCurrentIndex);
|
mTask->DispatchPause(GetTickCount() - mStartingTime, mCurrentIndex);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -86,6 +91,11 @@ SapiCallback::OnResume()
|
|||||||
if (FAILED(mSapiClient->Resume())) {
|
if (FAILED(mSapiClient->Resume())) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (!mTask) {
|
||||||
|
// When calling resume() on child porcess, it may not receive end event
|
||||||
|
// from chrome process yet.
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
mTask->DispatchResume(GetTickCount() - mStartingTime, mCurrentIndex);
|
mTask->DispatchResume(GetTickCount() - mStartingTime, mCurrentIndex);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
|||||||
, mIsWhitelistedForShumway(false)
|
, mIsWhitelistedForShumway(false)
|
||||||
, mWindowType(NPWindowTypeWindow)
|
, mWindowType(NPWindowTypeWindow)
|
||||||
, mDrawingModel(kDefaultDrawingModel)
|
, mDrawingModel(kDefaultDrawingModel)
|
||||||
|
, mLastRecordedDrawingModel(-1)
|
||||||
, mFrameID(0)
|
, mFrameID(0)
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
, mPluginHWND(nullptr)
|
, mPluginHWND(nullptr)
|
||||||
@ -809,6 +810,8 @@ PluginInstanceParent::SetCurrentImage(Image* aImage)
|
|||||||
nsAutoTArray<ImageContainer::NonOwningImage,1> imageList;
|
nsAutoTArray<ImageContainer::NonOwningImage,1> imageList;
|
||||||
imageList.AppendElement(holder);
|
imageList.AppendElement(holder);
|
||||||
mImageContainer->SetCurrentImages(imageList);
|
mImageContainer->SetCurrentImages(imageList);
|
||||||
|
|
||||||
|
RecordDrawingModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -973,6 +976,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||||||
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
|
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
|
||||||
mFrontSurface.get()));
|
mFrontSurface.get()));
|
||||||
|
|
||||||
|
RecordDrawingModel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,6 +1384,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
|||||||
return NPERR_GENERIC_ERROR;
|
return NPERR_GENERIC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordDrawingModel();
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2363,3 +2368,28 @@ PluginInstanceParent::Cast(NPP aInstance, PluginAsyncSurrogate** aSurrogate)
|
|||||||
return instancePtr;
|
return instancePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginInstanceParent::RecordDrawingModel()
|
||||||
|
{
|
||||||
|
int mode = -1;
|
||||||
|
switch (mWindowType) {
|
||||||
|
case NPWindowTypeWindow:
|
||||||
|
// We use 0=windowed since there is no specific NPDrawingModel value.
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
case NPWindowTypeDrawable:
|
||||||
|
mode = mDrawingModel + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("bad window type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == mLastRecordedDrawingModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(mode >= 0);
|
||||||
|
|
||||||
|
Telemetry::Accumulate(Telemetry::PLUGIN_DRAWING_MODEL, mode);
|
||||||
|
mLastRecordedDrawingModel = mode;
|
||||||
|
}
|
||||||
|
@ -376,6 +376,9 @@ private:
|
|||||||
|
|
||||||
void SetCurrentImage(layers::Image* aImage);
|
void SetCurrentImage(layers::Image* aImage);
|
||||||
|
|
||||||
|
// Update Telemetry with the current drawing model.
|
||||||
|
void RecordDrawingModel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PluginModuleParent* mParent;
|
PluginModuleParent* mParent;
|
||||||
RefPtr<PluginAsyncSurrogate> mSurrogate;
|
RefPtr<PluginAsyncSurrogate> mSurrogate;
|
||||||
@ -387,6 +390,11 @@ private:
|
|||||||
NPWindowType mWindowType;
|
NPWindowType mWindowType;
|
||||||
int16_t mDrawingModel;
|
int16_t mDrawingModel;
|
||||||
|
|
||||||
|
// Since plugins may request different drawing models to find a compatible
|
||||||
|
// one, we only record the drawing model after a SetWindow call and if the
|
||||||
|
// drawing model has changed.
|
||||||
|
int mLastRecordedDrawingModel;
|
||||||
|
|
||||||
nsDataHashtable<nsPtrHashKey<NPObject>, PluginScriptableObjectParent*> mScriptableObjects;
|
nsDataHashtable<nsPtrHashKey<NPObject>, PluginScriptableObjectParent*> mScriptableObjects;
|
||||||
|
|
||||||
// This is used to tell the compositor that it should invalidate the ImageLayer.
|
// This is used to tell the compositor that it should invalidate the ImageLayer.
|
||||||
|
@ -154,6 +154,9 @@ partial interface Document {
|
|||||||
attribute EventHandler onbeforescriptexecute;
|
attribute EventHandler onbeforescriptexecute;
|
||||||
attribute EventHandler onafterscriptexecute;
|
attribute EventHandler onafterscriptexecute;
|
||||||
|
|
||||||
|
[Pref="dom.select_events.enabled"]
|
||||||
|
attribute EventHandler onselectionchange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if this document is synthetic : stand alone image, video, audio file,
|
* True if this document is synthetic : stand alone image, video, audio file,
|
||||||
* etc.
|
* etc.
|
||||||
|
@ -1987,14 +1987,14 @@ nsEditor::StopPreservingSelection()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
|
nsEditor::EnsureComposition(mozilla::WidgetCompositionEvent* aCompositionEvent)
|
||||||
{
|
{
|
||||||
if (mComposition) {
|
if (mComposition) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The compositionstart event must cause creating new TextComposition
|
// The compositionstart event must cause creating new TextComposition
|
||||||
// instance at being dispatched by IMEStateManager.
|
// instance at being dispatched by IMEStateManager.
|
||||||
mComposition = IMEStateManager::GetTextCompositionFor(aEvent);
|
mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
|
||||||
if (!mComposition) {
|
if (!mComposition) {
|
||||||
MOZ_CRASH("IMEStateManager doesn't return proper composition");
|
MOZ_CRASH("IMEStateManager doesn't return proper composition");
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ protected:
|
|||||||
* EnsureComposition() should be called by composition event handlers. This
|
* EnsureComposition() should be called by composition event handlers. This
|
||||||
* tries to get the composition for the event and set it to mComposition.
|
* tries to get the composition for the event and set it to mComposition.
|
||||||
*/
|
*/
|
||||||
void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
|
void EnsureComposition(mozilla::WidgetCompositionEvent* aCompositionEvent);
|
||||||
|
|
||||||
nsresult GetSelection(int16_t aSelectionType, nsISelection** aSelection);
|
nsresult GetSelection(int16_t aSelectionType, nsISelection** aSelection);
|
||||||
|
|
||||||
|
@ -2219,7 +2219,7 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance
|
|||||||
SetState(PANNING);
|
SetState(PANNING);
|
||||||
}
|
}
|
||||||
} else if (mState == PANNING_LOCKED_Y) {
|
} else if (mState == PANNING_LOCKED_Y) {
|
||||||
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisLockAngle())) {
|
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisBreakoutAngle())) {
|
||||||
mX.SetAxisLocked(false);
|
mX.SetAxisLocked(false);
|
||||||
SetState(PANNING);
|
SetState(PANNING);
|
||||||
}
|
}
|
||||||
|
@ -548,11 +548,12 @@ Pan(const RefPtr<InputReceiver>& aTarget,
|
|||||||
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
|
nsEventStatus (*aOutEventStatuses)[4] = nullptr,
|
||||||
uint64_t* aOutInputBlockId = nullptr)
|
uint64_t* aOutInputBlockId = nullptr)
|
||||||
{
|
{
|
||||||
// Reduce the touch start tolerance to a tiny value.
|
// Reduce the touch start and move tolerance to a tiny value.
|
||||||
// We can't use a scoped pref because this value might be read at some later
|
// We can't use a scoped pref because this value might be read at some later
|
||||||
// time when the events are actually processed, rather than when we deliver
|
// time when the events are actually processed, rather than when we deliver
|
||||||
// them.
|
// them.
|
||||||
gfxPrefs::SetAPZTouchStartTolerance(1.0f / 1000.0f);
|
gfxPrefs::SetAPZTouchStartTolerance(1.0f / 1000.0f);
|
||||||
|
gfxPrefs::SetAPZTouchMoveTolerance(0.0f);
|
||||||
const int OVERCOME_TOUCH_TOLERANCE = 1;
|
const int OVERCOME_TOUCH_TOLERANCE = 1;
|
||||||
|
|
||||||
const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50);
|
const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50);
|
||||||
|
@ -415,6 +415,28 @@ APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aConte
|
|||||||
return context->PresShell();
|
return context->PresShell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsIPresShell*
|
||||||
|
GetRootDocumentPresShell(nsIContent* aContent)
|
||||||
|
{
|
||||||
|
nsIDocument* doc = aContent->GetComposedDoc();
|
||||||
|
if (!doc) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsIPresShell* shell = doc->GetShell();
|
||||||
|
if (!shell) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsPresContext* context = shell->GetPresContext();
|
||||||
|
if (!context) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
context = context->GetRootPresContext();
|
||||||
|
if (!context) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return context->PresShell();
|
||||||
|
}
|
||||||
|
|
||||||
CSSPoint
|
CSSPoint
|
||||||
APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
|
APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
|
||||||
const ScrollableLayerGuid& aGuid)
|
const ScrollableLayerGuid& aGuid)
|
||||||
@ -423,24 +445,21 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
|
|||||||
if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
|
if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
|
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
// First, scale inversely by the root content document's pres shell
|
// First, scale inversely by the root content document's pres shell
|
||||||
// resolution to cancel the scale-to-resolution transform that the
|
// resolution to cancel the scale-to-resolution transform that the
|
||||||
// compositor adds to the layer with the pres shell resolution. The points
|
// compositor adds to the layer with the pres shell resolution. The points
|
||||||
// sent to Gecko by APZ don't have this transform unapplied (unlike other
|
// sent to Gecko by APZ don't have this transform unapplied (unlike other
|
||||||
// compositor-side transforms) because APZ doesn't know about it.
|
// compositor-side transforms) because APZ doesn't know about it.
|
||||||
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
|
if (nsIPresShell* shell = GetRootDocumentPresShell(content)) {
|
||||||
input = input / shell->GetResolution();
|
input = input / shell->GetResolution();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Apply the callback-transform.
|
// Now apply the callback-transform.
|
||||||
// XXX: technically we need to walk all the way up the layer tree from the layer
|
// XXX: technically we need to walk all the way up the layer tree from the layer
|
||||||
// represented by |aGuid.mScrollId| up to the root of the layer tree and apply
|
// represented by |aGuid.mScrollId| up to the root of the layer tree and apply
|
||||||
// the input transforms at each level in turn. However, it is quite difficult
|
// the input transforms at each level in turn. However, it is quite difficult
|
||||||
@ -451,22 +470,9 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
|
|||||||
// some things transformed improperly. In practice we should rarely hit scenarios
|
// some things transformed improperly. In practice we should rarely hit scenarios
|
||||||
// where any of this matters, so I'm skipping it for now and just doing the single
|
// where any of this matters, so I'm skipping it for now and just doing the single
|
||||||
// transform for the layer that the input hit.
|
// transform for the layer that the input hit.
|
||||||
|
|
||||||
void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
|
void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
|
||||||
if (property) {
|
if (property) {
|
||||||
CSSPoint delta = (*static_cast<CSSPoint*>(property));
|
CSSPoint delta = (*static_cast<CSSPoint*>(property));
|
||||||
|
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
// The delta is in root content document coordinate space while the
|
|
||||||
// aInput point is in root document coordinate space so convert the
|
|
||||||
// delta to root document space before adding it to the aInput point.
|
|
||||||
float resolution = 1.0f;
|
|
||||||
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
|
|
||||||
resolution = shell->GetResolution();
|
|
||||||
}
|
|
||||||
delta.x = delta.x * resolution;
|
|
||||||
delta.y = delta.y * resolution;
|
|
||||||
#endif // MOZ_SINGLE_PROCESS_APZ
|
|
||||||
input += delta;
|
input += delta;
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
|
@ -147,7 +147,6 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
|
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
// CalculateRectToZoomTo performs a hit test on the frame associated with the
|
// CalculateRectToZoomTo performs a hit test on the frame associated with the
|
||||||
// Root Content Document. Unfortunately that frame does not know about the
|
// Root Content Document. Unfortunately that frame does not know about the
|
||||||
// resolution of the document and so we must remove it before calculating
|
// resolution of the document and so we must remove it before calculating
|
||||||
@ -156,7 +155,6 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
|
|||||||
const float resolution = presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f;
|
const float resolution = presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f;
|
||||||
point.x = point.x / resolution;
|
point.x = point.x / resolution;
|
||||||
point.y = point.y / resolution;
|
point.y = point.y / resolution;
|
||||||
#endif // MOZ_SINGLE_PROCESS_APZ
|
|
||||||
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
|
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
|
||||||
|
|
||||||
uint32_t presShellId;
|
uint32_t presShellId;
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/eintr_wrapper.h"
|
||||||
|
|
||||||
#include "chrome/common/child_process_info.h"
|
#include "chrome/common/child_process_info.h"
|
||||||
|
|
||||||
#include "mozilla/ipc/Transport.h"
|
#include "mozilla/ipc/Transport.h"
|
||||||
@ -41,6 +43,8 @@ CreateTransport(base::ProcessId aProcIdOne,
|
|||||||
fd1 = dup(fd1);
|
fd1 = dup(fd1);
|
||||||
fd2 = dup(fd2);
|
fd2 = dup(fd2);
|
||||||
if (fd1 < 0 || fd2 < 0) {
|
if (fd1 < 0 || fd2 < 0) {
|
||||||
|
HANDLE_EINTR(close(fd1));
|
||||||
|
HANDLE_EINTR(close(fd2));
|
||||||
return NS_ERROR_DUPLICATE_HANDLE;
|
return NS_ERROR_DUPLICATE_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,7 +553,6 @@ DynamicallyLinkModule(JSContext* cx, const CallArgs& args, AsmJSModule& module)
|
|||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case AsmJSModule::Global::ArrayView:
|
case AsmJSModule::Global::ArrayView:
|
||||||
case AsmJSModule::Global::SharedArrayView:
|
|
||||||
case AsmJSModule::Global::ArrayViewCtor:
|
case AsmJSModule::Global::ArrayViewCtor:
|
||||||
if (!ValidateArrayView(cx, global, globalVal))
|
if (!ValidateArrayView(cx, global, globalVal))
|
||||||
return false;
|
return false;
|
||||||
|
@ -100,7 +100,7 @@ class AsmJSModule
|
|||||||
class Global
|
class Global
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Which { Variable, FFI, ArrayView, ArrayViewCtor, SharedArrayView, MathBuiltinFunction,
|
enum Which { Variable, FFI, ArrayView, ArrayViewCtor, MathBuiltinFunction,
|
||||||
AtomicsBuiltinFunction, Constant, SimdCtor, SimdOperation, ByteLength };
|
AtomicsBuiltinFunction, Constant, SimdCtor, SimdOperation, ByteLength };
|
||||||
enum VarInitKind { InitConstant, InitImport };
|
enum VarInitKind { InitConstant, InitImport };
|
||||||
enum ConstantKind { GlobalConstant, MathConstant };
|
enum ConstantKind { GlobalConstant, MathConstant };
|
||||||
@ -189,17 +189,13 @@ class AsmJSModule
|
|||||||
// var i32 = new I32(buffer);
|
// var i32 = new I32(buffer);
|
||||||
// the second import has nothing to validate and thus has a null field.
|
// the second import has nothing to validate and thus has a null field.
|
||||||
PropertyName* maybeViewName() const {
|
PropertyName* maybeViewName() const {
|
||||||
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == SharedArrayView || pod.which_ == ArrayViewCtor);
|
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == ArrayViewCtor);
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
Scalar::Type viewType() const {
|
Scalar::Type viewType() const {
|
||||||
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == SharedArrayView || pod.which_ == ArrayViewCtor);
|
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == ArrayViewCtor);
|
||||||
return pod.u.viewType_;
|
return pod.u.viewType_;
|
||||||
}
|
}
|
||||||
void makeViewShared() {
|
|
||||||
MOZ_ASSERT(pod.which_ == ArrayView);
|
|
||||||
pod.which_ = SharedArrayView;
|
|
||||||
}
|
|
||||||
PropertyName* mathName() const {
|
PropertyName* mathName() const {
|
||||||
MOZ_ASSERT(pod.which_ == MathBuiltinFunction);
|
MOZ_ASSERT(pod.which_ == MathBuiltinFunction);
|
||||||
return name_;
|
return name_;
|
||||||
@ -910,20 +906,18 @@ class AsmJSModule
|
|||||||
g.pod.u.ffiIndex_ = *ffiIndex = pod.numFFIs_++;
|
g.pod.u.ffiIndex_ = *ffiIndex = pod.numFFIs_++;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
}
|
}
|
||||||
bool addArrayView(Scalar::Type vt, PropertyName* maybeField, bool isSharedView) {
|
bool addArrayView(Scalar::Type vt, PropertyName* maybeField) {
|
||||||
MOZ_ASSERT(!isFinished());
|
MOZ_ASSERT(!isFinished());
|
||||||
MOZ_ASSERT(!pod.hasArrayView_ || (pod.isSharedView_ == isSharedView));
|
|
||||||
pod.hasArrayView_ = true;
|
pod.hasArrayView_ = true;
|
||||||
pod.isSharedView_ = isSharedView;
|
pod.isSharedView_ = false;
|
||||||
Global g(Global::ArrayView, maybeField);
|
Global g(Global::ArrayView, maybeField);
|
||||||
g.pod.u.viewType_ = vt;
|
g.pod.u.viewType_ = vt;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
}
|
}
|
||||||
bool addArrayViewCtor(Scalar::Type vt, PropertyName* field, bool isSharedView) {
|
bool addArrayViewCtor(Scalar::Type vt, PropertyName* field) {
|
||||||
MOZ_ASSERT(!isFinished());
|
MOZ_ASSERT(!isFinished());
|
||||||
MOZ_ASSERT(field);
|
MOZ_ASSERT(field);
|
||||||
MOZ_ASSERT(!pod.isSharedView_ || isSharedView);
|
pod.isSharedView_ = false;
|
||||||
pod.isSharedView_ = isSharedView;
|
|
||||||
Global g(Global::ArrayViewCtor, field);
|
Global g(Global::ArrayViewCtor, field);
|
||||||
g.pod.u.viewType_ = vt;
|
g.pod.u.viewType_ = vt;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
@ -978,19 +972,9 @@ class AsmJSModule
|
|||||||
Global& global(unsigned i) {
|
Global& global(unsigned i) {
|
||||||
return globals_[i];
|
return globals_[i];
|
||||||
}
|
}
|
||||||
bool isValidViewSharedness(bool shared) const {
|
|
||||||
if (pod.hasArrayView_)
|
|
||||||
return pod.isSharedView_ == shared;
|
|
||||||
return !pod.isSharedView_ || shared;
|
|
||||||
}
|
|
||||||
void setViewsAreShared() {
|
void setViewsAreShared() {
|
||||||
if (pod.hasArrayView_)
|
if (pod.hasArrayView_)
|
||||||
pod.isSharedView_ = true;
|
pod.isSharedView_ = true;
|
||||||
for (size_t i=0 ; i < globals_.length() ; i++) {
|
|
||||||
Global& g = globals_[i];
|
|
||||||
if (g.which() == Global::ArrayView)
|
|
||||||
g.makeViewShared();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
@ -1014,7 +1014,6 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
uint32_t ffiIndex_;
|
uint32_t ffiIndex_;
|
||||||
struct {
|
struct {
|
||||||
Scalar::Type viewType_;
|
Scalar::Type viewType_;
|
||||||
bool isSharedView_;
|
|
||||||
} viewInfo;
|
} viewInfo;
|
||||||
AsmJSMathBuiltinFunction mathBuiltinFunc_;
|
AsmJSMathBuiltinFunction mathBuiltinFunc_;
|
||||||
AsmJSAtomicsBuiltinFunction atomicsBuiltinFunc_;
|
AsmJSAtomicsBuiltinFunction atomicsBuiltinFunc_;
|
||||||
@ -1072,14 +1071,6 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
MOZ_ASSERT(isAnyArrayView());
|
MOZ_ASSERT(isAnyArrayView());
|
||||||
return u.viewInfo.viewType_;
|
return u.viewInfo.viewType_;
|
||||||
}
|
}
|
||||||
bool viewIsSharedView() const {
|
|
||||||
MOZ_ASSERT(isAnyArrayView());
|
|
||||||
return u.viewInfo.isSharedView_;
|
|
||||||
}
|
|
||||||
void setViewIsSharedView() {
|
|
||||||
MOZ_ASSERT(isAnyArrayView());
|
|
||||||
u.viewInfo.isSharedView_ = true;
|
|
||||||
}
|
|
||||||
bool isMathFunction() const {
|
bool isMathFunction() const {
|
||||||
return which_ == MathBuiltinFunction;
|
return which_ == MathBuiltinFunction;
|
||||||
}
|
}
|
||||||
@ -1402,18 +1393,16 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
global->u.varOrConst.type_ = Type::var(importType).which();
|
global->u.varOrConst.type_ = Type::var(importType).which();
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
bool addArrayView(PropertyName* varName, Scalar::Type vt, PropertyName* maybeField,
|
bool addArrayView(PropertyName* varName, Scalar::Type vt, PropertyName* maybeField)
|
||||||
bool isSharedView)
|
|
||||||
{
|
{
|
||||||
if (!arrayViews_.append(ArrayView(varName, vt)))
|
if (!arrayViews_.append(ArrayView(varName, vt)))
|
||||||
return false;
|
return false;
|
||||||
Global* global = validationLifo_.new_<Global>(Global::ArrayView);
|
Global* global = validationLifo_.new_<Global>(Global::ArrayView);
|
||||||
if (!global)
|
if (!global)
|
||||||
return false;
|
return false;
|
||||||
if (!module().addArrayView(vt, maybeField, isSharedView))
|
if (!module().addArrayView(vt, maybeField))
|
||||||
return false;
|
return false;
|
||||||
global->u.viewInfo.viewType_ = vt;
|
global->u.viewInfo.viewType_ = vt;
|
||||||
global->u.viewInfo.isSharedView_ = isSharedView;
|
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
bool addMathBuiltinFunction(PropertyName* varName, AsmJSMathBuiltinFunction func,
|
bool addMathBuiltinFunction(PropertyName* varName, AsmJSMathBuiltinFunction func,
|
||||||
@ -1497,14 +1486,13 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
global->u.changeHeap.srcEnd_ = fn->pn_pos.end;
|
global->u.changeHeap.srcEnd_ = fn->pn_pos.end;
|
||||||
return globals_.putNew(name, global);
|
return globals_.putNew(name, global);
|
||||||
}
|
}
|
||||||
bool addArrayViewCtor(PropertyName* varName, Scalar::Type vt, PropertyName* fieldName, bool isSharedView) {
|
bool addArrayViewCtor(PropertyName* varName, Scalar::Type vt, PropertyName* fieldName) {
|
||||||
Global* global = validationLifo_.new_<Global>(Global::ArrayViewCtor);
|
Global* global = validationLifo_.new_<Global>(Global::ArrayViewCtor);
|
||||||
if (!global)
|
if (!global)
|
||||||
return false;
|
return false;
|
||||||
if (!module().addArrayViewCtor(vt, fieldName, isSharedView))
|
if (!module().addArrayViewCtor(vt, fieldName))
|
||||||
return false;
|
return false;
|
||||||
global->u.viewInfo.viewType_ = vt;
|
global->u.viewInfo.viewType_ = vt;
|
||||||
global->u.viewInfo.isSharedView_ = isSharedView;
|
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
bool addFFI(PropertyName* varName, PropertyName* field) {
|
bool addFFI(PropertyName* varName, PropertyName* field) {
|
||||||
@ -1612,6 +1600,10 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
return module().minHeapLength();
|
return module().minHeapLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool usesSharedMemory() const {
|
||||||
|
return atomicsPresent_;
|
||||||
|
}
|
||||||
|
|
||||||
// Error handling.
|
// Error handling.
|
||||||
bool hasAlreadyFailed() const {
|
bool hasAlreadyFailed() const {
|
||||||
return !!errorString_;
|
return !!errorString_;
|
||||||
@ -1740,14 +1732,8 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||||||
}
|
}
|
||||||
|
|
||||||
void startFunctionBodies() {
|
void startFunctionBodies() {
|
||||||
if (atomicsPresent_) {
|
if (atomicsPresent_)
|
||||||
for (GlobalMap::Range r = globals_.all() ; !r.empty() ; r.popFront()) {
|
|
||||||
Global* g = r.front().value();
|
|
||||||
if (g->isAnyArrayView())
|
|
||||||
g->setViewIsSharedView();
|
|
||||||
}
|
|
||||||
module().setViewsAreShared();
|
module().setViewsAreShared();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2472,10 +2458,9 @@ CheckGlobalVariableInitImport(ModuleValidator& m, PropertyName* varName, ParseNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsArrayViewCtorName(ModuleValidator& m, PropertyName* name, Scalar::Type* type, bool* shared)
|
IsArrayViewCtorName(ModuleValidator& m, PropertyName* name, Scalar::Type* type)
|
||||||
{
|
{
|
||||||
JSAtomState& names = m.cx()->names();
|
JSAtomState& names = m.cx()->names();
|
||||||
*shared = false;
|
|
||||||
if (name == names.Int8Array) {
|
if (name == names.Int8Array) {
|
||||||
*type = Scalar::Int8;
|
*type = Scalar::Int8;
|
||||||
} else if (name == names.Uint8Array) {
|
} else if (name == names.Uint8Array) {
|
||||||
@ -2526,7 +2511,6 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
|
|||||||
|
|
||||||
PropertyName* field;
|
PropertyName* field;
|
||||||
Scalar::Type type;
|
Scalar::Type type;
|
||||||
bool shared = false;
|
|
||||||
if (ctorExpr->isKind(PNK_DOT)) {
|
if (ctorExpr->isKind(PNK_DOT)) {
|
||||||
ParseNode* base = DotBase(ctorExpr);
|
ParseNode* base = DotBase(ctorExpr);
|
||||||
|
|
||||||
@ -2534,7 +2518,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
|
|||||||
return m.failName(base, "expecting '%s.*Array", globalName);
|
return m.failName(base, "expecting '%s.*Array", globalName);
|
||||||
|
|
||||||
field = DotMember(ctorExpr);
|
field = DotMember(ctorExpr);
|
||||||
if (!IsArrayViewCtorName(m, field, &type, &shared))
|
if (!IsArrayViewCtorName(m, field, &type))
|
||||||
return m.fail(ctorExpr, "could not match typed array name");
|
return m.fail(ctorExpr, "could not match typed array name");
|
||||||
} else {
|
} else {
|
||||||
if (!ctorExpr->isKind(PNK_NAME))
|
if (!ctorExpr->isKind(PNK_NAME))
|
||||||
@ -2550,16 +2534,12 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
|
|||||||
|
|
||||||
field = nullptr;
|
field = nullptr;
|
||||||
type = global->viewType();
|
type = global->viewType();
|
||||||
shared = global->viewIsSharedView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
|
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m.module().isValidViewSharedness(shared))
|
return m.addArrayView(varName, type, field);
|
||||||
return m.failName(ctorExpr, "%s has different sharedness than previous view constructors", globalName);
|
|
||||||
|
|
||||||
return m.addArrayView(varName, type, field, shared);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -2695,12 +2675,8 @@ CheckGlobalDotImport(ModuleValidator& m, PropertyName* varName, ParseNode* initN
|
|||||||
return m.addByteLength(varName);
|
return m.addByteLength(varName);
|
||||||
|
|
||||||
Scalar::Type type;
|
Scalar::Type type;
|
||||||
bool shared = false;
|
if (IsArrayViewCtorName(m, field, &type))
|
||||||
if (IsArrayViewCtorName(m, field, &type, &shared)) {
|
return m.addArrayViewCtor(varName, type, field);
|
||||||
if (!m.module().isValidViewSharedness(shared))
|
|
||||||
return m.failName(initNode, "'%s' has different sharedness than previous view constructors", field);
|
|
||||||
return m.addArrayViewCtor(varName, type, field, shared);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.failName(initNode, "'%s' is not a standard constant or typed array name", field);
|
return m.failName(initNode, "'%s' is not a standard constant or typed array name", field);
|
||||||
}
|
}
|
||||||
@ -6787,6 +6763,12 @@ CheckModule(ExclusiveContext* cx, AsmJSParser& parser, ParseNode* stmtList,
|
|||||||
|
|
||||||
m.startFunctionBodies();
|
m.startFunctionBodies();
|
||||||
|
|
||||||
|
#if !defined(ENABLE_SHARED_ARRAY_BUFFER)
|
||||||
|
if (m.usesSharedMemory())
|
||||||
|
return m.failOffset(m.parser().tokenStream.currentToken().pos.begin,
|
||||||
|
"shared memory and atomics not supported by this build");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!CheckFunctions(m))
|
if (!CheckFunctions(m))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -104,7 +104,8 @@ class FunctionCompiler
|
|||||||
curBlock_->initSlot(info().localSlot(i.index()), ins);
|
curBlock_->initSlot(info().localSlot(i.index()), ins);
|
||||||
if (!mirGen_.ensureBallast())
|
if (!mirGen_.ensureBallast())
|
||||||
return false;
|
return false;
|
||||||
localTypes_.append(args[i.index()]);
|
if (!localTypes_.append(args[i.index()]))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < func_.numVarInits(); i++) {
|
for (unsigned i = 0; i < func_.numVarInits(); i++) {
|
||||||
@ -134,7 +135,8 @@ class FunctionCompiler
|
|||||||
curBlock_->initSlot(info().localSlot(firstVarSlot + i), ins);
|
curBlock_->initSlot(info().localSlot(firstVarSlot + i), ins);
|
||||||
if (!mirGen_.ensureBallast())
|
if (!mirGen_.ensureBallast())
|
||||||
return false;
|
return false;
|
||||||
localTypes_.append(v.type());
|
if (!localTypes_.append(v.type()))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1129,12 +1131,20 @@ class FunctionCompiler
|
|||||||
if (!switchBlock)
|
if (!switchBlock)
|
||||||
return true;
|
return true;
|
||||||
MTableSwitch* mir = switchBlock->lastIns()->toTableSwitch();
|
MTableSwitch* mir = switchBlock->lastIns()->toTableSwitch();
|
||||||
size_t defaultIndex = mir->addDefault(defaultBlock);
|
size_t defaultIndex;
|
||||||
|
if (!mir->addDefault(defaultBlock, &defaultIndex))
|
||||||
|
return false;
|
||||||
for (unsigned i = 0; i < cases.length(); i++) {
|
for (unsigned i = 0; i < cases.length(); i++) {
|
||||||
if (!cases[i])
|
if (!cases[i]) {
|
||||||
mir->addCase(defaultIndex);
|
if (!mir->addCase(defaultIndex))
|
||||||
else
|
return false;
|
||||||
mir->addCase(mir->addSuccessor(cases[i]));
|
} else {
|
||||||
|
size_t caseIndex;
|
||||||
|
if (!mir->addSuccessor(cases[i], &caseIndex))
|
||||||
|
return false;
|
||||||
|
if (!mir->addCase(caseIndex))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (curBlock_) {
|
if (curBlock_) {
|
||||||
MBasicBlock* next;
|
MBasicBlock* next;
|
||||||
|
@ -238,12 +238,6 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evalType == DIRECT_EVAL && caller.script()->isDerivedClassConstructor()) {
|
|
||||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DISABLED_DERIVED_CLASS,
|
|
||||||
"direct eval");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ES5 15.1.2.1 step 1.
|
// ES5 15.1.2.1 step 1.
|
||||||
if (args.length() < 1) {
|
if (args.length() < 1) {
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
|
@ -2783,27 +2783,31 @@ BytecodeEmitter::emitNameIncDec(ParseNode* pn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BytecodeEmitter::emitElemOperands(ParseNode* pn, JSOp op)
|
BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||||
|
|
||||||
if (!emitTree(pn->pn_left))
|
if (!emitTree(pn->pn_left))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (op == JSOP_CALLELEM && !emit1(JSOP_DUP))
|
if (opts == EmitElemOption::IncDec) {
|
||||||
return false;
|
if (!emit1(JSOP_CHECKOBJCOERCIBLE))
|
||||||
|
return false;
|
||||||
|
} else if (opts == EmitElemOption::Call) {
|
||||||
|
if (!emit1(JSOP_DUP))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!emitTree(pn->pn_right))
|
if (!emitTree(pn->pn_right))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isSetElem = op == JSOP_SETELEM || op == JSOP_STRICTSETELEM;
|
if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 2))
|
||||||
if (isSetElem && !emit2(JSOP_PICK, 2))
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
|
BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
|
MOZ_ASSERT(pn->isKind(PNK_ELEM) && pn->as<PropertyByValue>().isSuper());
|
||||||
|
|
||||||
@ -2817,13 +2821,13 @@ BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
|
|||||||
|
|
||||||
// We need to convert the key to an object id first, so that we do not do
|
// We need to convert the key to an object id first, so that we do not do
|
||||||
// it inside both the GETELEM and the SETELEM.
|
// it inside both the GETELEM and the SETELEM.
|
||||||
if (opts == SuperElem_IncDec && !emit1(JSOP_TOID))
|
if (opts == EmitElemOption::IncDec && !emit1(JSOP_TOID))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!emitGetThisForSuperBase(pn->pn_left))
|
if (!emitGetThisForSuperBase(pn->pn_left))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (opts == SuperElem_Call) {
|
if (opts == EmitElemOption::Call) {
|
||||||
if (!emit1(JSOP_SWAP))
|
if (!emit1(JSOP_SWAP))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2835,7 +2839,7 @@ BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
|
|||||||
if (!emit1(JSOP_SUPERBASE))
|
if (!emit1(JSOP_SUPERBASE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (opts == SuperElem_Set && !emit2(JSOP_PICK, 3))
|
if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2854,17 +2858,23 @@ BytecodeEmitter::emitElemOpBase(JSOp op)
|
|||||||
bool
|
bool
|
||||||
BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op)
|
BytecodeEmitter::emitElemOp(ParseNode* pn, JSOp op)
|
||||||
{
|
{
|
||||||
return emitElemOperands(pn, op) && emitElemOpBase(op);
|
EmitElemOption opts = EmitElemOption::Get;
|
||||||
|
if (op == JSOP_CALLELEM)
|
||||||
|
opts = EmitElemOption::Call;
|
||||||
|
else if (op == JSOP_SETELEM || op == JSOP_STRICTSETELEM)
|
||||||
|
opts = EmitElemOption::Set;
|
||||||
|
|
||||||
|
return emitElemOperands(pn, opts) && emitElemOpBase(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
|
BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
|
||||||
{
|
{
|
||||||
SuperElemOptions opts = SuperElem_Get;
|
EmitElemOption opts = EmitElemOption::Get;
|
||||||
if (isCall)
|
if (isCall)
|
||||||
opts = SuperElem_Call;
|
opts = EmitElemOption::Call;
|
||||||
else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
|
else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
|
||||||
opts = SuperElem_Set;
|
opts = EmitElemOption::Set;
|
||||||
|
|
||||||
if (!emitSuperElemOperands(pn, opts))
|
if (!emitSuperElemOperands(pn, opts))
|
||||||
return false;
|
return false;
|
||||||
@ -2885,10 +2895,10 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn)
|
|||||||
bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
|
bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
|
||||||
|
|
||||||
if (isSuper) {
|
if (isSuper) {
|
||||||
if (!emitSuperElemOperands(pn->pn_kid, SuperElem_IncDec))
|
if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (!emitElemOperands(pn->pn_kid, JSOP_GETELEM))
|
if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3465,10 +3475,34 @@ BytecodeEmitter::emitSetThis(ParseNode* pn)
|
|||||||
|
|
||||||
JSOp setOp = name->getOp();
|
JSOp setOp = name->getOp();
|
||||||
|
|
||||||
|
// Handle the eval case. Only accept the strict variant, as eval in a
|
||||||
|
// derived class constructor must be strict.
|
||||||
|
if (setOp == JSOP_STRICTSETNAME) {
|
||||||
|
if (!emitAtomOp(name, JSOP_GETNAME))
|
||||||
|
return false;
|
||||||
|
if (!emit1(JSOP_CHECKTHISREINIT))
|
||||||
|
return false;
|
||||||
|
if (!emit1(JSOP_POP))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!emitAtomOp(name, JSOP_BINDNAME))
|
||||||
|
return false;
|
||||||
|
if (!emit1(JSOP_SWAP))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return emitAtomOp(name, setOp);
|
||||||
|
}
|
||||||
|
|
||||||
JSOp getOp;
|
JSOp getOp;
|
||||||
switch (setOp) {
|
switch (setOp) {
|
||||||
case JSOP_SETLOCAL: getOp = JSOP_GETLOCAL; break;
|
case JSOP_SETLOCAL:
|
||||||
case JSOP_SETALIASEDVAR: getOp = JSOP_GETALIASEDVAR; break;
|
getOp = JSOP_GETLOCAL;
|
||||||
|
setOp = JSOP_INITLEXICAL;
|
||||||
|
break;
|
||||||
|
case JSOP_SETALIASEDVAR:
|
||||||
|
getOp = JSOP_GETALIASEDVAR;
|
||||||
|
setOp = JSOP_INITALIASEDLEXICAL;
|
||||||
|
break;
|
||||||
default: MOZ_CRASH("Unexpected op");
|
default: MOZ_CRASH("Unexpected op");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4379,13 +4413,25 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
|
|||||||
* i' to be hoisted out of the loop.
|
* i' to be hoisted out of the loop.
|
||||||
*/
|
*/
|
||||||
MOZ_ASSERT(binding->isOp(JSOP_NOP));
|
MOZ_ASSERT(binding->isOp(JSOP_NOP));
|
||||||
MOZ_ASSERT(emitOption != DefineVars && emitOption != AnnexB);
|
MOZ_ASSERT(emitOption != DefineVars);
|
||||||
|
MOZ_ASSERT_IF(emitOption == AnnexB, binding->pn_left->isKind(PNK_NAME));
|
||||||
|
|
||||||
/*
|
// To allow the front end to rewrite |var f = x;| as |f = x;| when a
|
||||||
* To allow the front end to rewrite var f = x; as f = x; when a
|
// |function f(){}| precedes the var, detect simple name assignment
|
||||||
* function f(){} precedes the var, detect simple name assignment
|
// here and initialize the name.
|
||||||
* here and initialize the name.
|
//
|
||||||
*/
|
// There is a corner case where a function declaration synthesizes
|
||||||
|
// an Annex B declaration, which in turn gets rewritten later as a
|
||||||
|
// simple assignment due to hoisted function declaration of the
|
||||||
|
// same name. For example,
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// // Synthesizes an Annex B declaration because no 'f' binding
|
||||||
|
// // yet exists. This later gets rewritten as an assignment when
|
||||||
|
// // the outer function 'f' gets hoisted.
|
||||||
|
// function f() {}
|
||||||
|
// }
|
||||||
|
// function f() {}
|
||||||
if (binding->pn_left->isKind(PNK_NAME)) {
|
if (binding->pn_left->isKind(PNK_NAME)) {
|
||||||
if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
|
if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
|
||||||
return false;
|
return false;
|
||||||
|
@ -519,7 +519,8 @@ struct BytecodeEmitter
|
|||||||
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
||||||
// opcode onto the stack in the right order. In the case of SETELEM, the
|
// opcode onto the stack in the right order. In the case of SETELEM, the
|
||||||
// value to be assigned must already be pushed.
|
// value to be assigned must already be pushed.
|
||||||
bool emitElemOperands(ParseNode* pn, JSOp op);
|
enum class EmitElemOption { Get, Set, Call, IncDec };
|
||||||
|
bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
|
||||||
|
|
||||||
bool emitElemOpBase(JSOp op);
|
bool emitElemOpBase(JSOp op);
|
||||||
bool emitElemOp(ParseNode* pn, JSOp op);
|
bool emitElemOp(ParseNode* pn, JSOp op);
|
||||||
@ -654,8 +655,7 @@ struct BytecodeEmitter
|
|||||||
bool emitClass(ParseNode* pn);
|
bool emitClass(ParseNode* pn);
|
||||||
bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
|
bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
|
||||||
bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||||
enum SuperElemOptions { SuperElem_Get, SuperElem_Set, SuperElem_Call, SuperElem_IncDec };
|
bool emitSuperElemOperands(ParseNode* pn, EmitElemOption opts = EmitElemOption::Get);
|
||||||
bool emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts = SuperElem_Get);
|
|
||||||
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,8 +125,12 @@ SharedContext::computeAllowSyntax(JSObject* staticScope)
|
|||||||
// Any function supports new.target.
|
// Any function supports new.target.
|
||||||
allowNewTarget_ = true;
|
allowNewTarget_ = true;
|
||||||
allowSuperProperty_ = it.fun().allowSuperProperty();
|
allowSuperProperty_ = it.fun().allowSuperProperty();
|
||||||
if (it.maybeFunctionBox())
|
if (it.maybeFunctionBox()) {
|
||||||
superScopeAlreadyNeedsHomeObject_ = it.maybeFunctionBox()->needsHomeObject();
|
superScopeAlreadyNeedsHomeObject_ = it.maybeFunctionBox()->needsHomeObject();
|
||||||
|
allowSuperCall_ = it.maybeFunctionBox()->isDerivedClassConstructor();
|
||||||
|
} else {
|
||||||
|
allowSuperCall_ = it.fun().isDerivedClassConstructor();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7470,11 +7474,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
|||||||
if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
|
if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (pc->sc->isFunctionBox() && pc->sc->asFunctionBox()->isDerivedClassConstructor()) {
|
|
||||||
report(ParseError, false, null(), JSMSG_DISABLED_DERIVED_CLASS, "arrow functions");
|
|
||||||
return null();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
|
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
|
||||||
if (!arrowFunc)
|
if (!arrowFunc)
|
||||||
return null();
|
return null();
|
||||||
@ -8890,7 +8889,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
|||||||
tt == TOK_NO_SUBS_TEMPLATE)
|
tt == TOK_NO_SUBS_TEMPLATE)
|
||||||
{
|
{
|
||||||
if (handler.isSuperBase(lhs)) {
|
if (handler.isSuperBase(lhs)) {
|
||||||
if (!pc->sc->isFunctionBox() || !pc->sc->asFunctionBox()->isDerivedClassConstructor()) {
|
if (!pc->sc->allowSuperCall()) {
|
||||||
report(ParseError, false, null(), JSMSG_BAD_SUPERCALL);
|
report(ParseError, false, null(), JSMSG_BAD_SUPERCALL);
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
@ -202,6 +202,7 @@ class SharedContext
|
|||||||
|
|
||||||
bool allowNewTarget_;
|
bool allowNewTarget_;
|
||||||
bool allowSuperProperty_;
|
bool allowSuperProperty_;
|
||||||
|
bool allowSuperCall_;
|
||||||
bool inWith_;
|
bool inWith_;
|
||||||
bool needsThisTDZChecks_;
|
bool needsThisTDZChecks_;
|
||||||
bool superScopeAlreadyNeedsHomeObject_;
|
bool superScopeAlreadyNeedsHomeObject_;
|
||||||
@ -217,6 +218,7 @@ class SharedContext
|
|||||||
thisBinding_(ThisBinding::Global),
|
thisBinding_(ThisBinding::Global),
|
||||||
allowNewTarget_(false),
|
allowNewTarget_(false),
|
||||||
allowSuperProperty_(false),
|
allowSuperProperty_(false),
|
||||||
|
allowSuperCall_(false),
|
||||||
inWith_(false),
|
inWith_(false),
|
||||||
needsThisTDZChecks_(false),
|
needsThisTDZChecks_(false),
|
||||||
superScopeAlreadyNeedsHomeObject_(false)
|
superScopeAlreadyNeedsHomeObject_(false)
|
||||||
@ -244,6 +246,7 @@ class SharedContext
|
|||||||
|
|
||||||
bool allowNewTarget() const { return allowNewTarget_; }
|
bool allowNewTarget() const { return allowNewTarget_; }
|
||||||
bool allowSuperProperty() const { return allowSuperProperty_; }
|
bool allowSuperProperty() const { return allowSuperProperty_; }
|
||||||
|
bool allowSuperCall() const { return allowSuperCall_; }
|
||||||
bool inWith() const { return inWith_; }
|
bool inWith() const { return inWith_; }
|
||||||
bool needsThisTDZChecks() const { return needsThisTDZChecks_; }
|
bool needsThisTDZChecks() const { return needsThisTDZChecks_; }
|
||||||
|
|
||||||
|
@ -877,13 +877,15 @@ TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
|||||||
ungetChar('*');
|
ungetChar('*');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokenbuf.append(c);
|
if (!tokenbuf.append(c))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenbuf.empty())
|
if (tokenbuf.empty()) {
|
||||||
// The directive's URL was missing, but this is not quite an
|
// The directive's URL was missing, but this is not quite an
|
||||||
// exception that we should stop and drop everything for.
|
// exception that we should stop and drop everything for.
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
size_t length = tokenbuf.length();
|
size_t length = tokenbuf.length();
|
||||||
|
|
||||||
|
33
js/src/jit-test/tests/asm.js/gating.js
Normal file
33
js/src/jit-test/tests/asm.js/gating.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Check gating of shared memory features in asm.js (bug 1171540,
|
||||||
|
// bug 1231624).
|
||||||
|
//
|
||||||
|
// In asm.js, importing any atomic is a signal that shared memory is
|
||||||
|
// being used. If an atomic is imported, and if shared memory is
|
||||||
|
// disabled in the build or in the run then a type error should be
|
||||||
|
// signaled for the module at the end of the declaration section and
|
||||||
|
// the module should not be an asm.js module.
|
||||||
|
|
||||||
|
if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
|
||||||
|
quit(0);
|
||||||
|
|
||||||
|
// This code is not run, we only care whether it compiles as asm.js.
|
||||||
|
|
||||||
|
function module_a(stdlib, foreign, heap) {
|
||||||
|
"use asm";
|
||||||
|
|
||||||
|
var i32a = new stdlib.Int32Array(heap);
|
||||||
|
var ld = stdlib.Atomics.load;
|
||||||
|
|
||||||
|
// There should be a type error around this line if shared memory
|
||||||
|
// is not enabled.
|
||||||
|
|
||||||
|
function do_load() {
|
||||||
|
var v = 0;
|
||||||
|
v = ld(i32a, 0)|0; // It's not actually necessary to use the atomic op
|
||||||
|
return v|0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { load: do_load };
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEq(isAsmJSModule(module_a), !!this.SharedArrayBuffer);
|
@ -6,6 +6,8 @@ for (var i = 0; i < 10; i++) {
|
|||||||
gcslice()
|
gcslice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.SharedArrayBuffer)
|
||||||
|
quit(0);
|
||||||
|
|
||||||
for (var i = 0; i < 10; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
x = new SharedArrayBuffer(4)
|
x = new SharedArrayBuffer(4)
|
||||||
|
@ -3588,8 +3588,7 @@ BaselineCompiler::emit_JSOP_RETRVAL()
|
|||||||
return emitReturn();
|
return emitReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, HandleValue,
|
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, MutableHandleValue);
|
||||||
MutableHandleValue);
|
|
||||||
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(js::ToIdOperation);
|
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(js::ToIdOperation);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -3605,10 +3604,7 @@ BaselineCompiler::emit_JSOP_TOID()
|
|||||||
|
|
||||||
prepareVMCall();
|
prepareVMCall();
|
||||||
|
|
||||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
|
|
||||||
|
|
||||||
pushArg(R0);
|
pushArg(R0);
|
||||||
pushArg(R1);
|
|
||||||
pushArg(ImmPtr(pc));
|
pushArg(ImmPtr(pc));
|
||||||
pushArg(ImmGCPtr(script));
|
pushArg(ImmGCPtr(script));
|
||||||
|
|
||||||
@ -3621,6 +3617,32 @@ BaselineCompiler::emit_JSOP_TOID()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef bool (*ThrowObjectCoercibleFn)(JSContext*, HandleValue);
|
||||||
|
static const VMFunction ThrowObjectCoercibleInfo = FunctionInfo<ThrowObjectCoercibleFn>(ThrowObjectCoercible);
|
||||||
|
|
||||||
|
bool
|
||||||
|
BaselineCompiler::emit_JSOP_CHECKOBJCOERCIBLE()
|
||||||
|
{
|
||||||
|
frame.syncStack(0);
|
||||||
|
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
|
||||||
|
|
||||||
|
Label fail, done;
|
||||||
|
|
||||||
|
masm.branchTestUndefined(Assembler::Equal, R0, &fail);
|
||||||
|
masm.branchTestNull(Assembler::NotEqual, R0, &done);
|
||||||
|
|
||||||
|
masm.bind(&fail);
|
||||||
|
prepareVMCall();
|
||||||
|
|
||||||
|
pushArg(R0);
|
||||||
|
|
||||||
|
if (!callVM(ThrowObjectCoercibleInfo))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
masm.bind(&done);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
typedef JSString* (*ToStringFn)(JSContext*, HandleValue);
|
typedef JSString* (*ToStringFn)(JSContext*, HandleValue);
|
||||||
static const VMFunction ToStringInfo = FunctionInfo<ToStringFn>(ToStringSlow);
|
static const VMFunction ToStringInfo = FunctionInfo<ToStringFn>(ToStringSlow);
|
||||||
|
|
||||||
|
@ -219,7 +219,8 @@ namespace jit {
|
|||||||
_(JSOP_INITHIDDENPROP_SETTER) \
|
_(JSOP_INITHIDDENPROP_SETTER) \
|
||||||
_(JSOP_INITHIDDENELEM) \
|
_(JSOP_INITHIDDENELEM) \
|
||||||
_(JSOP_INITHIDDENELEM_GETTER) \
|
_(JSOP_INITHIDDENELEM_GETTER) \
|
||||||
_(JSOP_INITHIDDENELEM_SETTER)
|
_(JSOP_INITHIDDENELEM_SETTER) \
|
||||||
|
_(JSOP_CHECKOBJCOERCIBLE)
|
||||||
|
|
||||||
class BaselineCompiler : public BaselineCompilerSpecific
|
class BaselineCompiler : public BaselineCompilerSpecific
|
||||||
{
|
{
|
||||||
|
@ -2769,6 +2769,11 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't try to attach stubs that wish to be hidden. We don't know how to
|
||||||
|
// have different enumerability in the stubs for the moment.
|
||||||
|
if (op == JSOP_INITHIDDENELEM)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Overwrite the object on the stack (pushed for the decompiler) with the rhs.
|
// Overwrite the object on the stack (pushed for the decompiler) with the rhs.
|
||||||
MOZ_ASSERT(stack[2] == objv);
|
MOZ_ASSERT(stack[2] == objv);
|
||||||
stack[2] = rhs;
|
stack[2] = rhs;
|
||||||
|
@ -9061,7 +9061,7 @@ CodeGenerator::visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool)
|
|||||||
masm.jump(ool->rejoin());
|
masm.jump(ool->rejoin());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, HandleValue,
|
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue,
|
||||||
MutableHandleValue);
|
MutableHandleValue);
|
||||||
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(ToIdOperation);
|
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(ToIdOperation);
|
||||||
|
|
||||||
@ -9076,7 +9076,6 @@ CodeGenerator::visitToIdV(LToIdV* lir)
|
|||||||
OutOfLineCode* ool = oolCallVM(ToIdInfo, lir,
|
OutOfLineCode* ool = oolCallVM(ToIdInfo, lir,
|
||||||
ArgList(ImmGCPtr(current->mir()->info().script()),
|
ArgList(ImmGCPtr(current->mir()->info().script()),
|
||||||
ImmPtr(lir->mir()->resumePoint()->pc()),
|
ImmPtr(lir->mir()->resumePoint()->pc()),
|
||||||
ToValue(lir, LToIdV::Object),
|
|
||||||
ToValue(lir, LToIdV::Index)),
|
ToValue(lir, LToIdV::Index)),
|
||||||
StoreValueTo(out));
|
StoreValueTo(out));
|
||||||
|
|
||||||
@ -10369,6 +10368,22 @@ CodeGenerator::visitCheckReturn(LCheckReturn* ins)
|
|||||||
masm.bind(&noChecks);
|
masm.bind(&noChecks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef bool (*ThrowObjCoercibleFn)(JSContext*, HandleValue);
|
||||||
|
static const VMFunction ThrowObjectCoercibleInfo = FunctionInfo<ThrowObjCoercibleFn>(ThrowObjectCoercible);
|
||||||
|
|
||||||
|
void
|
||||||
|
CodeGenerator::visitCheckObjCoercible(LCheckObjCoercible* ins)
|
||||||
|
{
|
||||||
|
ValueOperand checkValue = ToValue(ins, LCheckObjCoercible::CheckValue);
|
||||||
|
Label fail, done;
|
||||||
|
masm.branchTestNull(Assembler::Equal, checkValue, &fail);
|
||||||
|
masm.branchTestUndefined(Assembler::NotEqual, checkValue, &done);
|
||||||
|
masm.bind(&fail);
|
||||||
|
pushArg(checkValue);
|
||||||
|
callVM(ThrowObjectCoercibleInfo, ins);
|
||||||
|
masm.bind(&done);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGenerator::visitRandom(LRandom* ins)
|
CodeGenerator::visitRandom(LRandom* ins)
|
||||||
{
|
{
|
||||||
|
@ -345,6 +345,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||||||
void visitNewTarget(LNewTarget* ins);
|
void visitNewTarget(LNewTarget* ins);
|
||||||
void visitArrowNewTarget(LArrowNewTarget* ins);
|
void visitArrowNewTarget(LArrowNewTarget* ins);
|
||||||
void visitCheckReturn(LCheckReturn* ins);
|
void visitCheckReturn(LCheckReturn* ins);
|
||||||
|
void visitCheckObjCoercible(LCheckObjCoercible* ins);
|
||||||
|
|
||||||
void visitCheckOverRecursed(LCheckOverRecursed* lir);
|
void visitCheckOverRecursed(LCheckOverRecursed* lir);
|
||||||
void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);
|
void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);
|
||||||
|
@ -354,9 +354,10 @@ class ExecutableAllocator
|
|||||||
// At this point, local |pool| is the owner.
|
// At this point, local |pool| is the owner.
|
||||||
|
|
||||||
if (m_smallPools.length() < maxSmallPools) {
|
if (m_smallPools.length() < maxSmallPools) {
|
||||||
// We haven't hit the maximum number of live pools; add the new pool.
|
// We haven't hit the maximum number of live pools; add the new pool.
|
||||||
m_smallPools.append(pool);
|
// If append() OOMs, we just return an unshared allocator.
|
||||||
pool->addRef();
|
if (m_smallPools.append(pool))
|
||||||
|
pool->addRef();
|
||||||
} else {
|
} else {
|
||||||
// Find the pool with the least space.
|
// Find the pool with the least space.
|
||||||
int iMin = 0;
|
int iMin = 0;
|
||||||
|
@ -134,7 +134,9 @@ class LinearSum
|
|||||||
: terms_(other.terms_.allocPolicy()),
|
: terms_(other.terms_.allocPolicy()),
|
||||||
constant_(other.constant_)
|
constant_(other.constant_)
|
||||||
{
|
{
|
||||||
terms_.appendAll(other.terms_);
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!terms_.appendAll(other.terms_))
|
||||||
|
oomUnsafe.crash("LinearSum::LinearSum");
|
||||||
}
|
}
|
||||||
|
|
||||||
// These return false on an integer overflow, and afterwards the sum must
|
// These return false on an integer overflow, and afterwards the sum must
|
||||||
|
@ -615,7 +615,8 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loopHeaders_.append(LoopHeader(start, entry));
|
if (!loopHeaders_.append(LoopHeader(start, entry)))
|
||||||
|
return false;
|
||||||
|
|
||||||
jsbytecode* last = nullptr;
|
jsbytecode* last = nullptr;
|
||||||
jsbytecode* earlier = nullptr;
|
jsbytecode* earlier = nullptr;
|
||||||
@ -2098,6 +2099,9 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||||||
case JSOP_NEWTARGET:
|
case JSOP_NEWTARGET:
|
||||||
return jsop_newtarget();
|
return jsop_newtarget();
|
||||||
|
|
||||||
|
case JSOP_CHECKOBJCOERCIBLE:
|
||||||
|
return jsop_checkobjcoercible();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
case JSOP_PUSHBLOCKSCOPE:
|
case JSOP_PUSHBLOCKSCOPE:
|
||||||
case JSOP_FRESHENBLOCKSCOPE:
|
case JSOP_FRESHENBLOCKSCOPE:
|
||||||
@ -3419,8 +3423,12 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote* sn)
|
|||||||
MBasicBlock* defaultcase = newBlock(current, defaultpc);
|
MBasicBlock* defaultcase = newBlock(current, defaultpc);
|
||||||
if (!defaultcase)
|
if (!defaultcase)
|
||||||
return ControlStatus_Error;
|
return ControlStatus_Error;
|
||||||
tableswitch->addDefault(defaultcase);
|
|
||||||
tableswitch->addBlock(defaultcase);
|
if (!tableswitch->addDefault(defaultcase))
|
||||||
|
return ControlStatus_Error;
|
||||||
|
|
||||||
|
if (!tableswitch->addBlock(defaultcase))
|
||||||
|
return ControlStatus_Error;
|
||||||
|
|
||||||
// Create cases
|
// Create cases
|
||||||
jsbytecode* casepc = nullptr;
|
jsbytecode* casepc = nullptr;
|
||||||
@ -3448,14 +3456,22 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote* sn)
|
|||||||
if (!caseblock)
|
if (!caseblock)
|
||||||
return ControlStatus_Error;
|
return ControlStatus_Error;
|
||||||
|
|
||||||
tableswitch->addBlock(caseblock);
|
if (!tableswitch->addBlock(caseblock))
|
||||||
|
return ControlStatus_Error;
|
||||||
|
|
||||||
// Add constant to indicate which case this is for use by
|
// Add constant to indicate which case this is for use by
|
||||||
// processNextTableSwitchCase.
|
// processNextTableSwitchCase.
|
||||||
MConstant* constant = MConstant::New(alloc(), Int32Value(i + low));
|
MConstant* constant = MConstant::New(alloc(), Int32Value(i + low));
|
||||||
caseblock->add(constant);
|
caseblock->add(constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
tableswitch->addCase(tableswitch->addSuccessor(caseblock));
|
size_t caseIndex;
|
||||||
|
if (!tableswitch->addSuccessor(caseblock, &caseIndex))
|
||||||
|
return ControlStatus_Error;
|
||||||
|
|
||||||
|
if (!tableswitch->addCase(caseIndex))
|
||||||
|
return ControlStatus_Error;
|
||||||
|
|
||||||
pc2 += JUMP_OFFSET_LEN;
|
pc2 += JUMP_OFFSET_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5389,7 +5405,7 @@ IonBuilder::selectInliningTargets(const ObjectVector& targets, CallInfo& callInf
|
|||||||
inlineable = false;
|
inlineable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
choiceSet.append(inlineable);
|
choiceSet.infallibleAppend(inlineable);
|
||||||
if (inlineable)
|
if (inlineable)
|
||||||
*numInlineable += 1;
|
*numInlineable += 1;
|
||||||
}
|
}
|
||||||
@ -5881,7 +5897,8 @@ IonBuilder::inlineCalls(CallInfo& callInfo, const ObjectVector& targets, BoolVec
|
|||||||
|
|
||||||
// Connect the inline path to the returnBlock.
|
// Connect the inline path to the returnBlock.
|
||||||
ObjectGroup* funcGroup = target->isSingleton() ? nullptr : target->group();
|
ObjectGroup* funcGroup = target->isSingleton() ? nullptr : target->group();
|
||||||
dispatch->addCase(target, funcGroup, inlineBlock);
|
if (!dispatch->addCase(target, funcGroup, inlineBlock))
|
||||||
|
return false;
|
||||||
|
|
||||||
MDefinition* retVal = inlineReturnBlock->peek(-1);
|
MDefinition* retVal = inlineReturnBlock->peek(-1);
|
||||||
retPhi->addInput(retVal);
|
retPhi->addInput(retVal);
|
||||||
@ -10309,6 +10326,31 @@ IonBuilder::jsop_rest()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IonBuilder::jsop_checkobjcoercible()
|
||||||
|
{
|
||||||
|
MDefinition* toCheck = current->peek(-1);
|
||||||
|
|
||||||
|
if (!toCheck->mightBeType(MIRType_Undefined) &&
|
||||||
|
!toCheck->mightBeType(MIRType_Null))
|
||||||
|
{
|
||||||
|
toCheck->setImplicitlyUsedUnchecked();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(toCheck->type() == MIRType_Value ||
|
||||||
|
toCheck->type() == MIRType_Null ||
|
||||||
|
toCheck->type() == MIRType_Undefined);
|
||||||
|
|
||||||
|
// If we want to squeeze more perf here, we can throw without checking,
|
||||||
|
// if IsNullOrUndefined(toCheck->type()). Since this is a failure case,
|
||||||
|
// it should be OK.
|
||||||
|
MCheckObjCoercible* check = MCheckObjCoercible::New(alloc(), current->pop());
|
||||||
|
current->add(check);
|
||||||
|
current->push(check);
|
||||||
|
return resumeAfter(check);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed)
|
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed)
|
||||||
{
|
{
|
||||||
@ -13021,7 +13063,7 @@ IonBuilder::jsop_toid()
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
MDefinition* index = current->pop();
|
MDefinition* index = current->pop();
|
||||||
MToId* ins = MToId::New(alloc(), current->peek(-1), index);
|
MToId* ins = MToId::New(alloc(), index);
|
||||||
|
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
@ -738,6 +738,7 @@ class IonBuilder
|
|||||||
bool jsop_setaliasedvar(ScopeCoordinate sc);
|
bool jsop_setaliasedvar(ScopeCoordinate sc);
|
||||||
bool jsop_debugger();
|
bool jsop_debugger();
|
||||||
bool jsop_newtarget();
|
bool jsop_newtarget();
|
||||||
|
bool jsop_checkobjcoercible();
|
||||||
|
|
||||||
/* Inlining. */
|
/* Inlining. */
|
||||||
|
|
||||||
|
@ -1097,8 +1097,7 @@ void
|
|||||||
LIRGenerator::visitToId(MToId* ins)
|
LIRGenerator::visitToId(MToId* ins)
|
||||||
{
|
{
|
||||||
LToIdV* lir = new(alloc()) LToIdV(tempDouble());
|
LToIdV* lir = new(alloc()) LToIdV(tempDouble());
|
||||||
useBox(lir, LToIdV::Object, ins->lhs());
|
useBox(lir, LToIdV::Index, ins->input());
|
||||||
useBox(lir, LToIdV::Index, ins->rhs());
|
|
||||||
defineBox(lir, ins);
|
defineBox(lir, ins);
|
||||||
assignSafepoint(lir, ins);
|
assignSafepoint(lir, ins);
|
||||||
}
|
}
|
||||||
@ -4331,6 +4330,19 @@ LIRGenerator::visitCheckReturn(MCheckReturn* ins)
|
|||||||
redefine(ins, retVal);
|
redefine(ins, retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LIRGenerator::visitCheckObjCoercible(MCheckObjCoercible* ins)
|
||||||
|
{
|
||||||
|
MDefinition* checkVal = ins->checkValue();
|
||||||
|
MOZ_ASSERT(checkVal->type() == MIRType_Value);
|
||||||
|
|
||||||
|
LCheckObjCoercible* lir = new(alloc()) LCheckObjCoercible();
|
||||||
|
useBoxAtStart(lir, LCheckObjCoercible::CheckValue, checkVal);
|
||||||
|
redefine(ins, checkVal);
|
||||||
|
add(lir, ins);
|
||||||
|
assignSafepoint(lir, ins);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
|
SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
|
||||||
{
|
{
|
||||||
|
@ -310,6 +310,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||||||
void visitAtomicIsLockFree(MAtomicIsLockFree* ins);
|
void visitAtomicIsLockFree(MAtomicIsLockFree* ins);
|
||||||
void visitGuardSharedTypedArray(MGuardSharedTypedArray* ins);
|
void visitGuardSharedTypedArray(MGuardSharedTypedArray* ins);
|
||||||
void visitCheckReturn(MCheckReturn* ins);
|
void visitCheckReturn(MCheckReturn* ins);
|
||||||
|
void visitCheckObjCoercible(MCheckObjCoercible* ins);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
|
@ -2536,11 +2536,11 @@ class MTableSwitch final
|
|||||||
return successors_.length();
|
return successors_.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t addSuccessor(MBasicBlock* successor) {
|
bool addSuccessor(MBasicBlock* successor, size_t* index) {
|
||||||
MOZ_ASSERT(successors_.length() < (size_t)(high_ - low_ + 2));
|
MOZ_ASSERT(successors_.length() < (size_t)(high_ - low_ + 2));
|
||||||
MOZ_ASSERT(!successors_.empty());
|
MOZ_ASSERT(!successors_.empty());
|
||||||
successors_.append(successor);
|
*index = successors_.length();
|
||||||
return successors_.length() - 1;
|
return successors_.append(successor);
|
||||||
}
|
}
|
||||||
|
|
||||||
MBasicBlock* getSuccessor(size_t i) const override {
|
MBasicBlock* getSuccessor(size_t i) const override {
|
||||||
@ -2581,14 +2581,15 @@ class MTableSwitch final
|
|||||||
return high() - low() + 1;
|
return high() - low() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t addDefault(MBasicBlock* block) {
|
bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
|
||||||
MOZ_ASSERT(successors_.empty());
|
MOZ_ASSERT(successors_.empty());
|
||||||
successors_.append(block);
|
if (index)
|
||||||
return 0;
|
*index = 0;
|
||||||
|
return successors_.append(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCase(size_t successorIndex) {
|
bool addCase(size_t successorIndex) {
|
||||||
cases_.append(successorIndex);
|
return cases_.append(successorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
MBasicBlock* getBlock(size_t i) const {
|
MBasicBlock* getBlock(size_t i) const {
|
||||||
@ -2596,8 +2597,8 @@ class MTableSwitch final
|
|||||||
return blocks_[i];
|
return blocks_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void addBlock(MBasicBlock* block) {
|
bool addBlock(MBasicBlock* block) {
|
||||||
blocks_.append(block);
|
return blocks_.append(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinition* getOperand(size_t index) const override {
|
MDefinition* getOperand(size_t index) const override {
|
||||||
@ -5371,11 +5372,11 @@ class MTypeOf
|
|||||||
};
|
};
|
||||||
|
|
||||||
class MToId
|
class MToId
|
||||||
: public MBinaryInstruction,
|
: public MUnaryInstruction,
|
||||||
public BoxInputsPolicy::Data
|
public BoxInputsPolicy::Data
|
||||||
{
|
{
|
||||||
MToId(MDefinition* object, MDefinition* index)
|
explicit MToId(MDefinition* index)
|
||||||
: MBinaryInstruction(object, index)
|
: MUnaryInstruction(index)
|
||||||
{
|
{
|
||||||
setResultType(MIRType_Value);
|
setResultType(MIRType_Value);
|
||||||
}
|
}
|
||||||
@ -5383,8 +5384,8 @@ class MToId
|
|||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(ToId)
|
INSTRUCTION_HEADER(ToId)
|
||||||
|
|
||||||
static MToId* New(TempAllocator& alloc, MDefinition* object, MDefinition* index) {
|
static MToId* New(TempAllocator& alloc, MDefinition* index) {
|
||||||
return new(alloc) MToId(object, index);
|
return new(alloc) MToId(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -10646,8 +10647,8 @@ class MDispatchInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void addCase(JSFunction* func, ObjectGroup* funcGroup, MBasicBlock* block) {
|
bool addCase(JSFunction* func, ObjectGroup* funcGroup, MBasicBlock* block) {
|
||||||
map_.append(Entry(func, funcGroup, block));
|
return map_.append(Entry(func, funcGroup, block));
|
||||||
}
|
}
|
||||||
uint32_t numCases() const {
|
uint32_t numCases() const {
|
||||||
return map_.length();
|
return map_.length();
|
||||||
@ -13365,6 +13366,29 @@ class MDebugger : public MNullaryInstruction
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MCheckObjCoercible
|
||||||
|
: public MUnaryInstruction,
|
||||||
|
public BoxInputsPolicy::Data
|
||||||
|
{
|
||||||
|
explicit MCheckObjCoercible(MDefinition* toCheck)
|
||||||
|
: MUnaryInstruction(toCheck)
|
||||||
|
{
|
||||||
|
setGuard();
|
||||||
|
setResultType(MIRType_Value);
|
||||||
|
setResultTypeSet(toCheck->resultTypeSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
INSTRUCTION_HEADER(CheckObjCoercible)
|
||||||
|
static MCheckObjCoercible* New(TempAllocator& alloc, MDefinition* toCheck) {
|
||||||
|
return new(alloc) MCheckObjCoercible(toCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDefinition* checkValue() {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class MAsmJSNeg
|
class MAsmJSNeg
|
||||||
: public MUnaryInstruction,
|
: public MUnaryInstruction,
|
||||||
public NoTypePolicy::Data
|
public NoTypePolicy::Data
|
||||||
|
@ -279,7 +279,8 @@ namespace jit {
|
|||||||
_(Debugger) \
|
_(Debugger) \
|
||||||
_(NewTarget) \
|
_(NewTarget) \
|
||||||
_(ArrowNewTarget) \
|
_(ArrowNewTarget) \
|
||||||
_(CheckReturn)
|
_(CheckReturn) \
|
||||||
|
_(CheckObjCoercible)
|
||||||
|
|
||||||
// Forward declarations of MIR types.
|
// Forward declarations of MIR types.
|
||||||
#define FORWARD_DECLARE(op) class M##op;
|
#define FORWARD_DECLARE(op) class M##op;
|
||||||
|
@ -65,9 +65,13 @@ struct AllocationIntegrityState
|
|||||||
|
|
||||||
InstructionInfo(const InstructionInfo& o)
|
InstructionInfo(const InstructionInfo& o)
|
||||||
{
|
{
|
||||||
inputs.appendAll(o.inputs);
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
temps.appendAll(o.temps);
|
if (!inputs.appendAll(o.inputs) ||
|
||||||
outputs.appendAll(o.outputs);
|
!temps.appendAll(o.temps) ||
|
||||||
|
!outputs.appendAll(o.outputs))
|
||||||
|
{
|
||||||
|
oomUnsafe.crash("InstructionInfo::InstructionInfo");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Vector<InstructionInfo, 0, SystemAllocPolicy> instructions;
|
Vector<InstructionInfo, 0, SystemAllocPolicy> instructions;
|
||||||
@ -76,7 +80,9 @@ struct AllocationIntegrityState
|
|||||||
Vector<InstructionInfo, 5, SystemAllocPolicy> phis;
|
Vector<InstructionInfo, 5, SystemAllocPolicy> phis;
|
||||||
BlockInfo() {}
|
BlockInfo() {}
|
||||||
BlockInfo(const BlockInfo& o) {
|
BlockInfo(const BlockInfo& o) {
|
||||||
phis.appendAll(o.phis);
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!phis.appendAll(o.phis))
|
||||||
|
oomUnsafe.crash("BlockInfo::BlockInfo");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Vector<BlockInfo, 0, SystemAllocPolicy> blocks;
|
Vector<BlockInfo, 0, SystemAllocPolicy> blocks;
|
||||||
|
@ -1311,6 +1311,15 @@ BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame)
|
|||||||
return ThrowUninitializedThis(cx, frame);
|
return ThrowUninitializedThis(cx, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ThrowObjectCoercible(JSContext* cx, HandleValue v)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(v.isUndefined() || v.isNull());
|
||||||
|
MOZ_ALWAYS_FALSE(ToObjectSlow(cx, v, false));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
|
BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
|
||||||
{
|
{
|
||||||
|
@ -738,6 +738,8 @@ bool ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber);
|
|||||||
bool BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame);
|
bool BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame);
|
||||||
bool ThrowBadDerivedReturn(JSContext* cx, HandleValue v);
|
bool ThrowBadDerivedReturn(JSContext* cx, HandleValue v);
|
||||||
|
|
||||||
|
bool ThrowObjectCoercible(JSContext* cx, HandleValue v);
|
||||||
|
|
||||||
bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
|
bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
|
@ -1276,7 +1276,7 @@ class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LToIdV : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 1>
|
class LToIdV : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LIR_HEADER(ToIdV)
|
LIR_HEADER(ToIdV)
|
||||||
@ -1286,8 +1286,7 @@ class LToIdV : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 1>
|
|||||||
setTemp(0, temp);
|
setTemp(0, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const size_t Object = 0;
|
static const size_t Index = 0;
|
||||||
static const size_t Index = BOX_PIECES;
|
|
||||||
|
|
||||||
MToId* mir() const {
|
MToId* mir() const {
|
||||||
return mir_->toToId();
|
return mir_->toToId();
|
||||||
@ -7397,6 +7396,14 @@ class LCheckReturn : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0
|
|||||||
LIR_HEADER(CheckReturn)
|
LIR_HEADER(CheckReturn)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LCheckObjCoercible : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const size_t CheckValue = 0;
|
||||||
|
|
||||||
|
LIR_HEADER(CheckObjCoercible)
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
@ -367,6 +367,7 @@
|
|||||||
_(Debugger) \
|
_(Debugger) \
|
||||||
_(NewTarget) \
|
_(NewTarget) \
|
||||||
_(ArrowNewTarget) \
|
_(ArrowNewTarget) \
|
||||||
_(CheckReturn)
|
_(CheckReturn) \
|
||||||
|
_(CheckObjCoercible)
|
||||||
|
|
||||||
#endif /* jit_shared_LOpcodes_shared_h */
|
#endif /* jit_shared_LOpcodes_shared_h */
|
||||||
|
@ -105,7 +105,6 @@ MSG_DEF(JSMSG_INVALID_ARG_TYPE, 3, JSEXN_TYPEERR, "Invalid type: {0} can'
|
|||||||
MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
|
MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
|
||||||
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
|
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
|
||||||
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
|
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
|
||||||
MSG_DEF(JSMSG_DISABLED_DERIVED_CLASS, 1, JSEXN_INTERNALERR, "{0} temporarily disallowed in derived class constructors")
|
|
||||||
MSG_DEF(JSMSG_UNINITIALIZED_THIS, 1, JSEXN_REFERENCEERR, "|this| used uninitialized in {0} class constructor")
|
MSG_DEF(JSMSG_UNINITIALIZED_THIS, 1, JSEXN_REFERENCEERR, "|this| used uninitialized in {0} class constructor")
|
||||||
MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}")
|
MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}")
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/unused.h"
|
|
||||||
|
|
||||||
#include <algorithm> // for std::max
|
#include <algorithm> // for std::max
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -802,10 +801,15 @@ GenerateSeed(uint64_t* seedBuffer, size_t length)
|
|||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
ssize_t size = length * sizeof(seedBuffer[0]);
|
ssize_t size = length * sizeof(seedBuffer[0]);
|
||||||
ssize_t nread = read(fd, (char *) seedBuffer, size);
|
ssize_t nread = read(fd, (char *) seedBuffer, size);
|
||||||
MOZ_ASSERT(nread == size, "Can't read /dev/urandom?!");
|
|
||||||
mozilla::Unused << nread;
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
MOZ_ASSERT(nread == size, "Can't read /dev/urandom?!");
|
||||||
|
if (nread == size)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use PRMJ_Now() if we couldn't read from /dev/urandom.
|
||||||
|
for (size_t i = 0; i < length; i++)
|
||||||
|
seedBuffer[i] = PRMJ_Now();
|
||||||
#else
|
#else
|
||||||
# error "Platform needs to implement random_generateSeed()"
|
# error "Platform needs to implement random_generateSeed()"
|
||||||
#endif
|
#endif
|
||||||
|
@ -2231,11 +2231,12 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject s
|
|||||||
|
|
||||||
// See note above RuntimeLexicalErrorObject.
|
// See note above RuntimeLexicalErrorObject.
|
||||||
if (pobj == scope) {
|
if (pobj == scope) {
|
||||||
if (IsUninitializedLexicalSlot(scope, shape)) {
|
if (name != cx->names().dotThis && IsUninitializedLexicalSlot(scope, shape)) {
|
||||||
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_UNINITIALIZED_LEXICAL);
|
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_UNINITIALIZED_LEXICAL);
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return false;
|
return false;
|
||||||
} else if (scope->is<ScopeObject>() && !scope->is<DeclEnvObject>() && !shape->writable()) {
|
} else if (scope->is<ScopeObject>() && !scope->is<DeclEnvObject>() && !shape->writable()) {
|
||||||
|
MOZ_ASSERT(name != cx->names().dotThis);
|
||||||
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_BAD_CONST_ASSIGN);
|
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_BAD_CONST_ASSIGN);
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return false;
|
return false;
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
// Make sure it doesn't matter when we make the arrow function
|
||||||
|
var test = `
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
let arrow = () => this;
|
||||||
|
assertThrowsInstanceOf(arrow, ReferenceError);
|
||||||
|
super();
|
||||||
|
assertEq(arrow(), this);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,18 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
let a1 = () => this;
|
||||||
|
let a2 = (() => super());
|
||||||
|
assertThrowsInstanceOf(a1, ReferenceError);
|
||||||
|
assertEq(a2(), a1());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,20 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
let arrow;
|
||||||
|
|
||||||
|
class foo extends class { } {
|
||||||
|
constructor() {
|
||||||
|
arrow = () => this;
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEq(new foo(), arrow());
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,45 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
let superArrow;
|
||||||
|
let thisArrow;
|
||||||
|
|
||||||
|
let thisStash;
|
||||||
|
|
||||||
|
class base {
|
||||||
|
constructor() {
|
||||||
|
// We run this constructor twice as part of the double init check
|
||||||
|
if (!thisStash)
|
||||||
|
thisStash = {prop:45};
|
||||||
|
return thisStash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class foo extends base {
|
||||||
|
constructor() {
|
||||||
|
superArrow = (()=>super());
|
||||||
|
thisArrow = ()=>this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the arrow function saves. Since we never invoke super(), we throw
|
||||||
|
assertThrowsInstanceOf(()=>new foo(), ReferenceError);
|
||||||
|
|
||||||
|
// No |this| binding in the closure, yet
|
||||||
|
assertThrowsInstanceOf(thisArrow, ReferenceError);
|
||||||
|
|
||||||
|
// call super()
|
||||||
|
superArrow();
|
||||||
|
|
||||||
|
// Can't call it twice
|
||||||
|
assertThrowsInstanceOf(superArrow, ReferenceError);
|
||||||
|
|
||||||
|
// Oh look, |this| is populated, now.
|
||||||
|
assertEq(thisArrow(), thisStash);
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,17 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,41 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
(()=>eval("super()"))();
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
(()=>(()=>super())())();
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
eval("(()=>super())()");
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
eval("eval('super()')");
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,25 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
assertEq(eval("super(); this"), this);
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
new class extends class { } {
|
||||||
|
constructor() {
|
||||||
|
(()=>super())();
|
||||||
|
assertEq(this, eval("this"));
|
||||||
|
assertEq(this, (()=>this)());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -1,38 +0,0 @@
|
|||||||
// |reftest| skip-if(!xulRuntime.shell)
|
|
||||||
|
|
||||||
var test = `
|
|
||||||
|
|
||||||
class base {
|
|
||||||
constructor() {
|
|
||||||
eval('');
|
|
||||||
(()=>0)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class derived extends base {
|
|
||||||
constructor() {
|
|
||||||
eval('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure eval and arrows are still valid in non-derived constructors.
|
|
||||||
new base();
|
|
||||||
|
|
||||||
|
|
||||||
// Eval throws in derived class constructors, in both class expressions and
|
|
||||||
// statements.
|
|
||||||
assertThrowsInstanceOf((() => new derived()), InternalError);
|
|
||||||
assertThrowsInstanceOf((() => new class extends base { constructor() { eval('') } }()), InternalError);
|
|
||||||
|
|
||||||
var g = newGlobal();
|
|
||||||
var dbg = Debugger(g);
|
|
||||||
dbg.onDebuggerStatement = function(frame) { assertThrowsInstanceOf(()=>frame.eval(''), InternalError); };
|
|
||||||
|
|
||||||
g.eval("new class foo extends null { constructor() { debugger; return {}; } }()");
|
|
||||||
`;
|
|
||||||
|
|
||||||
if (classesEnabled())
|
|
||||||
eval(test);
|
|
||||||
|
|
||||||
if (typeof reportCompare === 'function')
|
|
||||||
reportCompare(0,0,"OK");
|
|
31
js/src/tests/ecma_6/Class/superPropIncDecElem.js
Normal file
31
js/src/tests/ecma_6/Class/superPropIncDecElem.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
var test = `
|
||||||
|
|
||||||
|
// #1
|
||||||
|
function base() { }
|
||||||
|
|
||||||
|
base.prototype = {
|
||||||
|
test() {
|
||||||
|
--super[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var d = new base();
|
||||||
|
d.test();
|
||||||
|
|
||||||
|
// #2
|
||||||
|
class test2 {
|
||||||
|
test() {
|
||||||
|
super[1]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var d = new test2();
|
||||||
|
d.test()
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (classesEnabled())
|
||||||
|
eval(test);
|
||||||
|
|
||||||
|
if (typeof reportCompare === 'function')
|
||||||
|
reportCompare(0,0,"OK");
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
function f() { return "inner"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function f() { return "outer"; }
|
||||||
|
|
||||||
|
reportCompare(f(), "inner");
|
@ -132,9 +132,6 @@ function testClasses() {
|
|||||||
assertClass("class NAME { }", []);
|
assertClass("class NAME { }", []);
|
||||||
assertClass("class NAME extends null { }", [], lit(null));
|
assertClass("class NAME extends null { }", [], lit(null));
|
||||||
|
|
||||||
// For now, disallow arrow functions in derived class constructors
|
|
||||||
assertClassError("class NAME extends null { constructor() { (() => 0); }", InternalError);
|
|
||||||
|
|
||||||
// Derived class constructor must have curly brackets
|
// Derived class constructor must have curly brackets
|
||||||
assertClassError("class NAME extends null { constructor() 1 }", SyntaxError);
|
assertClassError("class NAME extends null { constructor() 1 }", SyntaxError);
|
||||||
|
|
||||||
|
@ -4373,8 +4373,8 @@ Debugger::setupTraceLogger(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
if (!GetProperty(cx, obj, obj, ids[i], &v))
|
if (!GetProperty(cx, obj, obj, ids[i], &v))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
textIds.append(textId);
|
textIds.infallibleAppend(textId);
|
||||||
values.append(ToBoolean(v));
|
values.infallibleAppend(ToBoolean(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(ids.length() == textIds.length());
|
MOZ_ASSERT(ids.length() == textIds.length());
|
||||||
@ -6724,13 +6724,6 @@ DebuggerGenericEval(JSContext* cx, const char* fullMethodName, const Value& code
|
|||||||
MOZ_ASSERT_IF(iter, !scope);
|
MOZ_ASSERT_IF(iter, !scope);
|
||||||
MOZ_ASSERT_IF(!iter, scope && IsGlobalLexicalScope(scope));
|
MOZ_ASSERT_IF(!iter, scope && IsGlobalLexicalScope(scope));
|
||||||
|
|
||||||
if (iter && iter->script()->isDerivedClassConstructor()) {
|
|
||||||
MOZ_ASSERT(iter->isFunctionFrame() && iter->calleeTemplate()->isClassConstructor());
|
|
||||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DISABLED_DERIVED_CLASS,
|
|
||||||
"debugger eval");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the first argument, the eval code string. */
|
/* Check the first argument, the eval code string. */
|
||||||
if (!code.isString()) {
|
if (!code.isString()) {
|
||||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
|
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
|
||||||
|
@ -427,7 +427,9 @@ js::EnqueuePendingParseTasksAfterGC(JSRuntime* rt)
|
|||||||
for (size_t i = 0; i < waiting.length(); i++) {
|
for (size_t i = 0; i < waiting.length(); i++) {
|
||||||
ParseTask* task = waiting[i];
|
ParseTask* task = waiting[i];
|
||||||
if (task->runtimeMatches(rt)) {
|
if (task->runtimeMatches(rt)) {
|
||||||
newTasks.append(task);
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!newTasks.append(task))
|
||||||
|
oomUnsafe.crash("EnqueuePendingParseTasksAfterGC");
|
||||||
HelperThreadState().remove(waiting, &i);
|
HelperThreadState().remove(waiting, &i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,8 +446,11 @@ js::EnqueuePendingParseTasksAfterGC(JSRuntime* rt)
|
|||||||
|
|
||||||
AutoLockHelperThreadState lock;
|
AutoLockHelperThreadState lock;
|
||||||
|
|
||||||
for (size_t i = 0; i < newTasks.length(); i++)
|
{
|
||||||
HelperThreadState().parseWorklist().append(newTasks[i]);
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!HelperThreadState().parseWorklist().appendAll(newTasks))
|
||||||
|
oomUnsafe.crash("EnqueuePendingParseTasksAfterGC");
|
||||||
|
}
|
||||||
|
|
||||||
HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
|
HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,10 @@ FetchName(JSContext* cx, HandleObject obj, HandleObject obj2, HandlePropertyName
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do our own explicit checking for |this|
|
||||||
|
if (name == cx->names().dotThis)
|
||||||
|
return true;
|
||||||
|
|
||||||
// NAME operations are the slow paths already, so unconditionally check
|
// NAME operations are the slow paths already, so unconditionally check
|
||||||
// for uninitialized lets.
|
// for uninitialized lets.
|
||||||
return CheckUninitializedLexical(cx, name, vp);
|
return CheckUninitializedLexical(cx, name, vp);
|
||||||
@ -391,18 +395,14 @@ NegOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue val
|
|||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE bool
|
static MOZ_ALWAYS_INLINE bool
|
||||||
ToIdOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue objval,
|
ToIdOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue idval,
|
||||||
HandleValue idval, MutableHandleValue res)
|
MutableHandleValue res)
|
||||||
{
|
{
|
||||||
if (idval.isInt32()) {
|
if (idval.isInt32()) {
|
||||||
res.set(idval);
|
res.set(idval);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* obj = ToObjectFromStack(cx, objval);
|
|
||||||
if (!obj)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
if (!ToPropertyKey(cx, idval, &id))
|
if (!ToPropertyKey(cx, idval, &id))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1740,7 +1740,6 @@ CASE(JSOP_NOP)
|
|||||||
CASE(JSOP_UNUSED14)
|
CASE(JSOP_UNUSED14)
|
||||||
CASE(JSOP_UNUSED65)
|
CASE(JSOP_UNUSED65)
|
||||||
CASE(JSOP_BACKPATCH)
|
CASE(JSOP_BACKPATCH)
|
||||||
CASE(JSOP_UNUSED163)
|
|
||||||
CASE(JSOP_UNUSED177)
|
CASE(JSOP_UNUSED177)
|
||||||
CASE(JSOP_UNUSED178)
|
CASE(JSOP_UNUSED178)
|
||||||
CASE(JSOP_UNUSED179)
|
CASE(JSOP_UNUSED179)
|
||||||
@ -2422,10 +2421,9 @@ CASE(JSOP_TOID)
|
|||||||
* but we need to avoid the observable stringification the second time.
|
* but we need to avoid the observable stringification the second time.
|
||||||
* There must be an object value below the id, which will not be popped.
|
* There must be an object value below the id, which will not be popped.
|
||||||
*/
|
*/
|
||||||
ReservedRooted<Value> objval(&rootValue0, REGS.sp[-2]);
|
|
||||||
ReservedRooted<Value> idval(&rootValue1, REGS.sp[-1]);
|
ReservedRooted<Value> idval(&rootValue1, REGS.sp[-1]);
|
||||||
MutableHandleValue res = REGS.stackHandleAt(-1);
|
MutableHandleValue res = REGS.stackHandleAt(-1);
|
||||||
if (!ToIdOperation(cx, script, REGS.pc, objval, idval, res))
|
if (!ToIdOperation(cx, script, REGS.pc, idval, res))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
END_CASE(JSOP_TOID)
|
END_CASE(JSOP_TOID)
|
||||||
@ -3232,10 +3230,7 @@ CASE(JSOP_SETLOCAL)
|
|||||||
{
|
{
|
||||||
uint32_t i = GET_LOCALNO(REGS.pc);
|
uint32_t i = GET_LOCALNO(REGS.pc);
|
||||||
|
|
||||||
// Derived class constructors store the TDZ Value in the .this slot
|
MOZ_ASSERT(!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));
|
||||||
// before a super() call.
|
|
||||||
MOZ_ASSERT_IF(!script->isDerivedClassConstructor(),
|
|
||||||
!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));
|
|
||||||
|
|
||||||
REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
|
REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
|
||||||
}
|
}
|
||||||
@ -3893,6 +3888,14 @@ CASE(JSOP_CLASSCONSTRUCTOR)
|
|||||||
}
|
}
|
||||||
END_CASE(JSOP_CLASSCONSTRUCTOR)
|
END_CASE(JSOP_CLASSCONSTRUCTOR)
|
||||||
|
|
||||||
|
CASE(JSOP_CHECKOBJCOERCIBLE)
|
||||||
|
{
|
||||||
|
ReservedRooted<Value> checkVal(&rootValue0, REGS.sp[-1]);
|
||||||
|
if (checkVal.isNullOrUndefined() && !ToObjectFromStack(cx, checkVal))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
END_CASE(JSOP_CHECKOBJCOERCIBLE)
|
||||||
|
|
||||||
DEFAULT()
|
DEFAULT()
|
||||||
{
|
{
|
||||||
char numBuf[12];
|
char numBuf[12];
|
||||||
@ -4837,9 +4840,6 @@ js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame)
|
|||||||
{
|
{
|
||||||
RootedFunction fun(cx, frame.callee());
|
RootedFunction fun(cx, frame.callee());
|
||||||
|
|
||||||
MOZ_ASSERT(fun->isClassConstructor());
|
|
||||||
MOZ_ASSERT(fun->nonLazyScript()->isDerivedClassConstructor());
|
|
||||||
|
|
||||||
const char* name = "anonymous";
|
const char* name = "anonymous";
|
||||||
JSAutoByteString str;
|
JSAutoByteString str;
|
||||||
if (fun->atom()) {
|
if (fun->atom()) {
|
||||||
|
@ -1668,7 +1668,14 @@
|
|||||||
* Stack: =>
|
* Stack: =>
|
||||||
*/ \
|
*/ \
|
||||||
macro(JSOP_DEFLET, 162,"deflet", NULL, 5, 0, 0, JOF_ATOM) \
|
macro(JSOP_DEFLET, 162,"deflet", NULL, 5, 0, 0, JOF_ATOM) \
|
||||||
macro(JSOP_UNUSED163, 163,"unused163", NULL, 1, 0, 1, JOF_BYTE) \
|
/*
|
||||||
|
* Throw if the value on the stack is not coerscible to an object (is |null| or |undefined|).
|
||||||
|
* Category: Literals
|
||||||
|
* Type: Object
|
||||||
|
* Operands:
|
||||||
|
* Stack: val => val
|
||||||
|
*/ \
|
||||||
|
macro(JSOP_CHECKOBJCOERCIBLE, 163, "checkobjcoercible", NULL, 1, 1, 1, JOF_BYTE) \
|
||||||
/*
|
/*
|
||||||
* Find the function to invoke with |super()| on the scope chain.
|
* Find the function to invoke with |super()| on the scope chain.
|
||||||
*
|
*
|
||||||
@ -2122,15 +2129,12 @@
|
|||||||
macro(JSOP_REST, 224, "rest", NULL, 1, 0, 1, JOF_BYTE|JOF_TYPESET) \
|
macro(JSOP_REST, 224, "rest", NULL, 1, 0, 1, JOF_BYTE|JOF_TYPESET) \
|
||||||
\
|
\
|
||||||
/*
|
/*
|
||||||
* First, throw a TypeError if baseValue is null or undefined. Then,
|
* Replace the top-of-stack value propertyNameValue with
|
||||||
* replace the top-of-stack value propertyNameValue with
|
* ToPropertyKey(propertyNameValue).
|
||||||
* ToPropertyKey(propertyNameValue). This opcode implements ES6 12.3.2.1
|
|
||||||
* steps 7-10. It is also used to implement computed property names; in
|
|
||||||
* that case, baseValue is always an object, so the first step is a no-op.
|
|
||||||
* Category: Literals
|
* Category: Literals
|
||||||
* Type: Object
|
* Type: Object
|
||||||
* Operands:
|
* Operands:
|
||||||
* Stack: baseValue, propertyNameValue => baseValue, propertyKey
|
* Stack: propertyNameValue => propertyKey
|
||||||
*/ \
|
*/ \
|
||||||
macro(JSOP_TOID, 225, "toid", NULL, 1, 1, 1, JOF_BYTE) \
|
macro(JSOP_TOID, 225, "toid", NULL, 1, 1, 1, JOF_BYTE) \
|
||||||
\
|
\
|
||||||
|
@ -306,8 +306,10 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
|||||||
if (!atomsCompartment || !atomsCompartment->init(nullptr))
|
if (!atomsCompartment || !atomsCompartment->init(nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
gc.zones.append(atomsZone.get());
|
if (!gc.zones.append(atomsZone.get()))
|
||||||
atomsZone->compartments.append(atomsCompartment.get());
|
return false;
|
||||||
|
if (!atomsZone->compartments.append(atomsCompartment.get()))
|
||||||
|
return false;
|
||||||
|
|
||||||
atomsCompartment->setIsSystem(true);
|
atomsCompartment->setIsSystem(true);
|
||||||
|
|
||||||
|
@ -953,7 +953,7 @@ class ClonedBlockObject : public BlockObject
|
|||||||
// Attempting to access anything on this scope throws the appropriate
|
// Attempting to access anything on this scope throws the appropriate
|
||||||
// ReferenceError.
|
// ReferenceError.
|
||||||
//
|
//
|
||||||
// ES6 'const' bindings induce a runtime assignment when assigned to outside
|
// ES6 'const' bindings induce a runtime error when assigned to outside
|
||||||
// of initialization, regardless of strictness.
|
// of initialization, regardless of strictness.
|
||||||
class RuntimeLexicalErrorObject : public ScopeObject
|
class RuntimeLexicalErrorObject : public ScopeObject
|
||||||
{
|
{
|
||||||
|
@ -3875,7 +3875,11 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
|
|||||||
RootedFunction function(cx, this->function());
|
RootedFunction function(cx, this->function());
|
||||||
Vector<uint32_t, 32> pcOffsets(cx);
|
Vector<uint32_t, 32> pcOffsets(cx);
|
||||||
for (ScriptFrameIter iter(cx); !iter.done(); ++iter) {
|
for (ScriptFrameIter iter(cx); !iter.done(); ++iter) {
|
||||||
pcOffsets.append(iter.script()->pcToOffset(iter.pc()));
|
{
|
||||||
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
if (!pcOffsets.append(iter.script()->pcToOffset(iter.pc())))
|
||||||
|
oomUnsafe.crash("rollbackPartiallyInitializedObjects");
|
||||||
|
}
|
||||||
|
|
||||||
if (!iter.isConstructing() || !iter.matchCallee(cx, function))
|
if (!iter.isConstructing() || !iter.matchCallee(cx, function))
|
||||||
continue;
|
continue;
|
||||||
|
@ -29,11 +29,11 @@ namespace js {
|
|||||||
*
|
*
|
||||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||||
*/
|
*/
|
||||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 327;
|
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 329;
|
||||||
static const uint32_t XDR_BYTECODE_VERSION =
|
static const uint32_t XDR_BYTECODE_VERSION =
|
||||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||||
|
|
||||||
static_assert(JSErr_Limit == 425,
|
static_assert(JSErr_Limit == 424,
|
||||||
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
|
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
|
||||||
"removed MSG_DEFs from js.msg, you should increment "
|
"removed MSG_DEFs from js.msg, you should increment "
|
||||||
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
|
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
|
||||||
|
@ -4575,13 +4575,9 @@ nsDisplayResolution::HitTest(nsDisplayListBuilder* aBuilder,
|
|||||||
HitTestState* aState,
|
HitTestState* aState,
|
||||||
nsTArray<nsIFrame*> *aOutFrames)
|
nsTArray<nsIFrame*> *aOutFrames)
|
||||||
{
|
{
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
nsIPresShell* presShell = mFrame->PresContext()->PresShell();
|
nsIPresShell* presShell = mFrame->PresContext()->PresShell();
|
||||||
nsRect rect = aRect.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
|
nsRect rect = aRect.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
|
||||||
mList.HitTest(aBuilder, rect, aState, aOutFrames);
|
mList.HitTest(aBuilder, rect, aState, aOutFrames);
|
||||||
#else
|
|
||||||
mList.HitTest(aBuilder, aRect, aState, aOutFrames);
|
|
||||||
#endif // MOZ_SINGLE_PROCESS_APZ
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Layer>
|
already_AddRefed<Layer>
|
||||||
|
@ -1416,7 +1416,12 @@ public:
|
|||||||
virtual nsresult SetResolution(float aResolution) = 0;
|
virtual nsresult SetResolution(float aResolution) = 0;
|
||||||
float GetResolution() { return mResolution.valueOr(1.0); }
|
float GetResolution() { return mResolution.valueOr(1.0); }
|
||||||
virtual float GetCumulativeResolution() = 0;
|
virtual float GetCumulativeResolution() = 0;
|
||||||
virtual float GetCumulativeScaleResolution() = 0;
|
|
||||||
|
/**
|
||||||
|
* Calculate the cumulative scale resolution from this document up to
|
||||||
|
* but not including the root document.
|
||||||
|
*/
|
||||||
|
virtual float GetCumulativeNonRootScaleResolution() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Was the current resolution set by the user or just default initialized?
|
* Was the current resolution set by the user or just default initialized?
|
||||||
|
@ -2021,9 +2021,7 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
|
|||||||
nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
|
nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
|
||||||
presContext->DevPixelsToAppUnits(aPoint.y));
|
presContext->DevPixelsToAppUnits(aPoint.y));
|
||||||
pt = pt - view->ViewToWidgetOffset();
|
pt = pt - view->ViewToWidgetOffset();
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeNonRootScaleResolution());
|
||||||
pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeScaleResolution());
|
|
||||||
#endif // MOZ_SINGLE_PROCESS_APZ
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2059,12 +2057,10 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
|
|||||||
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
int32_t localAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
|
int32_t localAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
widgetToView = widgetToView.ScaleToOtherAppUnits(rootAPD, localAPD);
|
widgetToView = widgetToView.ScaleToOtherAppUnits(rootAPD, localAPD);
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
nsIPresShell* shell = aFrame->PresContext()->PresShell();
|
nsIPresShell* shell = aFrame->PresContext()->PresShell();
|
||||||
|
|
||||||
// XXX Bug 1224748 - Update nsLayoutUtils functions to correctly handle nsPresShell resolution
|
// XXX Bug 1224748 - Update nsLayoutUtils functions to correctly handle nsPresShell resolution
|
||||||
widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeScaleResolution());
|
widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeNonRootScaleResolution());
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we encountered a transform, we can't do simple arithmetic to figure
|
/* If we encountered a transform, we can't do simple arithmetic to figure
|
||||||
* out how to convert back to aFrame's coordinates and must use the CTM.
|
* out how to convert back to aFrame's coordinates and must use the CTM.
|
||||||
@ -2812,10 +2808,8 @@ nsLayoutUtils::TranslateViewToWidget(nsPresContext* aPresContext,
|
|||||||
return LayoutDeviceIntPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
return LayoutDeviceIntPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPoint pt = aPt + viewOffset;
|
nsPoint pt = (aPt +
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
viewOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution());
|
||||||
pt = pt.ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
|
|
||||||
#endif // MOZ_SINGLE_PROCESS_APZ
|
|
||||||
LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(pt.x),
|
LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(pt.x),
|
||||||
aPresContext->AppUnitsToDevPixels(pt.y));
|
aPresContext->AppUnitsToDevPixels(pt.y));
|
||||||
return relativeToViewWidget + WidgetToWidgetOffset(viewWidget, aWidget);
|
return relativeToViewWidget + WidgetToWidgetOffset(viewWidget, aWidget);
|
||||||
|
@ -5330,13 +5330,16 @@ float PresShell::GetCumulativeResolution()
|
|||||||
return resolution;
|
return resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
float PresShell::GetCumulativeScaleResolution()
|
float PresShell::GetCumulativeNonRootScaleResolution()
|
||||||
{
|
{
|
||||||
float resolution = 1.0;
|
float resolution = 1.0;
|
||||||
nsIPresShell* currentShell = this;
|
nsIPresShell* currentShell = this;
|
||||||
while (currentShell) {
|
while (currentShell) {
|
||||||
resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f;
|
nsPresContext* currentCtx = currentShell->GetPresContext();
|
||||||
nsPresContext* parentCtx = currentShell->GetPresContext()->GetParentPresContext();
|
if (currentCtx != currentCtx->GetRootPresContext()) {
|
||||||
|
resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f;
|
||||||
|
}
|
||||||
|
nsPresContext* parentCtx = currentCtx->GetParentPresContext();
|
||||||
if (parentCtx) {
|
if (parentCtx) {
|
||||||
currentShell = parentCtx->PresShell();
|
currentShell = parentCtx->PresShell();
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,7 +218,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual bool ScaleToResolution() const override;
|
virtual bool ScaleToResolution() const override;
|
||||||
virtual float GetCumulativeResolution() override;
|
virtual float GetCumulativeResolution() override;
|
||||||
virtual float GetCumulativeScaleResolution() override;
|
virtual float GetCumulativeNonRootScaleResolution() override;
|
||||||
|
|
||||||
//nsIViewObserver interface
|
//nsIViewObserver interface
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ support-files =
|
|||||||
file_bug1018265.xul
|
file_bug1018265.xul
|
||||||
|
|
||||||
[test_bug370436.html]
|
[test_bug370436.html]
|
||||||
|
skip-if = buildapp == 'b2g'
|
||||||
[test_bug396367-1.html]
|
[test_bug396367-1.html]
|
||||||
[test_bug396367-2.html]
|
[test_bug396367-2.html]
|
||||||
[test_bug420499.xul]
|
[test_bug420499.xul]
|
||||||
|
@ -442,12 +442,10 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
aBuilder->EnterPresShell(subdocRootFrame,
|
aBuilder->EnterPresShell(subdocRootFrame,
|
||||||
pointerEventsNone && !passPointerEventsToChildren);
|
pointerEventsNone && !passPointerEventsToChildren);
|
||||||
|
|
||||||
#if defined(MOZ_SINGLE_PROCESS_APZ)
|
|
||||||
if (!haveDisplayPort) {
|
if (!haveDisplayPort) {
|
||||||
// Remove nsPresShell resolution
|
// Remove nsPresShell resolution
|
||||||
dirty = dirty.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
|
dirty = dirty.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
dirty = aDirtyRect;
|
dirty = aDirtyRect;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user