merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-12-11 11:38:17 +01:00
Родитель 25349c8a3e 45242f7699
Коммит b25476080d
137 изменённых файлов: 1696 добавлений и 752 удалений

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

@ -1007,16 +1007,8 @@ pref("security.exthelperapp.disable_background_handling", true);
// Inactivity time in milliseconds after which we shut down the OS.File worker.
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
pref("apz.axis_lock.mode", 2); // Use "sticky" axis locking
pref("apz.fling_curve_function_x1", "0.41");
pref("apz.fling_curve_function_y1", "0.0");
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_friction", "0.0019");
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.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
pref("layout.event-regions.enabled", true);

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

@ -29,17 +29,12 @@ function serializeServiceWorkerInfo(aServiceWorkerInfo) {
let result = {};
Object.keys(aServiceWorkerInfo).forEach(property => {
if (typeof aServiceWorkerInfo[property] == "function") {
return;
}
if (property === "principal") {
result.principal = {
origin: aServiceWorkerInfo.principal.originNoSuffix,
originAttributes: aServiceWorkerInfo.principal.originAttributes
};
return;
}
result.principal = {
origin: aServiceWorkerInfo.principal.originNoSuffix,
originAttributes: aServiceWorkerInfo.principal.originAttributes
};
["scope", "scriptSpec"].forEach(property => {
result[property] = aServiceWorkerInfo[property];
});

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

@ -761,7 +761,7 @@
}
// 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.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
}

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

@ -324,7 +324,6 @@ skip-if = buildapp == 'mulet'
[browser_identity_UI.js]
[browser_insecureLoginForms.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_postData.js]
[browser_lastAccessedTab.js]

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

@ -12,6 +12,14 @@ add_task(function* test_keyword_bookmarklet() {
yield promisePageShow();
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;" })
// Enter bookmarklet keyword in the URL bar
@ -21,7 +29,19 @@ add_task(function* test_keyword_bookmarklet() {
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() {

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

@ -4224,7 +4224,6 @@ cairo-uikit)
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
MOZ_USER_DIR="Mozilla"
MOZ_FS_LAYOUT=bundle
AC_DEFINE(MOZ_SINGLE_PROCESS_APZ)
;;
cairo-android)
@ -4798,11 +4797,8 @@ MOZ_ARG_ENABLE_BOOL(android-apz,
MOZ_ANDROID_APZ=1,
MOZ_ANDROID_APZ=)
if test -n "$MOZ_ANDROID_APZ"; then
dnl Do this if defined in confvars.sh
AC_DEFINE(MOZ_ANDROID_APZ)
if test -z "$MOZ_B2GDROID"; then
AC_DEFINE(MOZ_SINGLE_PROCESS_APZ)
fi
dnl Do this if defined in confvars.sh
AC_DEFINE(MOZ_ANDROID_APZ)
fi
dnl ========================================================

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

@ -229,7 +229,7 @@ function installCache(app) {
return;
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 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)) {
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = type;
SlurpFileToString(file, item->data());
nsAutoCString data;
SlurpFileToString(file, data);
item->data() = data;
}
continue;
@ -7669,11 +7671,10 @@ nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
const nsPoint& aOffset,
nsPresContext* aPresContext)
{
nsPoint point = CSSPoint::ToAppUnits(aPoint) + aOffset;
#if defined(MOZ_SINGLE_PROCESS_APZ)
point = point.ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
#endif
return LayoutDeviceIntPoint::FromAppUnitsRounded(point, aPresContext->AppUnitsPerDevPixel());
return LayoutDeviceIntPoint::FromAppUnitsRounded(
(CSSPoint::ToAppUnits(aPoint) +
aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()),
aPresContext->AppUnitsPerDevPixel());
}
nsView*

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

@ -286,11 +286,10 @@ already_AddRefed<nsIScriptTimeoutHandler>
NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
const nsAString& aExpression, ErrorResult& aError)
{
ErrorResult rv;
bool allowEval = false;
RefPtr<nsJSScriptTimeoutHandler> handler =
new nsJSScriptTimeoutHandler(aCx, aWindow, aExpression, &allowEval, rv);
if (rv.Failed() || !allowEval) {
new nsJSScriptTimeoutHandler(aCx, aWindow, aExpression, &allowEval, aError);
if (aError.Failed() || !allowEval) {
return nullptr;
}

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

@ -5,61 +5,66 @@
* loads. The policy we are enforcing is outlined here:
* https://bugzilla.mozilla.org/show_bug.cgi?id=593387#c17
*/
var newBrowser;
function test() {
waitForExplicitFinish();
add_task(function* test() {
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();
gBrowser.selectedTab = newTab;
newBrowser = gBrowser.getBrowserForTab(newTab);
//alert(newBrowser.contentWindow);
// Run next test (try the same with a content top-level context)
yield BrowserTestUtils.loadURI(newBrowser, "http://example.com/");
yield BrowserTestUtils.browserLoaded(newBrowser);
newBrowser.addEventListener("load", testXFOFrameInChrome, true);
newBrowser.contentWindow.location = "chrome://global/content/mozilla.xhtml";
}
function testXFOFrameInChrome() {
newBrowser.removeEventListener("load", testXFOFrameInChrome, true);
yield ContentTask.spawn(newBrowser, null, testXFOFrameInContent);
});
});
function testXFOFrameInChrome(newBrowser) {
// Insert an iframe that specifies "X-Frame-Options: DENY" and verify
// 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");
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.removeEventListener("load", arguments.callee, true);
frame.addEventListener("load", function loaded() {
frame.removeEventListener("load", loaded, true);
// Test that the frame loaded
var test = this.contentDocument.getElementById("test");
is(test.tagName, "H1", "wrong element type");
is(test.textContent, "deny", "wrong textContent");
// Run next test (try the same with a content top-level context)
newBrowser.addEventListener("load", testXFOFrameInContent, true);
newBrowser.contentWindow.location = "http://example.com/";
deferred.resolve();
}, true);
newBrowser.contentDocument.body.appendChild(frame);
return deferred.promise;
}
function testXFOFrameInContent() {
newBrowser.removeEventListener("load", testXFOFrameInContent, true);
function testXFOFrameInContent(newBrowser) {
// 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
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.addEventListener("load", function() {
frame.removeEventListener("load", arguments.callee, true);
frame.addEventListener("load", function loaded() {
frame.removeEventListener("load", loaded, true);
// Test that the frame DID NOT load
var test = this.contentDocument.getElementById("test");
is(test, undefined, "should be about:blank");
is(test, null, "should be about:blank");
// Finalize the test
gBrowser.removeCurrentTab();
finish();
deferred.resolve();
}, true);
newBrowser.contentDocument.body.appendChild(frame);
content.document.body.appendChild(frame);
return deferred.promise;
}

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

@ -2487,14 +2487,24 @@ CanvasRenderingContext2D::UpdateFilter()
// rects
//
// 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.
static void
NormalizeRect(double& aX, double& aY, double& aWidth, double& aHeight)
static bool
ValidateRect(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) {
aWidth = -aWidth;
aX -= aWidth;
@ -2503,13 +2513,16 @@ NormalizeRect(double& aX, double& aY, double& aWidth, double& aHeight)
aHeight = -aHeight;
aY -= aHeight;
}
return true;
}
void
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
double h)
{
NormalizeRect(x, y, w, h);
if(!ValidateRect(x, y, w, h)) {
return;
}
EnsureTarget();
@ -2524,7 +2537,9 @@ CanvasRenderingContext2D::FillRect(double x, double y, double w,
{
const ContextState &state = CurrentState();
NormalizeRect(x, y, w, h);
if(!ValidateRect(x, y, w, h)) {
return;
}
if (state.patternStyles[Style::FILL]) {
CanvasPattern::RepeatMode repeat =
@ -2599,7 +2614,10 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
if (!w && !h) {
return;
}
NormalizeRect(x, y, w, h);
if(!ValidateRect(x, y, w, h)) {
return;
}
EnsureTarget();
if (!IsTargetValid()) {
@ -4375,8 +4393,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
if (optional_argc == 6) {
NormalizeRect(sx, sy, sw, sh);
NormalizeRect(dx, dy, dw, dh);
if (!ValidateRect(sx, sy, sw, sh) ||
!ValidateRect(dx, dy, dw, dh)) {
return;
}
}
RefPtr<SourceSurface> srcSurf;

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

@ -21536,6 +21536,20 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
</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>
function asyncTestsDone() {
@ -24835,7 +24849,13 @@ try {
} catch (e) {
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
try {
test_2d_drawImage_animated_apng();

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

@ -935,11 +935,9 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
nsPoint pt =
LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
#if defined(MOZ_SINGLE_PROCESS_APZ)
if (aPresContext->PresShell()) {
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution());
}
#endif
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());

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

@ -760,15 +760,17 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
if (content)
mCurrentTargetContent = content;
// NOTE: Don't refer TextComposition::IsComposing() since DOM Level 3
// Events defines that KeyboardEvent.isComposing is true when it's
// NOTE: Don't refer TextComposition::IsComposing() since UI Events
// defines that KeyboardEvent.isComposing is true when it's
// dispatched after compositionstart and compositionend.
// TextComposition::IsComposing() is false even before
// 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 =
IMEStateManager::GetTextCompositionFor(keyEvent);
keyEvent->mIsComposing = !!composition;
IMEStateManager::GetTextCompositionFor(aPresContext);
aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
}
break;
case eWheel:

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

@ -1144,11 +1144,21 @@ IMEStateManager::DispatchCompositionEvent(
MOZ_LOG(sISMLog, LogLevel::Info,
("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 } }, "
"aIsSynthesized=%s), tabParent=%p",
aEventTargetNode, aPresContext,
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.mPropagationStopped),
GetBoolName(aIsSynthesized), tabParent.get()));
@ -1164,7 +1174,7 @@ IMEStateManager::DispatchCompositionEvent(
EnsureTextCompositionArray();
RefPtr<TextComposition> composition =
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
sTextCompositions->GetCompositionFor(aCompositionEvent);
if (!composition) {
// If synthesized event comes after delayed native composition events
// for request of commit or cancel, we should ignore it.
@ -1278,8 +1288,18 @@ IMEStateManager::OnCompositionEventDiscarded(
MOZ_LOG(sISMLog, LogLevel::Info,
("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),
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)));
if (!aCompositionEvent->mFlags.mIsTrusted) {
@ -1649,11 +1669,27 @@ IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
// static
already_AddRefed<TextComposition>
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aGUIEvent)
IMEStateManager::GetTextCompositionFor(
const WidgetCompositionEvent* aCompositionEvent)
{
MOZ_ASSERT(aGUIEvent->AsCompositionEvent() || aGUIEvent->AsKeyboardEvent(),
"aGUIEvent has to be WidgetCompositionEvent or WidgetKeyboardEvent");
return GetTextCompositionFor(aGUIEvent->widget);
if (!sTextCompositions) {
return nullptr;
}
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

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

@ -181,11 +181,17 @@ public:
/**
* Returns TextComposition instance for the event.
*
* @param aGUIEvent Should be a composition event which is being dispatched.
*/
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

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

@ -39,8 +39,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
: mPresContext(aPresContext)
, mNode(aNode)
, mTabParent(aTabParent)
, mNativeContext(
aCompositionEvent->widget->GetInputContext().mNativeIMEContext)
, mNativeContext(aCompositionEvent->mNativeIMEContext)
, mCompositionStartOffset(0)
, mCompositionTargetOffset(0)
, mIsSynthesizedForTests(aCompositionEvent->mFlags.mIsSynthesizedForTests)
@ -54,6 +53,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
Preferences::GetBool("dom.compositionevent.allow_control_characters",
false))
{
MOZ_ASSERT(aCompositionEvent->mNativeIMEContext.IsValid());
}
void
@ -66,12 +66,6 @@ TextComposition::Destroy()
// this being destroyed for cleaning up the stuff.
}
bool
TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
{
return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
}
bool
TextComposition::IsValidStateForComposition(nsIWidget* aWidget) const
{
@ -114,6 +108,7 @@ TextComposition::CloneAndDispatchAs(
compositionEvent.time = aCompositionEvent->time;
compositionEvent.timeStamp = aCompositionEvent->timeStamp;
compositionEvent.mData = aCompositionEvent->mData;
compositionEvent.mNativeIMEContext = aCompositionEvent->mNativeIMEContext;
compositionEvent.mOriginalMessage = aCompositionEvent->mMessage;
compositionEvent.mFlags.mIsSynthesizedForTests =
aCompositionEvent->mFlags.mIsSynthesizedForTests;
@ -613,6 +608,7 @@ TextComposition::CompositionEventDispatcher::Run()
switch (mEventMessage) {
case eCompositionStart: {
WidgetCompositionEvent compStart(true, eCompositionStart, widget);
compStart.mNativeIMEContext = mTextComposition->mNativeContext;
WidgetQueryContentEvent selectedText(true, eQuerySelectedText, widget);
ContentEventHandler handler(presContext);
handler.OnQuerySelectedText(&selectedText);
@ -629,6 +625,7 @@ TextComposition::CompositionEventDispatcher::Run()
case eCompositionCommitAsIs:
case eCompositionCommit: {
WidgetCompositionEvent compEvent(true, mEventMessage, widget);
compEvent.mNativeIMEContext = mTextComposition->mNativeContext;
if (mEventMessage != eCompositionCommitAsIs) {
compEvent.mData = mData;
}
@ -650,16 +647,25 @@ TextComposition::CompositionEventDispatcher::Run()
******************************************************************************/
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) {
if (ElementAt(i - 1)->MatchesNativeContext(aWidget)) {
if (ElementAt(i - 1)->GetNativeIMEContext() == aNativeIMEContext) {
return i - 1;
}
}
return NoIndex;
}
TextCompositionArray::index_type
TextCompositionArray::IndexOf(nsIWidget* aWidget)
{
return IndexOf(aWidget->GetNativeIMEContext());
}
TextCompositionArray::index_type
TextCompositionArray::IndexOf(nsPresContext* aPresContext)
{
@ -693,6 +699,27 @@ TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
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*
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
nsINode* aNode)

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

@ -76,7 +76,10 @@ public:
// came from nsDOMWindowUtils.
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.
@ -191,7 +194,7 @@ private:
// mNativeContext stores a opaque pointer. This works as the "ID" for this
// 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.
nsWeakPtr mEditorWeak;
@ -400,11 +403,19 @@ class TextCompositionArray final :
public nsAutoTArray<RefPtr<TextComposition>, 2>
{
public:
// Looking for per native IME context.
index_type IndexOf(const widget::NativeIMEContext& aNativeIMEContext);
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, nsINode* aNode);
TextComposition* GetCompositionFor(nsIWidget* aWidget);
TextComposition* GetCompositionFor(nsPresContext* aPresContext);
TextComposition* GetCompositionFor(nsPresContext* aPresContext,
nsINode* aNode);
TextComposition* GetCompositionInContent(nsPresContext* aPresContext,

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

@ -4980,7 +4980,7 @@ HTMLMediaElement::GetTopLevelPrincipal()
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
{
MOZ_ASSERT(mAudioChannelAgent);
MOZ_ASSERT(mAudioChannelAgent);
if (!OwnerDoc()->GetInnerWindow()) {
return NS_OK;
@ -4995,7 +4995,7 @@ NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
uint64_t id = window->WindowID();
MediaStreamGraph* msg =
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
AudioChannel::Normal);
mAudioChannel);
if (GetSrcMediaStream()) {
mCaptureStreamPort = msg->ConnectToCaptureStream(id, GetSrcMediaStream());

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

@ -235,20 +235,19 @@ parent:
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
* noCompositionEvent true if no composition event is fired by commit or
* cancel
* composition Text to commit before ending the composition
* cancel Set true if composition should be cancelled.
*
* if cancel is true,
* widget should return empty string for composition
* if cancel is false,
* widget should return the current composition text
* isCommitted Returns true if the request causes composition
* being committed synchronously.
* committedString Returns committed string. The may be non-empty
* 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)
returns (bool noCompositionEvent, nsString composition);
prio(urgent) sync RequestIMEToCommitComposition(bool cancel)
returns (bool isCommitted, nsString committedString);
/**
* OnEventNeedingAckHandled() is called after a child process dispatches a
@ -296,8 +295,7 @@ parent:
nsCString[] disabledCommands);
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
int32_t IMEOpen,
intptr_t NativeIMEContext);
int32_t IMEOpen);
prio(urgent) async SetInputContext(int32_t IMEEnabled,
int32_t IMEOpen,

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

@ -2321,16 +2321,19 @@ TabParent::GetRenderFrame()
}
bool
TabParent::RecvEndIMEComposition(const bool& aCancel,
bool* aNoCompositionEvent,
nsString* aComposition)
TabParent::RecvRequestIMEToCommitComposition(const bool& aCancel,
bool* aIsCommitted,
nsString* aCommittedString)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aIsCommitted = false;
return true;
}
*aNoCompositionEvent =
!mContentCache.RequestToCommitComposition(widget, aCancel, *aComposition);
*aIsCommitted =
mContentCache.RequestIMEToCommitComposition(widget, aCancel,
*aCommittedString);
return true;
}
@ -2363,21 +2366,18 @@ TabParent::RecvSetPluginFocused(const bool& aFocused)
bool
TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
int32_t* aIMEOpen,
intptr_t* aNativeIMEContext)
int32_t* aIMEOpen)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aIMEEnabled = IMEState::DISABLED;
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
*aNativeIMEContext = 0;
return true;
}
InputContext context = widget->GetInputContext();
*aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
*aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
*aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext);
return true;
}

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

@ -187,17 +187,16 @@ public:
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
const widget::IMENotification& aEventMessage) override;
virtual bool RecvOnEventNeedingAckHandled(const EventMessage& aMessage) override;
virtual bool RecvEndIMEComposition(const bool& aCancel,
bool* aNoCompositionEvent,
nsString* aComposition) override;
virtual bool RecvRequestIMEToCommitComposition(const bool& aCancel,
bool* aIsCommitted,
nsString* aCommittedString) override;
virtual bool RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
const int32_t& aPanelX,
const int32_t& aPanelY,
nsString* aCommitted) override;
virtual bool RecvSetPluginFocused(const bool& aFocused) override;
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
int32_t* aIMEOpen,
intptr_t* aNativeIMEContext) override;
int32_t* aIMEOpen) override;
virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
const int32_t& aIMEOpen,
const nsString& aType,

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

@ -2112,22 +2112,17 @@ MediaDecoderStateMachine::SeekCompleted()
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
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
// if we need to seek again.
bool isLiveStream = mResource->IsLiveStream();
State nextState;
if (mPendingSeek.Exists()) {
// A new seek target came in while we were processing the old one. No rest
// for the 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) {
// 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
@ -2135,11 +2130,26 @@ MediaDecoderStateMachine::SeekCompleted()
DECODER_LOG("Changed state from SEEKING (to %lld) to COMPLETED", seekTime);
// Explicitly set our state so we don't decode further, and so
// we report playback ended to the media element.
SetState(DECODER_STATE_COMPLETED);
DispatchDecodeTasksIfNeeded();
nextState = DECODER_STATE_COMPLETED;
} else {
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();
} else {
SetState(nextState);
}
// Ensure timestamps are up to date.
@ -2153,7 +2163,6 @@ MediaDecoderStateMachine::SeekCompleted()
// if we need to buffer after the seek.
mQuickBuffering = false;
mCurrentSeek.Resolve(mState == DECODER_STATE_COMPLETED, __func__);
ScheduleStateMachine();
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+
[test_SeekNoData_mp4.html]
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]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_Sequence_mp4.html]

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

@ -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 "nsISeekableStream.h"
#include "gfx2DGlue.h"
#include "mozilla/Telemetry.h"
#include "nsPrintfCString.h"
using namespace mozilla::gfx;
using namespace mozilla::media;
@ -148,6 +150,17 @@ OggReader::~OggReader()
{
ogg_sync_clear(&mOggState);
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() {
@ -704,10 +717,13 @@ bool OggReader::DecodeAudioData()
return true;
}
void OggReader::SetChained(bool aIsChained) {
void OggReader::SetChained() {
{
ReentrantMonitorAutoEnter mon(mMonitor);
mIsChained = aIsChained;
if (mIsChained) {
return;
}
mIsChained = true;
}
mOnMediaNotSeekable.Notify();
}
@ -800,7 +816,7 @@ bool OggReader::ReadOggChain()
}
if (chained) {
SetChained(true);
SetChained();
{
auto t = mDecodedAudioFrames * USECS_PER_S / mInfo.mAudio.mRate;
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.
// It's probably from a new "link" in a "chained" ogg. Don't
// bother even trying to find a duration...
SetChained(true);
SetChained();
endTime = -1;
break;
}
@ -1913,7 +1929,7 @@ media::TimeIntervals OggReader::GetBuffered()
// ogg), return OK to abort the finding any further ranges. This
// prevents us searching through the rest of the media when we
// may not be able to extract timestamps from it.
SetChained(true);
SetChained();
return buffered;
}
}

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

@ -252,7 +252,7 @@ private:
// Set this media as being a chain and notifies the state machine that the
// media is no longer seekable.
void SetChained(bool aIsChained);
void SetChained();
// 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.

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

@ -280,21 +280,23 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason)
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};
params.BackBufferWidth = 1;
params.BackBufferHeight = 1;
params.BackBufferFormat = D3DFMT_UNKNOWN;
params.BackBufferCount = 1;
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
params.hDeviceWindow = ::GetShellWindow();
params.hDeviceWindow = nullptr;
params.Windowed = TRUE;
params.Flags = D3DPRESENTFLAG_VIDEO;
RefPtr<IDirect3DDevice9Ex> device;
hr = d3d9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
::GetShellWindow(),
nullptr,
D3DCREATE_FPU_PRESERVE |
D3DCREATE_MULTITHREADED |
D3DCREATE_MIXED_VERTEXPROCESSING,

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

@ -79,6 +79,11 @@ SpeechTaskCallback::OnPause()
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[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);
return NS_OK;
@ -91,6 +96,11 @@ SpeechTaskCallback::OnResume()
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[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);
return NS_OK;
@ -120,6 +130,9 @@ void
SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
{
mCurrentIndex = aIndex;
if (!mTask) {
return;
}
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
GetTimeDurationFromStart(), mCurrentIndex);
}
@ -127,6 +140,9 @@ SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
void
SpeechTaskCallback::OnError(uint32_t aIndex)
{
if (!mTask) {
return;
}
mTask->DispatchError(GetTimeDurationFromStart(), aIndex);
}

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

@ -76,6 +76,11 @@ SapiCallback::OnPause()
if (FAILED(mSapiClient->Pause())) {
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);
return NS_OK;
}
@ -86,6 +91,11 @@ SapiCallback::OnResume()
if (FAILED(mSapiClient->Resume())) {
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);
return NS_OK;
}

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

@ -125,6 +125,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mIsWhitelistedForShumway(false)
, mWindowType(NPWindowTypeWindow)
, mDrawingModel(kDefaultDrawingModel)
, mLastRecordedDrawingModel(-1)
, mFrameID(0)
#if defined(OS_WIN)
, mPluginHWND(nullptr)
@ -809,6 +810,8 @@ PluginInstanceParent::SetCurrentImage(Image* aImage)
nsAutoTArray<ImageContainer::NonOwningImage,1> imageList;
imageList.AppendElement(holder);
mImageContainer->SetCurrentImages(imageList);
RecordDrawingModel();
}
bool
@ -973,6 +976,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
mFrontSurface.get()));
RecordDrawingModel();
return true;
}
@ -1380,6 +1384,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
return NPERR_GENERIC_ERROR;
}
RecordDrawingModel();
return NPERR_NO_ERROR;
}
@ -2363,3 +2368,28 @@ PluginInstanceParent::Cast(NPP aInstance, PluginAsyncSurrogate** aSurrogate)
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);
// Update Telemetry with the current drawing model.
void RecordDrawingModel();
private:
PluginModuleParent* mParent;
RefPtr<PluginAsyncSurrogate> mSurrogate;
@ -387,6 +390,11 @@ private:
NPWindowType mWindowType;
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;
// 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 onafterscriptexecute;
[Pref="dom.select_events.enabled"]
attribute EventHandler onselectionchange;
/**
* True if this document is synthetic : stand alone image, video, audio file,
* etc.

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

@ -1987,14 +1987,14 @@ nsEditor::StopPreservingSelection()
}
void
nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
nsEditor::EnsureComposition(mozilla::WidgetCompositionEvent* aCompositionEvent)
{
if (mComposition) {
return;
}
// The compositionstart event must cause creating new TextComposition
// instance at being dispatched by IMEStateManager.
mComposition = IMEStateManager::GetTextCompositionFor(aEvent);
mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
if (!mComposition) {
MOZ_CRASH("IMEStateManager doesn't return proper composition");
}

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

@ -413,7 +413,7 @@ protected:
* EnsureComposition() should be called by composition event handlers. This
* 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);

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

@ -2219,7 +2219,7 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance
SetState(PANNING);
}
} else if (mState == PANNING_LOCKED_Y) {
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisLockAngle())) {
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisBreakoutAngle())) {
mX.SetAxisLocked(false);
SetState(PANNING);
}

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

@ -548,11 +548,12 @@ Pan(const RefPtr<InputReceiver>& aTarget,
nsEventStatus (*aOutEventStatuses)[4] = 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
// time when the events are actually processed, rather than when we deliver
// them.
gfxPrefs::SetAPZTouchStartTolerance(1.0f / 1000.0f);
gfxPrefs::SetAPZTouchMoveTolerance(0.0f);
const int OVERCOME_TOUCH_TOLERANCE = 1;
const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50);

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

@ -415,6 +415,28 @@ APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aConte
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
APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
const ScrollableLayerGuid& aGuid)
@ -423,24 +445,21 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
return input;
}
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
if (!content) {
return input;
}
#if !defined(MOZ_SINGLE_PROCESS_APZ)
// First, scale inversely by the root content document's pres shell
// resolution to cancel the scale-to-resolution transform that the
// 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
// compositor-side transforms) because APZ doesn't know about it.
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
if (nsIPresShell* shell = GetRootDocumentPresShell(content)) {
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
// 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
@ -451,22 +470,9 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
// 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
// transform for the layer that the input hit.
void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
if (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;
}
return input;

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

@ -147,7 +147,6 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
}
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
#if defined(MOZ_SINGLE_PROCESS_APZ)
// CalculateRectToZoomTo performs a hit test on the frame associated with the
// Root Content Document. Unfortunately that frame does not know about the
// 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;
point.x = point.x / resolution;
point.y = point.y / resolution;
#endif // MOZ_SINGLE_PROCESS_APZ
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
uint32_t presShellId;

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

@ -9,6 +9,8 @@
#include <string>
#include "base/eintr_wrapper.h"
#include "chrome/common/child_process_info.h"
#include "mozilla/ipc/Transport.h"
@ -41,6 +43,8 @@ CreateTransport(base::ProcessId aProcIdOne,
fd1 = dup(fd1);
fd2 = dup(fd2);
if (fd1 < 0 || fd2 < 0) {
HANDLE_EINTR(close(fd1));
HANDLE_EINTR(close(fd2));
return NS_ERROR_DUPLICATE_HANDLE;
}

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

@ -553,7 +553,6 @@ DynamicallyLinkModule(JSContext* cx, const CallArgs& args, AsmJSModule& module)
return false;
break;
case AsmJSModule::Global::ArrayView:
case AsmJSModule::Global::SharedArrayView:
case AsmJSModule::Global::ArrayViewCtor:
if (!ValidateArrayView(cx, global, globalVal))
return false;

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

@ -100,7 +100,7 @@ class AsmJSModule
class Global
{
public:
enum Which { Variable, FFI, ArrayView, ArrayViewCtor, SharedArrayView, MathBuiltinFunction,
enum Which { Variable, FFI, ArrayView, ArrayViewCtor, MathBuiltinFunction,
AtomicsBuiltinFunction, Constant, SimdCtor, SimdOperation, ByteLength };
enum VarInitKind { InitConstant, InitImport };
enum ConstantKind { GlobalConstant, MathConstant };
@ -189,17 +189,13 @@ class AsmJSModule
// var i32 = new I32(buffer);
// the second import has nothing to validate and thus has a null field.
PropertyName* maybeViewName() const {
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == SharedArrayView || pod.which_ == ArrayViewCtor);
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == ArrayViewCtor);
return name_;
}
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_;
}
void makeViewShared() {
MOZ_ASSERT(pod.which_ == ArrayView);
pod.which_ = SharedArrayView;
}
PropertyName* mathName() const {
MOZ_ASSERT(pod.which_ == MathBuiltinFunction);
return name_;
@ -910,20 +906,18 @@ class AsmJSModule
g.pod.u.ffiIndex_ = *ffiIndex = pod.numFFIs_++;
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(!pod.hasArrayView_ || (pod.isSharedView_ == isSharedView));
pod.hasArrayView_ = true;
pod.isSharedView_ = isSharedView;
pod.isSharedView_ = false;
Global g(Global::ArrayView, maybeField);
g.pod.u.viewType_ = vt;
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(field);
MOZ_ASSERT(!pod.isSharedView_ || isSharedView);
pod.isSharedView_ = isSharedView;
pod.isSharedView_ = false;
Global g(Global::ArrayViewCtor, field);
g.pod.u.viewType_ = vt;
return globals_.append(g);
@ -978,19 +972,9 @@ class AsmJSModule
Global& global(unsigned i) {
return globals_[i];
}
bool isValidViewSharedness(bool shared) const {
if (pod.hasArrayView_)
return pod.isSharedView_ == shared;
return !pod.isSharedView_ || shared;
}
void setViewsAreShared() {
if (pod.hasArrayView_)
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_;
struct {
Scalar::Type viewType_;
bool isSharedView_;
} viewInfo;
AsmJSMathBuiltinFunction mathBuiltinFunc_;
AsmJSAtomicsBuiltinFunction atomicsBuiltinFunc_;
@ -1072,14 +1071,6 @@ class MOZ_STACK_CLASS ModuleValidator
MOZ_ASSERT(isAnyArrayView());
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 {
return which_ == MathBuiltinFunction;
}
@ -1402,18 +1393,16 @@ class MOZ_STACK_CLASS ModuleValidator
global->u.varOrConst.type_ = Type::var(importType).which();
return globals_.putNew(varName, global);
}
bool addArrayView(PropertyName* varName, Scalar::Type vt, PropertyName* maybeField,
bool isSharedView)
bool addArrayView(PropertyName* varName, Scalar::Type vt, PropertyName* maybeField)
{
if (!arrayViews_.append(ArrayView(varName, vt)))
return false;
Global* global = validationLifo_.new_<Global>(Global::ArrayView);
if (!global)
return false;
if (!module().addArrayView(vt, maybeField, isSharedView))
if (!module().addArrayView(vt, maybeField))
return false;
global->u.viewInfo.viewType_ = vt;
global->u.viewInfo.isSharedView_ = isSharedView;
return globals_.putNew(varName, global);
}
bool addMathBuiltinFunction(PropertyName* varName, AsmJSMathBuiltinFunction func,
@ -1497,14 +1486,13 @@ class MOZ_STACK_CLASS ModuleValidator
global->u.changeHeap.srcEnd_ = fn->pn_pos.end;
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);
if (!global)
return false;
if (!module().addArrayViewCtor(vt, fieldName, isSharedView))
if (!module().addArrayViewCtor(vt, fieldName))
return false;
global->u.viewInfo.viewType_ = vt;
global->u.viewInfo.isSharedView_ = isSharedView;
return globals_.putNew(varName, global);
}
bool addFFI(PropertyName* varName, PropertyName* field) {
@ -1612,6 +1600,10 @@ class MOZ_STACK_CLASS ModuleValidator
return module().minHeapLength();
}
bool usesSharedMemory() const {
return atomicsPresent_;
}
// Error handling.
bool hasAlreadyFailed() const {
return !!errorString_;
@ -1740,14 +1732,8 @@ class MOZ_STACK_CLASS ModuleValidator
}
void startFunctionBodies() {
if (atomicsPresent_) {
for (GlobalMap::Range r = globals_.all() ; !r.empty() ; r.popFront()) {
Global* g = r.front().value();
if (g->isAnyArrayView())
g->setViewIsSharedView();
}
if (atomicsPresent_)
module().setViewsAreShared();
}
}
};
@ -2472,10 +2458,9 @@ CheckGlobalVariableInitImport(ModuleValidator& m, PropertyName* varName, ParseNo
}
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();
*shared = false;
if (name == names.Int8Array) {
*type = Scalar::Int8;
} else if (name == names.Uint8Array) {
@ -2526,7 +2511,6 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
PropertyName* field;
Scalar::Type type;
bool shared = false;
if (ctorExpr->isKind(PNK_DOT)) {
ParseNode* base = DotBase(ctorExpr);
@ -2534,7 +2518,7 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
return m.failName(base, "expecting '%s.*Array", globalName);
field = DotMember(ctorExpr);
if (!IsArrayViewCtorName(m, field, &type, &shared))
if (!IsArrayViewCtorName(m, field, &type))
return m.fail(ctorExpr, "could not match typed array name");
} else {
if (!ctorExpr->isKind(PNK_NAME))
@ -2550,16 +2534,12 @@ CheckNewArrayView(ModuleValidator& m, PropertyName* varName, ParseNode* newExpr)
field = nullptr;
type = global->viewType();
shared = global->viewIsSharedView();
}
if (!CheckNewArrayViewArgs(m, ctorExpr, bufferName))
return false;
if (!m.module().isValidViewSharedness(shared))
return m.failName(ctorExpr, "%s has different sharedness than previous view constructors", globalName);
return m.addArrayView(varName, type, field, shared);
return m.addArrayView(varName, type, field);
}
static bool
@ -2695,12 +2675,8 @@ CheckGlobalDotImport(ModuleValidator& m, PropertyName* varName, ParseNode* initN
return m.addByteLength(varName);
Scalar::Type type;
bool shared = false;
if (IsArrayViewCtorName(m, field, &type, &shared)) {
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);
}
if (IsArrayViewCtorName(m, field, &type))
return m.addArrayViewCtor(varName, type, 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();
#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))
return false;

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

@ -104,7 +104,8 @@ class FunctionCompiler
curBlock_->initSlot(info().localSlot(i.index()), ins);
if (!mirGen_.ensureBallast())
return false;
localTypes_.append(args[i.index()]);
if (!localTypes_.append(args[i.index()]))
return false;
}
for (unsigned i = 0; i < func_.numVarInits(); i++) {
@ -134,7 +135,8 @@ class FunctionCompiler
curBlock_->initSlot(info().localSlot(firstVarSlot + i), ins);
if (!mirGen_.ensureBallast())
return false;
localTypes_.append(v.type());
if (!localTypes_.append(v.type()))
return false;
}
return true;
@ -1129,12 +1131,20 @@ class FunctionCompiler
if (!switchBlock)
return true;
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++) {
if (!cases[i])
mir->addCase(defaultIndex);
else
mir->addCase(mir->addSuccessor(cases[i]));
if (!cases[i]) {
if (!mir->addCase(defaultIndex))
return false;
} else {
size_t caseIndex;
if (!mir->addSuccessor(cases[i], &caseIndex))
return false;
if (!mir->addCase(caseIndex))
return false;
}
}
if (curBlock_) {
MBasicBlock* next;

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

@ -238,12 +238,6 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
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.
if (args.length() < 1) {
args.rval().setUndefined();

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

@ -2783,27 +2783,31 @@ BytecodeEmitter::emitNameIncDec(ParseNode* pn)
}
bool
BytecodeEmitter::emitElemOperands(ParseNode* pn, JSOp op)
BytecodeEmitter::emitElemOperands(ParseNode* pn, EmitElemOption opts)
{
MOZ_ASSERT(pn->isArity(PN_BINARY));
if (!emitTree(pn->pn_left))
return false;
if (op == JSOP_CALLELEM && !emit1(JSOP_DUP))
return false;
if (opts == EmitElemOption::IncDec) {
if (!emit1(JSOP_CHECKOBJCOERCIBLE))
return false;
} else if (opts == EmitElemOption::Call) {
if (!emit1(JSOP_DUP))
return false;
}
if (!emitTree(pn->pn_right))
return false;
bool isSetElem = op == JSOP_SETELEM || op == JSOP_STRICTSETELEM;
if (isSetElem && !emit2(JSOP_PICK, 2))
if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 2))
return false;
return true;
}
bool
BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, EmitElemOption opts)
{
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
// it inside both the GETELEM and the SETELEM.
if (opts == SuperElem_IncDec && !emit1(JSOP_TOID))
if (opts == EmitElemOption::IncDec && !emit1(JSOP_TOID))
return false;
if (!emitGetThisForSuperBase(pn->pn_left))
return false;
if (opts == SuperElem_Call) {
if (opts == EmitElemOption::Call) {
if (!emit1(JSOP_SWAP))
return false;
@ -2835,7 +2839,7 @@ BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
if (!emit1(JSOP_SUPERBASE))
return false;
if (opts == SuperElem_Set && !emit2(JSOP_PICK, 3))
if (opts == EmitElemOption::Set && !emit2(JSOP_PICK, 3))
return false;
return true;
@ -2854,17 +2858,23 @@ BytecodeEmitter::emitElemOpBase(JSOp op)
bool
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
BytecodeEmitter::emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall)
{
SuperElemOptions opts = SuperElem_Get;
EmitElemOption opts = EmitElemOption::Get;
if (isCall)
opts = SuperElem_Call;
opts = EmitElemOption::Call;
else if (op == JSOP_SETELEM_SUPER || op == JSOP_STRICTSETELEM_SUPER)
opts = SuperElem_Set;
opts = EmitElemOption::Set;
if (!emitSuperElemOperands(pn, opts))
return false;
@ -2885,10 +2895,10 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn)
bool isSuper = pn->pn_kid->as<PropertyByValue>().isSuper();
if (isSuper) {
if (!emitSuperElemOperands(pn->pn_kid, SuperElem_IncDec))
if (!emitSuperElemOperands(pn->pn_kid, EmitElemOption::IncDec))
return false;
} else {
if (!emitElemOperands(pn->pn_kid, JSOP_GETELEM))
if (!emitElemOperands(pn->pn_kid, EmitElemOption::IncDec))
return false;
}
@ -3465,10 +3475,34 @@ BytecodeEmitter::emitSetThis(ParseNode* pn)
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;
switch (setOp) {
case JSOP_SETLOCAL: getOp = JSOP_GETLOCAL; break;
case JSOP_SETALIASEDVAR: getOp = JSOP_GETALIASEDVAR; break;
case JSOP_SETLOCAL:
getOp = JSOP_GETLOCAL;
setOp = JSOP_INITLEXICAL;
break;
case JSOP_SETALIASEDVAR:
getOp = JSOP_GETALIASEDVAR;
setOp = JSOP_INITALIASEDLEXICAL;
break;
default: MOZ_CRASH("Unexpected op");
}
@ -4379,13 +4413,25 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
* i' to be hoisted out of the loop.
*/
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
* function f(){} precedes the var, detect simple name assignment
* here and initialize the name.
*/
// To allow the front end to rewrite |var f = x;| as |f = x;| when a
// |function f(){}| precedes the var, detect simple name assignment
// 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 (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
return false;

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

@ -519,7 +519,8 @@ struct BytecodeEmitter
// 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
// 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 emitElemOp(ParseNode* pn, JSOp op);
@ -654,8 +655,7 @@ struct BytecodeEmitter
bool emitClass(ParseNode* pn);
bool emitSuperPropLHS(ParseNode* superBase, 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, SuperElemOptions opts = SuperElem_Get);
bool emitSuperElemOperands(ParseNode* pn, EmitElemOption opts = EmitElemOption::Get);
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
};

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

@ -125,8 +125,12 @@ SharedContext::computeAllowSyntax(JSObject* staticScope)
// Any function supports new.target.
allowNewTarget_ = true;
allowSuperProperty_ = it.fun().allowSuperProperty();
if (it.maybeFunctionBox())
if (it.maybeFunctionBox()) {
superScopeAlreadyNeedsHomeObject_ = it.maybeFunctionBox()->needsHomeObject();
allowSuperCall_ = it.maybeFunctionBox()->isDerivedClassConstructor();
} else {
allowSuperCall_ = it.fun().isDerivedClassConstructor();
}
break;
}
}
@ -7470,11 +7474,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
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);
if (!arrowFunc)
return null();
@ -8890,7 +8889,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
tt == TOK_NO_SUBS_TEMPLATE)
{
if (handler.isSuperBase(lhs)) {
if (!pc->sc->isFunctionBox() || !pc->sc->asFunctionBox()->isDerivedClassConstructor()) {
if (!pc->sc->allowSuperCall()) {
report(ParseError, false, null(), JSMSG_BAD_SUPERCALL);
return null();
}

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

@ -202,6 +202,7 @@ class SharedContext
bool allowNewTarget_;
bool allowSuperProperty_;
bool allowSuperCall_;
bool inWith_;
bool needsThisTDZChecks_;
bool superScopeAlreadyNeedsHomeObject_;
@ -217,6 +218,7 @@ class SharedContext
thisBinding_(ThisBinding::Global),
allowNewTarget_(false),
allowSuperProperty_(false),
allowSuperCall_(false),
inWith_(false),
needsThisTDZChecks_(false),
superScopeAlreadyNeedsHomeObject_(false)
@ -244,6 +246,7 @@ class SharedContext
bool allowNewTarget() const { return allowNewTarget_; }
bool allowSuperProperty() const { return allowSuperProperty_; }
bool allowSuperCall() const { return allowSuperCall_; }
bool inWith() const { return inWith_; }
bool needsThisTDZChecks() const { return needsThisTDZChecks_; }

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

@ -877,13 +877,15 @@ TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
ungetChar('*');
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
// exception that we should stop and drop everything for.
return true;
}
size_t length = tokenbuf.length();

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

@ -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()
}
if (!this.SharedArrayBuffer)
quit(0);
for (var i = 0; i < 10; i++) {
x = new SharedArrayBuffer(4)

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

@ -3588,8 +3588,7 @@ BaselineCompiler::emit_JSOP_RETRVAL()
return emitReturn();
}
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, HandleValue,
MutableHandleValue);
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, MutableHandleValue);
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(js::ToIdOperation);
bool
@ -3605,10 +3604,7 @@ BaselineCompiler::emit_JSOP_TOID()
prepareVMCall();
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
pushArg(R0);
pushArg(R1);
pushArg(ImmPtr(pc));
pushArg(ImmGCPtr(script));
@ -3621,6 +3617,32 @@ BaselineCompiler::emit_JSOP_TOID()
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);
static const VMFunction ToStringInfo = FunctionInfo<ToStringFn>(ToStringSlow);

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

@ -219,7 +219,8 @@ namespace jit {
_(JSOP_INITHIDDENPROP_SETTER) \
_(JSOP_INITHIDDENELEM) \
_(JSOP_INITHIDDENELEM_GETTER) \
_(JSOP_INITHIDDENELEM_SETTER)
_(JSOP_INITHIDDENELEM_SETTER) \
_(JSOP_CHECKOBJCOERCIBLE)
class BaselineCompiler : public BaselineCompilerSpecific
{

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

@ -2769,6 +2769,11 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
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.
MOZ_ASSERT(stack[2] == objv);
stack[2] = rhs;

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

@ -9061,7 +9061,7 @@ CodeGenerator::visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool)
masm.jump(ool->rejoin());
}
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, HandleValue,
typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue,
MutableHandleValue);
static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(ToIdOperation);
@ -9076,7 +9076,6 @@ CodeGenerator::visitToIdV(LToIdV* lir)
OutOfLineCode* ool = oolCallVM(ToIdInfo, lir,
ArgList(ImmGCPtr(current->mir()->info().script()),
ImmPtr(lir->mir()->resumePoint()->pc()),
ToValue(lir, LToIdV::Object),
ToValue(lir, LToIdV::Index)),
StoreValueTo(out));
@ -10369,6 +10368,22 @@ CodeGenerator::visitCheckReturn(LCheckReturn* ins)
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
CodeGenerator::visitRandom(LRandom* ins)
{

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

@ -345,6 +345,7 @@ class CodeGenerator : public CodeGeneratorSpecific
void visitNewTarget(LNewTarget* ins);
void visitArrowNewTarget(LArrowNewTarget* ins);
void visitCheckReturn(LCheckReturn* ins);
void visitCheckObjCoercible(LCheckObjCoercible* ins);
void visitCheckOverRecursed(LCheckOverRecursed* lir);
void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);

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

@ -354,9 +354,10 @@ class ExecutableAllocator
// At this point, local |pool| is the owner.
if (m_smallPools.length() < maxSmallPools) {
// We haven't hit the maximum number of live pools; add the new pool.
m_smallPools.append(pool);
pool->addRef();
// We haven't hit the maximum number of live pools; add the new pool.
// If append() OOMs, we just return an unshared allocator.
if (m_smallPools.append(pool))
pool->addRef();
} else {
// Find the pool with the least space.
int iMin = 0;

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

@ -134,7 +134,9 @@ class LinearSum
: terms_(other.terms_.allocPolicy()),
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

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

@ -615,7 +615,8 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
return true;
}
}
loopHeaders_.append(LoopHeader(start, entry));
if (!loopHeaders_.append(LoopHeader(start, entry)))
return false;
jsbytecode* last = nullptr;
jsbytecode* earlier = nullptr;
@ -2098,6 +2099,9 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_NEWTARGET:
return jsop_newtarget();
case JSOP_CHECKOBJCOERCIBLE:
return jsop_checkobjcoercible();
#ifdef DEBUG
case JSOP_PUSHBLOCKSCOPE:
case JSOP_FRESHENBLOCKSCOPE:
@ -3419,8 +3423,12 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote* sn)
MBasicBlock* defaultcase = newBlock(current, defaultpc);
if (!defaultcase)
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
jsbytecode* casepc = nullptr;
@ -3448,14 +3456,22 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote* sn)
if (!caseblock)
return ControlStatus_Error;
tableswitch->addBlock(caseblock);
if (!tableswitch->addBlock(caseblock))
return ControlStatus_Error;
// Add constant to indicate which case this is for use by
// processNextTableSwitchCase.
MConstant* constant = MConstant::New(alloc(), Int32Value(i + low));
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;
}
@ -5389,7 +5405,7 @@ IonBuilder::selectInliningTargets(const ObjectVector& targets, CallInfo& callInf
inlineable = false;
}
choiceSet.append(inlineable);
choiceSet.infallibleAppend(inlineable);
if (inlineable)
*numInlineable += 1;
}
@ -5881,7 +5897,8 @@ IonBuilder::inlineCalls(CallInfo& callInfo, const ObjectVector& targets, BoolVec
// Connect the inline path to the returnBlock.
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);
retPhi->addInput(retVal);
@ -10309,6 +10326,31 @@ IonBuilder::jsop_rest()
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
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed)
{
@ -13021,7 +13063,7 @@ IonBuilder::jsop_toid()
return true;
MDefinition* index = current->pop();
MToId* ins = MToId::New(alloc(), current->peek(-1), index);
MToId* ins = MToId::New(alloc(), index);
current->add(ins);
current->push(ins);

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

@ -738,6 +738,7 @@ class IonBuilder
bool jsop_setaliasedvar(ScopeCoordinate sc);
bool jsop_debugger();
bool jsop_newtarget();
bool jsop_checkobjcoercible();
/* Inlining. */

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

@ -1097,8 +1097,7 @@ void
LIRGenerator::visitToId(MToId* ins)
{
LToIdV* lir = new(alloc()) LToIdV(tempDouble());
useBox(lir, LToIdV::Object, ins->lhs());
useBox(lir, LToIdV::Index, ins->rhs());
useBox(lir, LToIdV::Index, ins->input());
defineBox(lir, ins);
assignSafepoint(lir, ins);
}
@ -4331,6 +4330,19 @@ LIRGenerator::visitCheckReturn(MCheckReturn* ins)
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
SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
{

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

@ -310,6 +310,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitAtomicIsLockFree(MAtomicIsLockFree* ins);
void visitGuardSharedTypedArray(MGuardSharedTypedArray* ins);
void visitCheckReturn(MCheckReturn* ins);
void visitCheckObjCoercible(MCheckObjCoercible* ins);
};
} // namespace jit

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

@ -2536,11 +2536,11 @@ class MTableSwitch final
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_.empty());
successors_.append(successor);
return successors_.length() - 1;
*index = successors_.length();
return successors_.append(successor);
}
MBasicBlock* getSuccessor(size_t i) const override {
@ -2581,14 +2581,15 @@ class MTableSwitch final
return high() - low() + 1;
}
size_t addDefault(MBasicBlock* block) {
bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
MOZ_ASSERT(successors_.empty());
successors_.append(block);
return 0;
if (index)
*index = 0;
return successors_.append(block);
}
void addCase(size_t successorIndex) {
cases_.append(successorIndex);
bool addCase(size_t successorIndex) {
return cases_.append(successorIndex);
}
MBasicBlock* getBlock(size_t i) const {
@ -2596,8 +2597,8 @@ class MTableSwitch final
return blocks_[i];
}
void addBlock(MBasicBlock* block) {
blocks_.append(block);
bool addBlock(MBasicBlock* block) {
return blocks_.append(block);
}
MDefinition* getOperand(size_t index) const override {
@ -5371,11 +5372,11 @@ class MTypeOf
};
class MToId
: public MBinaryInstruction,
: public MUnaryInstruction,
public BoxInputsPolicy::Data
{
MToId(MDefinition* object, MDefinition* index)
: MBinaryInstruction(object, index)
explicit MToId(MDefinition* index)
: MUnaryInstruction(index)
{
setResultType(MIRType_Value);
}
@ -5383,8 +5384,8 @@ class MToId
public:
INSTRUCTION_HEADER(ToId)
static MToId* New(TempAllocator& alloc, MDefinition* object, MDefinition* index) {
return new(alloc) MToId(object, index);
static MToId* New(TempAllocator& alloc, MDefinition* index) {
return new(alloc) MToId(index);
}
};
@ -10646,8 +10647,8 @@ class MDispatchInstruction
}
public:
void addCase(JSFunction* func, ObjectGroup* funcGroup, MBasicBlock* block) {
map_.append(Entry(func, funcGroup, block));
bool addCase(JSFunction* func, ObjectGroup* funcGroup, MBasicBlock* block) {
return map_.append(Entry(func, funcGroup, block));
}
uint32_t numCases() const {
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
: public MUnaryInstruction,
public NoTypePolicy::Data

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

@ -279,7 +279,8 @@ namespace jit {
_(Debugger) \
_(NewTarget) \
_(ArrowNewTarget) \
_(CheckReturn)
_(CheckReturn) \
_(CheckObjCoercible)
// Forward declarations of MIR types.
#define FORWARD_DECLARE(op) class M##op;

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

@ -65,9 +65,13 @@ struct AllocationIntegrityState
InstructionInfo(const InstructionInfo& o)
{
inputs.appendAll(o.inputs);
temps.appendAll(o.temps);
outputs.appendAll(o.outputs);
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!inputs.appendAll(o.inputs) ||
!temps.appendAll(o.temps) ||
!outputs.appendAll(o.outputs))
{
oomUnsafe.crash("InstructionInfo::InstructionInfo");
}
}
};
Vector<InstructionInfo, 0, SystemAllocPolicy> instructions;
@ -76,7 +80,9 @@ struct AllocationIntegrityState
Vector<InstructionInfo, 5, SystemAllocPolicy> phis;
BlockInfo() {}
BlockInfo(const BlockInfo& o) {
phis.appendAll(o.phis);
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!phis.appendAll(o.phis))
oomUnsafe.crash("BlockInfo::BlockInfo");
}
};
Vector<BlockInfo, 0, SystemAllocPolicy> blocks;

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

@ -1311,6 +1311,15 @@ BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* 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
BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
{

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

@ -738,6 +738,8 @@ bool ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber);
bool BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame);
bool ThrowBadDerivedReturn(JSContext* cx, HandleValue v);
bool ThrowObjectCoercible(JSContext* cx, HandleValue v);
bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
} // 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:
LIR_HEADER(ToIdV)
@ -1286,8 +1286,7 @@ class LToIdV : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 1>
setTemp(0, temp);
}
static const size_t Object = 0;
static const size_t Index = BOX_PIECES;
static const size_t Index = 0;
MToId* mir() const {
return mir_->toToId();
@ -7397,6 +7396,14 @@ class LCheckReturn : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0
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 js

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

@ -367,6 +367,7 @@
_(Debugger) \
_(NewTarget) \
_(ArrowNewTarget) \
_(CheckReturn)
_(CheckReturn) \
_(CheckObjCoercible)
#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_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_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_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}")

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

@ -13,7 +13,6 @@
#include "mozilla/FloatingPoint.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/unused.h"
#include <algorithm> // for std::max
#include <fcntl.h>
@ -802,10 +801,15 @@ GenerateSeed(uint64_t* seedBuffer, size_t length)
if (fd >= 0) {
ssize_t size = length * sizeof(seedBuffer[0]);
ssize_t nread = read(fd, (char *) seedBuffer, size);
MOZ_ASSERT(nread == size, "Can't read /dev/urandom?!");
mozilla::Unused << nread;
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
# error "Platform needs to implement random_generateSeed()"
#endif

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

@ -2231,11 +2231,12 @@ js::LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject s
// See note above RuntimeLexicalErrorObject.
if (pobj == scope) {
if (IsUninitializedLexicalSlot(scope, shape)) {
if (name != cx->names().dotThis && IsUninitializedLexicalSlot(scope, shape)) {
scope = RuntimeLexicalErrorObject::create(cx, scope, JSMSG_UNINITIALIZED_LEXICAL);
if (!scope)
return false;
} 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);
if (!scope)
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");

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

@ -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 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
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))
return false;
textIds.append(textId);
values.append(ToBoolean(v));
textIds.infallibleAppend(textId);
values.infallibleAppend(ToBoolean(v));
}
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 && 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. */
if (!code.isString()) {
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++) {
ParseTask* task = waiting[i];
if (task->runtimeMatches(rt)) {
newTasks.append(task);
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!newTasks.append(task))
oomUnsafe.crash("EnqueuePendingParseTasksAfterGC");
HelperThreadState().remove(waiting, &i);
}
}
@ -444,8 +446,11 @@ js::EnqueuePendingParseTasksAfterGC(JSRuntime* rt)
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);
}

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

@ -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
// for uninitialized lets.
return CheckUninitializedLexical(cx, name, vp);
@ -391,18 +395,14 @@ NegOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue val
}
static MOZ_ALWAYS_INLINE bool
ToIdOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue objval,
HandleValue idval, MutableHandleValue res)
ToIdOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue idval,
MutableHandleValue res)
{
if (idval.isInt32()) {
res.set(idval);
return true;
}
JSObject* obj = ToObjectFromStack(cx, objval);
if (!obj)
return false;
RootedId id(cx);
if (!ToPropertyKey(cx, idval, &id))
return false;

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

@ -1740,7 +1740,6 @@ CASE(JSOP_NOP)
CASE(JSOP_UNUSED14)
CASE(JSOP_UNUSED65)
CASE(JSOP_BACKPATCH)
CASE(JSOP_UNUSED163)
CASE(JSOP_UNUSED177)
CASE(JSOP_UNUSED178)
CASE(JSOP_UNUSED179)
@ -2422,10 +2421,9 @@ CASE(JSOP_TOID)
* 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.
*/
ReservedRooted<Value> objval(&rootValue0, REGS.sp[-2]);
ReservedRooted<Value> idval(&rootValue1, REGS.sp[-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;
}
END_CASE(JSOP_TOID)
@ -3232,10 +3230,7 @@ CASE(JSOP_SETLOCAL)
{
uint32_t i = GET_LOCALNO(REGS.pc);
// Derived class constructors store the TDZ Value in the .this slot
// before a super() call.
MOZ_ASSERT_IF(!script->isDerivedClassConstructor(),
!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));
MOZ_ASSERT(!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));
REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
}
@ -3893,6 +3888,14 @@ 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()
{
char numBuf[12];
@ -4837,9 +4840,6 @@ js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame)
{
RootedFunction fun(cx, frame.callee());
MOZ_ASSERT(fun->isClassConstructor());
MOZ_ASSERT(fun->nonLazyScript()->isDerivedClassConstructor());
const char* name = "anonymous";
JSAutoByteString str;
if (fun->atom()) {

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

@ -1668,7 +1668,14 @@
* Stack: =>
*/ \
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.
*
@ -2122,15 +2129,12 @@
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
* 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.
* Replace the top-of-stack value propertyNameValue with
* ToPropertyKey(propertyNameValue).
* Category: Literals
* Type: Object
* Operands:
* Stack: baseValue, propertyNameValue => baseValue, propertyKey
* Stack: propertyNameValue => propertyKey
*/ \
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))
return false;
gc.zones.append(atomsZone.get());
atomsZone->compartments.append(atomsCompartment.get());
if (!gc.zones.append(atomsZone.get()))
return false;
if (!atomsZone->compartments.append(atomsCompartment.get()))
return false;
atomsCompartment->setIsSystem(true);

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

@ -953,7 +953,7 @@ class ClonedBlockObject : public BlockObject
// Attempting to access anything on this scope throws the appropriate
// 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.
class RuntimeLexicalErrorObject : public ScopeObject
{

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

@ -3875,7 +3875,11 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
RootedFunction function(cx, this->function());
Vector<uint32_t, 32> pcOffsets(cx);
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))
continue;

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

@ -29,11 +29,11 @@ namespace js {
*
* 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 =
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 "
"removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "

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

@ -4575,13 +4575,9 @@ nsDisplayResolution::HitTest(nsDisplayListBuilder* aBuilder,
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames)
{
#if defined(MOZ_SINGLE_PROCESS_APZ)
nsIPresShell* presShell = mFrame->PresContext()->PresShell();
nsRect rect = aRect.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
mList.HitTest(aBuilder, rect, aState, aOutFrames);
#else
mList.HitTest(aBuilder, aRect, aState, aOutFrames);
#endif // MOZ_SINGLE_PROCESS_APZ
}
already_AddRefed<Layer>

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

@ -1416,7 +1416,12 @@ public:
virtual nsresult SetResolution(float aResolution) = 0;
float GetResolution() { return mResolution.valueOr(1.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?

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

@ -2021,9 +2021,7 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
presContext->DevPixelsToAppUnits(aPoint.y));
pt = pt - view->ViewToWidgetOffset();
#if defined(MOZ_SINGLE_PROCESS_APZ)
pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeScaleResolution());
#endif // MOZ_SINGLE_PROCESS_APZ
pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeNonRootScaleResolution());
return pt;
}
}
@ -2059,12 +2057,10 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
int32_t localAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
widgetToView = widgetToView.ScaleToOtherAppUnits(rootAPD, localAPD);
#if defined(MOZ_SINGLE_PROCESS_APZ)
nsIPresShell* shell = aFrame->PresContext()->PresShell();
// XXX Bug 1224748 - Update nsLayoutUtils functions to correctly handle nsPresShell resolution
widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeScaleResolution());
#endif
widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeNonRootScaleResolution());
/* 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.
@ -2812,10 +2808,8 @@ nsLayoutUtils::TranslateViewToWidget(nsPresContext* aPresContext,
return LayoutDeviceIntPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
}
nsPoint pt = aPt + viewOffset;
#if defined(MOZ_SINGLE_PROCESS_APZ)
pt = pt.ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
#endif // MOZ_SINGLE_PROCESS_APZ
nsPoint pt = (aPt +
viewOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution());
LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(pt.x),
aPresContext->AppUnitsToDevPixels(pt.y));
return relativeToViewWidget + WidgetToWidgetOffset(viewWidget, aWidget);

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

@ -5330,13 +5330,16 @@ float PresShell::GetCumulativeResolution()
return resolution;
}
float PresShell::GetCumulativeScaleResolution()
float PresShell::GetCumulativeNonRootScaleResolution()
{
float resolution = 1.0;
nsIPresShell* currentShell = this;
while (currentShell) {
resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f;
nsPresContext* parentCtx = currentShell->GetPresContext()->GetParentPresContext();
nsPresContext* currentCtx = currentShell->GetPresContext();
if (currentCtx != currentCtx->GetRootPresContext()) {
resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f;
}
nsPresContext* parentCtx = currentCtx->GetParentPresContext();
if (parentCtx) {
currentShell = parentCtx->PresShell();
} else {

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

@ -218,7 +218,7 @@ public:
}
virtual bool ScaleToResolution() const override;
virtual float GetCumulativeResolution() override;
virtual float GetCumulativeScaleResolution() override;
virtual float GetCumulativeNonRootScaleResolution() override;
//nsIViewObserver interface

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

@ -20,6 +20,7 @@ support-files =
file_bug1018265.xul
[test_bug370436.html]
skip-if = buildapp == 'b2g'
[test_bug396367-1.html]
[test_bug396367-2.html]
[test_bug420499.xul]

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

@ -442,12 +442,10 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
aBuilder->EnterPresShell(subdocRootFrame,
pointerEventsNone && !passPointerEventsToChildren);
#if defined(MOZ_SINGLE_PROCESS_APZ)
if (!haveDisplayPort) {
// Remove nsPresShell resolution
dirty = dirty.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
}
#endif
} else {
dirty = aDirtyRect;
}

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