Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2015-04-02 17:45:19 -07:00
commit 64dfc0694b
83 changed files with 4105 additions and 1127 deletions

View File

@ -225,7 +225,6 @@ skip-if = e10s
[browser_bug565667.js]
skip-if = toolkit != "cocoa"
[browser_bug567306.js]
skip-if = e10s # Bug XXX - Needs some massaging to run in e10s
[browser_bug575561.js]
[browser_bug575830.js]
skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
@ -462,7 +461,6 @@ skip-if = e10s # Bug 1093941 - ESC reverted the location bar value - Got foobar,
[browser_urlbar_search_healthreport.js]
[browser_utilityOverlay.js]
[browser_visibleFindSelection.js]
skip-if = e10s # Bug 921935 - focusmanager issues with e10s (test calls waitForFocus)
[browser_visibleLabel.js]
[browser_visibleTabs.js]
[browser_visibleTabs_bookmarkAllPages.js]

View File

@ -7,48 +7,44 @@ const {Ci: interfaces, Cc: classes} = Components;
let Clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
let HasFindClipboard = Clipboard.supportsFindClipboard();
function test() {
waitForExplicitFinish();
add_task(function* () {
let newwindow = yield BrowserTestUtils.openNewBrowserWindow();
whenNewWindowLoaded(undefined, function (win) {
whenDelayedStartupFinished(win, function () {
let selectedBrowser = win.gBrowser.selectedBrowser;
selectedBrowser.addEventListener("pageshow", function pageshowListener() {
selectedBrowser.removeEventListener("pageshow", pageshowListener, true);
ok(true, "pageshow listener called: " + win.content.location);
waitForFocus(function () {
onFocus(win);
}, selectedBrowser.contentWindow);
}, true);
selectedBrowser.loadURI("data:text/html,<h1 id='h1'>Select Me</h1>");
});
let selectedBrowser = newwindow.gBrowser.selectedBrowser;
yield new Promise((resolve, reject) => {
selectedBrowser.addEventListener("pageshow", function pageshowListener() {
if (selectedBrowser.currentURI.spec == "about:blank")
return;
selectedBrowser.removeEventListener("pageshow", pageshowListener, true);
ok(true, "pageshow listener called: " + newwindow.content.location);
resolve();
}, true);
selectedBrowser.loadURI("data:text/html,<h1 id='h1'>Select Me</h1>");
});
}
function selectText(win) {
let elt = win.document.getElementById("h1");
let selection = win.getSelection();
let range = win.document.createRange();
range.setStart(elt, 0);
range.setEnd(elt, 1);
selection.removeAllRanges();
selection.addRange(range);
}
yield SimpleTest.promiseFocus(newwindow);
function onFocus(win) {
ok(!win.gFindBarInitialized, "find bar is not yet initialized");
let findBar = win.gFindBar;
selectText(win.content);
ok(!newwindow.gFindBarInitialized, "find bar is not yet initialized");
let findBar = newwindow.gFindBar;
findBar.onFindCommand().then(onInitialized.bind(null, findBar, win));
}
yield ContentTask.spawn(selectedBrowser, { }, function* () {
let elt = content.document.getElementById("h1");
let selection = content.getSelection();
let range = content.document.createRange();
range.setStart(elt, 0);
range.setEnd(elt, 1);
selection.removeAllRanges();
selection.addRange(range);
});
yield findBar.onFindCommand();
function onInitialized(findBar, win) {
// When the OS supports the Find Clipboard (OSX), the find field value is
// persisted across Fx sessions, thus not useful to test.
if (!HasFindClipboard)
is(findBar._findField.value, "Select Me", "Findbar is initialized with selection");
findBar.close();
win.close();
finish();
}
yield promiseWindowClosed(newwindow);
});

View File

@ -1,33 +1,36 @@
add_task(function*() {
const childContent = "<div style='position: absolute; left: 2200px; background: green; width: 200px; height: 200px;'>" +
"div</div><div style='position: absolute; left: 0px; background: red; width: 200px; height: 200px;'>" +
"<span id='s'>div</span></div>";
function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
tab.linkedBrowser.addEventListener("load", function(aEvent) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
yield promiseTabLoadEvent(tab, "data:text/html," + escape(childContent));
yield SimpleTest.promiseFocus(gBrowser.selectedBrowser.contentWindowAsCPOW);
ok(true, "Load listener called");
waitForFocus(onFocus, content);
}, true);
content.location = "data:text/html,<div style='position: absolute; left: 2200px; background: green; width: 200px; height: 200px;'>div</div><div style='position: absolute; left: 0px; background: red; width: 200px; height: 200px;'><span id='s'>div</span></div>";
}
function onFocus() {
let findBarOpenPromise = promiseWaitForEvent(gBrowser, "findbaropen");
EventUtils.synthesizeKey("f", { accelKey: true });
yield findBarOpenPromise;
ok(gFindBarInitialized, "find bar is now initialized");
// Finds the div in the green box.
let scrollPromise = promiseWaitForEvent(gBrowser, "scroll");
EventUtils.synthesizeKey("d", {});
EventUtils.synthesizeKey("i", {});
EventUtils.synthesizeKey("v", {});
// finds the div in the green box
yield scrollPromise;
// Finds the div in the red box.
scrollPromise = promiseWaitForEvent(gBrowser, "scroll");
EventUtils.synthesizeKey("g", { accelKey: true });
// finds the div in the red box
yield scrollPromise;
var rect = content.document.getElementById("s").getBoundingClientRect();
ok(rect.left >= 0, "scroll should include find result");
let scrollLeftPos = yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* (arg) {
return content.document.getElementById("s").getBoundingClientRect().left;
});
ok(scrollLeftPos >= 0, "scroll should include find result");
// clear the find bar
EventUtils.synthesizeKey("a", { accelKey: true });
@ -35,5 +38,5 @@ function onFocus() {
gFindBar.close();
gBrowser.removeCurrentTab();
finish();
}
});

View File

@ -122,13 +122,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
"resource://gre/modules/UpdateChannel.jsm");
#endif
#if defined(MOZ_UPDATE_CHANNEL) && MOZ_UPDATE_CHANNEL != release
#define MOZ_DEBUG_UA // Shorthand define for subsequent conditional sections.
XPCOMUtils.defineLazyModuleGetter(this, "UserAgentOverrides",
"resource://gre/modules/UserAgentOverrides.jsm");
#endif
XPCOMUtils.defineLazyGetter(this, "ShellService", function() {
try {
return Cc["@mozilla.org/browser/shell-service;1"].
@ -727,11 +720,6 @@ BrowserGlue.prototype = {
Services.prefs.addObserver(POLARIS_ENABLED, this, false);
#endif
#ifdef MOZ_DEBUG_UA
UserAgentOverrides.init();
DebugUserAgent.init();
#endif
#ifndef RELEASE_BUILD
let themeName = gBrowserBundle.GetStringFromName("deveditionTheme.name");
let vendorShortName = gBrandBundle.GetStringFromName("vendorShortName");
@ -1003,9 +991,6 @@ BrowserGlue.prototype = {
if (Services.prefs.getBoolPref("dom.identity.enabled")) {
SignInToWebsiteUX.uninit();
}
#endif
#ifdef MOZ_DEBUG_UA
UserAgentOverrides.uninit();
#endif
webrtcUI.uninit();
FormValidationHandler.uninit();
@ -2975,36 +2960,3 @@ let globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessag
globalMM.addMessageListener("UITour:onPageEvent", function(aMessage) {
UITour.onPageEvent(aMessage, aMessage.data);
});
#ifdef MOZ_DEBUG_UA
// Modify the user agent string for specific domains
// to route debug information through their logging.
var DebugUserAgent = {
DEBUG_UA: null,
DOMAINS: [
'youtube.com',
'www.youtube.com',
'youtube-nocookie.com',
'www.youtube-nocookie.com',
],
init: function() {
// Only run if the MediaSource Extension API is available.
if (!Services.prefs.getBoolPref("media.mediasource.enabled")) {
return;
}
// Install our override filter.
UserAgentOverrides.addComplexOverride(this.onRequest.bind(this));
let ua = Cc["@mozilla.org/network/protocol;1?name=http"]
.getService(Ci.nsIHttpProtocolHandler).userAgent;
this.DEBUG_UA = ua + " Build/" + Services.appinfo.appBuildID;
},
onRequest: function(channel, defaultUA) {
if (this.DOMAINS.indexOf(channel.URI.host) != -1) {
return this.DEBUG_UA;
}
return null;
},
};
#endif // MOZ_DEBUG_UA

View File

@ -1621,83 +1621,6 @@ struct GetParentObject<T, false>
}
};
MOZ_ALWAYS_INLINE
JSObject* GetJSObjectFromCallback(CallbackObject* callback)
{
return callback->Callback();
}
MOZ_ALWAYS_INLINE
JSObject* GetJSObjectFromCallback(void* noncallback)
{
return nullptr;
}
template<typename T>
static inline bool
WrapCallThisValue(JSContext* cx, const T& p, JS::MutableHandle<JS::Value> rval)
{
// Callbacks are nsISupports, so WrapNativeParent will just happily wrap them
// up as an nsISupports XPCWrappedNative... which is not at all what we want.
// So we need to special-case them.
JS::Rooted<JSObject*> obj(cx, GetJSObjectFromCallback(p));
if (!obj) {
// WrapNativeParent is a bit of a Swiss army knife that will
// wrap anything for us.
obj = WrapNativeParent(cx, p);
if (!obj) {
return false;
}
}
// But all that won't necessarily put things in the compartment of cx.
if (!JS_WrapObject(cx, &obj)) {
return false;
}
rval.setObject(*obj);
return true;
}
/*
* This specialized function simply wraps a JS::Rooted<> since
* WrapNativeParent() is not applicable for JS objects.
*/
template<>
inline bool
WrapCallThisValue<JS::Rooted<JSObject*>>(JSContext* cx,
const JS::Rooted<JSObject*>& p,
JS::MutableHandle<JS::Value> rval)
{
JS::Rooted<JSObject*> obj(cx, p);
if (!JS_WrapObject(cx, &obj)) {
return false;
}
rval.setObject(*obj);
return true;
}
/*
* This specialization is for wrapping any JS value.
*/
template<>
inline bool
WrapCallThisValue<JS::Rooted<JS::Value>>(JSContext* cx,
const JS::Rooted<JS::Value>& v,
JS::MutableHandle<JS::Value> rval)
{
JS::Rooted<JS::Value> val(cx, v);
if (!JS_WrapValue(cx, &val)) {
return false;
}
rval.set(val);
return true;
}
// Helper for calling GetOrCreateDOMReflector with smart pointers
// (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
template <class T, bool isSmartPtr=IsSmartPtr<T>::value>

View File

@ -1146,14 +1146,14 @@ class CGHeaders(CGWrapper):
if len(callbacks) != 0:
# We need CallbackFunction to serve as our parent class
declareIncludes.add("mozilla/dom/CallbackFunction.h")
# And we need BindingUtils.h so we can wrap "this" objects
declareIncludes.add("mozilla/dom/BindingUtils.h")
# And we need ToJSValue.h so we can wrap "this" objects
declareIncludes.add("mozilla/dom/ToJSValue.h")
if len(callbackDescriptors) != 0 or len(jsImplementedDescriptors) != 0:
# We need CallbackInterface to serve as our parent class
declareIncludes.add("mozilla/dom/CallbackInterface.h")
# And we need BindingUtils.h so we can wrap "this" objects
declareIncludes.add("mozilla/dom/BindingUtils.h")
# And we need ToJSValue.h so we can wrap "this" objects
declareIncludes.add("mozilla/dom/ToJSValue.h")
# Also need to include the headers for ancestors of
# JS-implemented interfaces.
@ -13825,7 +13825,7 @@ class CGCallback(CGClass):
"""
$*{setupCall}
JS::Rooted<JS::Value> thisValJS(s.GetContext());
if (!WrapCallThisValue(s.GetContext(), thisVal, &thisValJS)) {
if (!ToJSValue(s.GetContext(), thisVal, &thisValJS)) {
aRv.Throw(NS_ERROR_FAILURE);
return${errorReturn};
}

View File

@ -38,19 +38,6 @@ ToJSValue(JSContext* aCx, const nsAString& aArgument,
}
namespace tojsvalue_detail {
bool
ISupportsToJSValue(JSContext* aCx,
nsISupports* aArgument,
JS::MutableHandle<JS::Value> aValue)
{
nsresult rv = nsContentUtils::WrapNative(aCx, aArgument, aValue);
return NS_SUCCEEDED(rv);
}
} // namespace tojsvalue_detail
bool
ToJSValue(JSContext* aCx,
nsresult aArgument,

View File

@ -28,10 +28,16 @@ ToJSValue(JSContext* aCx,
const nsAString& aArgument,
JS::MutableHandle<JS::Value> aValue);
// Accept booleans.
MOZ_WARN_UNUSED_RESULT inline bool
// Accept booleans. But be careful here: if we just have a function that takes
// a boolean argument, then any pointer that doesn't match one of our other
// signatures/templates will get treated as a boolean, which is clearly not
// desirable. So make this a template that only gets used if the argument type
// is actually boolean
template<typename T>
MOZ_WARN_UNUSED_RESULT
typename EnableIf<IsSame<T, bool>::value, bool>::Type
ToJSValue(JSContext* aCx,
bool aArgument,
T aArgument,
JS::MutableHandle<JS::Value> aValue)
{
// Make sure we're called in a compartment
@ -174,15 +180,6 @@ ToJSValue(JSContext* aCx,
return true;
}
// We don't want to include nsContentUtils here, so use a helper
// function for the nsISupports case.
namespace tojsvalue_detail {
bool
ISupportsToJSValue(JSContext* aCx,
nsISupports* aArgument,
JS::MutableHandle<JS::Value> aValue);
} // namespace tojsvalue_detail
// Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
// nsIDOMFile).
template <class T>
@ -197,7 +194,9 @@ ToJSValue(JSContext* aCx,
// Make sure we're called in a compartment
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
return tojsvalue_detail::ISupportsToJSValue(aCx, &aArgument, aValue);
qsObjectHelper helper(ToSupports(&aArgument), nullptr);
JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
return XPCOMObjectToJsval(aCx, scope, helper, nullptr, true, aValue);
}
// Accept nsRefPtr/nsCOMPtr
@ -257,6 +256,16 @@ ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument,
return MaybeWrapValue(aCx, aValue);
}
// Accept existing rooted JS objects (which may not be same-compartment with
// us).
MOZ_WARN_UNUSED_RESULT inline bool
ToJSValue(JSContext* aCx, const JS::Rooted<JSObject*>& aArgument,
JS::MutableHandle<JS::Value> aValue)
{
aValue.setObjectOrNull(aArgument);
return MaybeWrapObjectOrNullValue(aCx, aValue);
}
// Accept nsresult, for use in rejections, and create an XPCOM
// exception object representing that nsresult.
MOZ_WARN_UNUSED_RESULT bool

View File

@ -197,7 +197,7 @@ public:
bool* aHasPlugin,
nsCString* aVersion);
virtual void ActorDestroy(ActorDestroyReason aWhy);
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid);

View File

@ -774,7 +774,7 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
dstPtr + (yStride * dstHeight + (uvStride * dstHeight / 2)), uvStride,
dstPtr + (yStride * dstHeight), uvStride,
0, 0,
aWidth, aHeight,
graphicBuffer->getStride(), aHeight,
aWidth, aHeight,
static_cast<libyuv::RotationMode>(mRotation),
libyuv::FOURCC_NV21);
@ -796,7 +796,7 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
dstPtr + (dstWidth * dstHeight), half_width,
dstPtr + (dstWidth * dstHeight * 5 / 4), half_width,
0, 0,
aWidth, aHeight,
graphicBuffer->getStride(), aHeight,
aWidth, aHeight,
static_cast<libyuv::RotationMode>(mRotation),
ConvertPixelFormatToFOURCC(graphicBuffer->getPixelFormat()));

View File

@ -118,6 +118,7 @@ nsSpeechTask::nsSpeechTask(float aVolume, const nsAString& aText)
nsSpeechTask::~nsSpeechTask()
{
LOG(PR_LOG_DEBUG, ("~nsSpeechTask"));
if (mStream) {
if (!mStream->IsDestroyed()) {
mStream->Destroy();
@ -125,6 +126,18 @@ nsSpeechTask::~nsSpeechTask()
mStream = nullptr;
}
if (mPort) {
mPort->Destroy();
mPort = nullptr;
}
}
void
nsSpeechTask::BindStream(ProcessedMediaStream* aStream)
{
mStream = MediaStreamGraph::GetInstance()->CreateSourceStream(nullptr);
mPort = aStream->AllocateInputPort(mStream, 0);
}
NS_IMETHODIMP
@ -137,16 +150,16 @@ nsSpeechTask::Setup(nsISpeechTaskCallback* aCallback,
mCallback = aCallback;
if (argc < 2) {
if (mIndirectAudio) {
if (argc > 0) {
NS_WARNING("Audio info arguments in Setup() are ignored for indirect audio services.");
}
return NS_OK;
}
if (mIndirectAudio) {
NS_WARNING("Audio info arguments in Setup() are ignored for indirect audio services.");
}
// mStream is set up in BindStream() that should be called before this.
MOZ_ASSERT(mStream);
// XXX: Is there setup overhead here that hurtls latency?
mStream = MediaStreamGraph::GetInstance()->CreateSourceStream(nullptr);
mStream->AddListener(new SynthStreamListener(this));
// XXX: Support more than one channel

View File

@ -45,6 +45,8 @@ public:
void SetIndirectAudio(bool aIndirectAudio) { mIndirectAudio = aIndirectAudio; }
void BindStream(ProcessedMediaStream* aStream);
protected:
virtual ~nsSpeechTask();
@ -78,6 +80,8 @@ private:
nsRefPtr<SourceMediaStream> mStream;
nsRefPtr<MediaInputPort> mPort;
nsCOMPtr<nsISpeechTaskCallback> mCallback;
uint32_t mChannels;

View File

@ -134,6 +134,14 @@ nsSynthVoiceRegistry::~nsSynthVoiceRegistry()
// mSpeechSynthChild's lifecycle is managed by the Content protocol.
mSpeechSynthChild = nullptr;
if (mStream) {
if (!mStream->IsDestroyed()) {
mStream->Destroy();
}
mStream = nullptr;
}
mUriVoiceMap.Clear();
}
@ -568,6 +576,11 @@ nsSynthVoiceRegistry::Speak(const nsAString& aText,
if (serviceType == nsISpeechService::SERVICETYPE_INDIRECT_AUDIO) {
aTask->SetIndirectAudio(true);
} else {
if (!mStream) {
mStream = MediaStreamGraph::GetInstance()->CreateTrackUnionStream(nullptr);
}
aTask->BindStream(mStream);
}
voice->mService->Speak(aText, voice->mUri, aRate, aPitch, aTask);

View File

@ -11,6 +11,7 @@
#include "nsISynthVoiceRegistry.h"
#include "nsRefPtrHashtable.h"
#include "nsTArray.h"
#include "MediaStreamGraph.h"
class nsISpeechService;
@ -73,6 +74,8 @@ private:
nsRefPtrHashtable<nsStringHashKey, VoiceData> mUriVoiceMap;
SpeechSynthesisChild* mSpeechSynthChild;
nsRefPtr<ProcessedMediaStream> mStream;
};
} // namespace dom

View File

@ -436,16 +436,20 @@ PluginAsyncSurrogate::SetStreamType(NPStream* aStream, uint16_t aStreamType)
void
PluginAsyncSurrogate::OnInstanceCreated(PluginInstanceParent* aInstance)
{
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
uint16_t streamType = NP_NORMAL;
NPError curError = aInstance->NPP_NewStream(
const_cast<char*>(NullableStringGet(curPendingCall.mType)),
curPendingCall.mStream, curPendingCall.mSeekable,
&streamType);
if (curError != NPERR_NO_ERROR) {
// If we failed here then the send failed and we need to clean up
DestroyAsyncStream(curPendingCall.mStream);
if (!mDestroyPending) {
// If NPP_Destroy has already been called then these streams have already
// been cleaned up on the browser side and are no longer valid.
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
uint16_t streamType = NP_NORMAL;
NPError curError = aInstance->NPP_NewStream(
const_cast<char*>(NullableStringGet(curPendingCall.mType)),
curPendingCall.mStream, curPendingCall.mSeekable,
&streamType);
if (curError != NPERR_NO_ERROR) {
// If we failed here then the send failed and we need to clean up
DestroyAsyncStream(curPendingCall.mStream);
}
}
}
mPendingNewStreamCalls.Clear();
@ -543,10 +547,12 @@ PluginAsyncSurrogate::AsyncCallArriving()
void
PluginAsyncSurrogate::NotifyAsyncInitFailed()
{
// Clean up any pending NewStream requests
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
DestroyAsyncStream(curPendingCall.mStream);
if (!mDestroyPending) {
// Clean up any pending NewStream requests
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
DestroyAsyncStream(curPendingCall.mStream);
}
}
mPendingNewStreamCalls.Clear();
@ -556,9 +562,7 @@ PluginAsyncSurrogate::NotifyAsyncInitFailed()
return;
}
nsPluginInstanceOwner* owner = inst->GetOwner();
if (!owner) {
return;
}
MOZ_ASSERT(owner);
owner->NotifyHostAsyncInitFailed();
}

View File

@ -1739,10 +1739,17 @@ PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult)
mSurrogate->SetAcceptingCalls(true);
}
// It is possible for a plugin instance to outlive its owner (eg. When a
// PluginDestructionGuard was on the stack at the time the owner was being
// destroyed). We need to handle that case.
nsPluginInstanceOwner* owner = GetOwner();
// It is possible for a plugin instance to outlive its owner when async
// plugin init is turned on, so we need to handle that case.
if (aResult != NPERR_NO_ERROR || !owner) {
if (!owner) {
// We can't do anything at this point, just return. Any pending browser
// streams will be cleaned up when the plugin instance is destroyed.
return true;
}
if (aResult != NPERR_NO_ERROR) {
mSurrogate->NotifyAsyncInitFailed();
return true;
}

View File

@ -869,8 +869,7 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
const nsDependentString key(aAttributes[0]);
if (key.EqualsLiteral("src")) {
src.Assign(aAttributes[1]);
}
else if (key.EqualsLiteral("type")) {
} else if (key.EqualsLiteral("type")) {
nsDependentString str(aAttributes[1]);
nsContentTypeParser parser(str);
nsAutoString mimeType;
@ -888,12 +887,8 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
if (nsContentUtils::IsJavascriptMIMEType(mimeType)) {
langID = nsIProgrammingLanguage::JAVASCRIPT;
version = JSVERSION_LATEST;
} else {
langID = nsIProgrammingLanguage::UNKNOWN;
}
if (langID != nsIProgrammingLanguage::UNKNOWN) {
// Get the version string, and ensure the language supports it.
// Get the version string, and ensure that JavaScript supports it.
nsAutoString versionName;
rv = parser.GetParameter("version", versionName);
@ -902,9 +897,10 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
} else if (rv != NS_ERROR_INVALID_ARG) {
return rv;
}
} else {
langID = nsIProgrammingLanguage::UNKNOWN;
}
}
else if (key.EqualsLiteral("language")) {
} else if (key.EqualsLiteral("language")) {
// Language is deprecated, and the impl in nsScriptLoader ignores the
// various version strings anyway. So we make no attempt to support
// languages other than JS for language=
@ -917,80 +913,68 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
aAttributes += 2;
}
// Not all script languages have a "sandbox" concept. At time of
// writing, Python is the only other language, and it does not.
// For such languages, neither any inline script nor remote script are
// safe to execute from untrusted sources.
// So for such languages, we only allow script when the document
// itself is from chrome. We then don't bother to check the
// "src=" tag - we trust chrome to do the right thing.
// (See also similar code in nsScriptLoader.cpp)
nsCOMPtr<nsIDocument> doc(do_QueryReferent(mDocument));
if (langID != nsIProgrammingLanguage::UNKNOWN &&
langID != nsIProgrammingLanguage::JAVASCRIPT &&
doc && !nsContentUtils::IsChromeDoc(doc)) {
langID = nsIProgrammingLanguage::UNKNOWN;
NS_WARNING("Non JS language called from non chrome - ignored");
}
// Don't process scripts that aren't known
if (langID != nsIProgrammingLanguage::UNKNOWN) {
nsCOMPtr<nsIScriptGlobalObject> globalObject;
if (doc)
globalObject = do_QueryInterface(doc->GetWindow());
nsRefPtr<nsXULPrototypeScript> script =
new nsXULPrototypeScript(aLineNumber, version);
if (! script)
return NS_ERROR_OUT_OF_MEMORY;
if (langID == nsIProgrammingLanguage::UNKNOWN) {
return NS_OK;
}
// If there is a SRC attribute...
if (! src.IsEmpty()) {
// Use the SRC attribute value to load the URL
rv = NS_NewURI(getter_AddRefs(script->mSrcURI), src, nullptr, mDocumentURL);
nsCOMPtr<nsIScriptGlobalObject> globalObject;
if (doc)
globalObject = do_QueryInterface(doc->GetWindow());
nsRefPtr<nsXULPrototypeScript> script =
new nsXULPrototypeScript(aLineNumber, version);
if (! script)
return NS_ERROR_OUT_OF_MEMORY;
// Check if this document is allowed to load a script from this source
// NOTE: if we ever allow scripts added via the DOM to run, we need to
// add a CheckLoadURI call for that as well.
// If there is a SRC attribute...
if (! src.IsEmpty()) {
// Use the SRC attribute value to load the URL
rv = NS_NewURI(getter_AddRefs(script->mSrcURI), src, nullptr, mDocumentURL);
// Check if this document is allowed to load a script from this source
// NOTE: if we ever allow scripts added via the DOM to run, we need to
// add a CheckLoadURI call for that as well.
if (NS_SUCCEEDED(rv)) {
if (!mSecMan)
mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
if (!mSecMan)
mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument, &rv);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument, &rv);
if (NS_SUCCEEDED(rv)) {
rv = mSecMan->
CheckLoadURIWithPrincipal(doc->NodePrincipal(),
script->mSrcURI,
nsIScriptSecurityManager::ALLOW_CHROME);
}
if (NS_SUCCEEDED(rv)) {
rv = mSecMan->
CheckLoadURIWithPrincipal(doc->NodePrincipal(),
script->mSrcURI,
nsIScriptSecurityManager::ALLOW_CHROME);
}
}
if (NS_FAILED(rv)) {
return rv;
}
// Attempt to deserialize an out-of-line script from the FastLoad
// file right away. Otherwise we'll end up reloading the script and
// corrupting the FastLoad file trying to serialize it, in the case
// where it's already there.
script->DeserializeOutOfLine(nullptr, mPrototype);
}
nsPrototypeArray* children = nullptr;
rv = mContextStack.GetTopChildren(&children);
if (NS_FAILED(rv)) {
return rv;
}
children->AppendElement(script);
mConstrainSize = false;
mContextStack.Push(script, mState);
mState = eInScript;
// Attempt to deserialize an out-of-line script from the FastLoad
// file right away. Otherwise we'll end up reloading the script and
// corrupting the FastLoad file trying to serialize it, in the case
// where it's already there.
script->DeserializeOutOfLine(nullptr, mPrototype);
}
nsPrototypeArray* children = nullptr;
rv = mContextStack.GetTopChildren(&children);
if (NS_FAILED(rv)) {
return rv;
}
children->AppendElement(script);
mConstrainSize = false;
mContextStack.Push(script, mState);
mState = eInScript;
return NS_OK;
}
@ -1071,8 +1055,7 @@ XULContentSinkImpl::AddText(const char16_t* aText,
if (NS_OK != rv) {
return rv;
}
}
else {
} else {
mTextSize += aLength;
mText = (char16_t *) realloc(mText, sizeof(char16_t) * mTextSize);
if (nullptr == mText) {

View File

@ -1983,10 +1983,11 @@ gfxWindowsPlatform::InitD3D11Devices()
if (FAILED(hr)) {
// This should always succeed... in theory.
gfxCriticalError() << "Failed to initialize WARP D3D11 device!" << hr;
} else {
mIsWARP = true;
reporterWARP.SetSuccessful();
return;
}
mIsWARP = true;
reporterWARP.SetSuccessful();
}
mD3D11Device->SetExceptionMode(0);

View File

@ -783,7 +783,7 @@ static const JSFunctionSpec sInt64StaticFunctions[] = {
JS_FN("compare", Int64::Compare, 2, CTYPESFN_FLAGS),
JS_FN("lo", Int64::Lo, 1, CTYPESFN_FLAGS),
JS_FN("hi", Int64::Hi, 1, CTYPESFN_FLAGS),
JS_FN("join", Int64::Join, 2, CTYPESFN_FLAGS),
// "join" is defined specially; see InitInt64Class.
JS_FS_END
};
@ -791,7 +791,7 @@ static const JSFunctionSpec sUInt64StaticFunctions[] = {
JS_FN("compare", UInt64::Compare, 2, CTYPESFN_FLAGS),
JS_FN("lo", UInt64::Lo, 1, CTYPESFN_FLAGS),
JS_FN("hi", UInt64::Hi, 1, CTYPESFN_FLAGS),
JS_FN("join", UInt64::Join, 2, CTYPESFN_FLAGS),
// "join" is defined specially; see InitInt64Class.
JS_FS_END
};
@ -1102,10 +1102,8 @@ InitInt64Class(JSContext* cx,
RootedObject ctor(cx, JS_GetConstructor(cx, prototype));
if (!ctor)
return nullptr;
if (!JS_FreezeObject(cx, ctor))
return nullptr;
// Redefine the 'join' function as an extended native and stash
// Define the 'join' function as an extended native and stash
// ctypes.{Int64,UInt64}.prototype in a reserved slot of the new function.
MOZ_ASSERT(clasp == &sInt64ProtoClass || clasp == &sUInt64ProtoClass);
JSNative native = (clasp == &sInt64ProtoClass) ? Int64::Join : UInt64::Join;
@ -1117,6 +1115,8 @@ InitInt64Class(JSContext* cx,
js::SetFunctionNativeReserved(fun, SLOT_FN_INT64PROTO,
OBJECT_TO_JSVAL(prototype));
if (!JS_FreezeObject(cx, ctor))
return nullptr;
if (!JS_FreezeObject(cx, prototype))
return nullptr;

View File

@ -0,0 +1,19 @@
load(libdir + 'bytecode-cache.js');
// Ensure that if a function is encoded when non-lazy but relazifiable, then
// decoded, the resulting LazyScript is marked as being non-lazy so that when
// the debugger tries to delazify things it doesn't get all confused. We just
// use findScripts() to trigger debugger delazification; we don't really care
// about the scripts themselves.
function checkAfter(ctx) {
var dbg = new Debugger(ctx.global);
var allScripts = dbg.findScripts();
assertEq(allScripts.length == 0, false);
}
test = `
function f() { return true; };
f();
`
evalWithCache(test, { assertEqBytecode: true, assertEqResult: true,
checkAfter: checkAfter });

View File

@ -2595,7 +2595,7 @@ class PropertyDescriptorOperations
MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
MOZ_ASSERT(!has(SHADOWABLE));
MOZ_ASSERT(desc()->value.isUndefined());
MOZ_ASSERT(value().isUndefined());
MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
} else {

View File

@ -505,7 +505,7 @@ js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
return false;
}
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
/* ES6 draft rev 34 (2015 Feb 20) 9.4.2.4 ArraySetLength */
bool
js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
unsigned attrs, HandleValue value, ObjectOpResult& result)
@ -515,26 +515,26 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
if (!arr->maybeCopyElementsForWrite(cx))
return false;
/* Steps 1-2 are irrelevant in our implementation. */
/* Steps 3-5. */
// Step 1.
uint32_t newLen;
if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
return false;
if (attrs & JSPROP_IGNORE_VALUE) {
// The spec has us calling OrdinaryDefineOwnProperty if
// Desc.[[Value]] is absent, but our implementation is so different that
// this is impossible. Instead, set newLen to the current length and
// proceed to step 9.
newLen = arr->length();
} else {
// Step 2 is irrelevant in our implementation.
// Abort if we're being asked to change enumerability or configurability.
// (The length property of arrays is non-configurable, so such attempts
// must fail.) This behavior is spread throughout the ArraySetLength spec
// algorithm, but we only need check it once as our array implementation
// is internally so different from the spec algorithm. (ES5 and ES6 define
// behavior by delegating to the default define-own-property algorithm --
// OrdinaryDefineOwnProperty in ES6, the default [[DefineOwnProperty]] in
// ES5 -- but we reimplement all the conflict-detection bits ourselves here
// so that we can use a customized length representation.)
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE))
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Steps 3-7.
MOZ_ASSERT_IF(attrs & JSPROP_IGNORE_VALUE, value.isUndefined());
if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
return false;
/* Steps 6-7. */
// Step 8 is irrelevant in our implementation.
}
// Steps 9-11.
bool lengthIsWritable = arr->lengthIsWritable();
#ifdef DEBUG
{
@ -543,10 +543,21 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
MOZ_ASSERT(lengthShape->writable() == lengthIsWritable);
}
#endif
uint32_t oldLen = arr->length();
/* Steps 8-9 for arrays with non-writable length. */
// Part of steps 1.a, 12.a, and 16: Fail if we're being asked to change
// enumerability or configurability, or otherwise break the object
// invariants. (ES6 checks these by calling OrdinaryDefineOwnProperty, but
// in SM, the array length property is hardly ordinary.)
if ((attrs & (JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT)) == 0 ||
(attrs & (JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE)) == JSPROP_ENUMERATE ||
(attrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0 ||
(!lengthIsWritable && (attrs & (JSPROP_READONLY | JSPROP_IGNORE_READONLY)) == 0))
{
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
// Steps 12-13 for arrays with non-writable length.
if (!lengthIsWritable) {
if (newLen == oldLen)
return result.succeed();
@ -554,7 +565,7 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
return result.fail(JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
/* Step 8. */
// Step 19.
bool succeeded = true;
do {
// The initialized length and capacity of an array only need updating
@ -616,10 +627,10 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// If we're removing a relatively small number of elements, just do
// it exactly by the spec.
while (newLen < oldLen) {
/* Step 15a. */
// Step 15a.
oldLen--;
/* Steps 15b-d. */
// Steps 15b-d.
ObjectOpResult deleteSucceeded;
if (!DeleteElement(cx, arr, oldLen, deleteSucceeded))
return false;
@ -679,7 +690,7 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
MOZ_ASSERT(indexes[i] < index, "indexes should never repeat");
index = indexes[i];
/* Steps 15b-d. */
// Steps 15b-d.
ObjectOpResult deleteSucceeded;
if (!DeleteElement(cx, arr, index, deleteSucceeded))
return false;
@ -692,23 +703,25 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
}
} while (false);
/* Steps 12, 16. */
// Yes, we totally drop a non-stub getter/setter from a defineProperty
// API call on the floor here. Given that getter/setter will go away in
// the long run, with accessors replacing them both internally and at the
// API level, just run with this.
RootedShape lengthShape(cx, arr->lookup(cx, id));
if (!NativeObject::changeProperty(cx, arr, lengthShape,
attrs | JSPROP_PERMANENT | JSPROP_SHARED |
(lengthShape->attributes() & JSPROP_READONLY),
array_length_getter, array_length_setter))
{
return false;
}
// Update array length. Technically we should have been doing this
// throughout the loop, in step 19.d.iii.
arr->setLength(cx, newLen);
// Step 20.
if (attrs & JSPROP_READONLY) {
// Yes, we totally drop a non-stub getter/setter from a defineProperty
// API call on the floor here. Given that getter/setter will go away in
// the long run, with accessors replacing them both internally and at the
// API level, just run with this.
RootedShape lengthShape(cx, arr->lookup(cx, id));
if (!NativeObject::changeProperty(cx, arr, lengthShape,
lengthShape->attributes() | JSPROP_READONLY,
array_length_getter, array_length_setter))
{
return false;
}
}
// All operations past here until the |!succeeded| code must be infallible,
// so that all element fields remain properly synchronized.

View File

@ -1407,7 +1407,8 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
// chain of their inner functions, or in the case of eval, possibly
// eval'd inner functions. This prohibits re-lazification as
// StaticScopeIter queries isHeavyweight of those functions, which
// requires a non-lazy script.
// requires a non-lazy script. Note that if this ever changes,
// XDRRelazificationInfo will have to be fixed.
bool canRelazify = !lazy->numInnerFunctions() && !lazy->hasDirectEval();
if (script) {

View File

@ -627,44 +627,8 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id,
MOZ_ASSERT(IsAnyTypedArray(obj));
// Steps 3.a-c.
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
// These are all substeps of 3.c.
// Steps i-vi.
// We (wrongly) ignore out of range defines with a value.
if (index >= AnyTypedArrayLength(obj))
return result.succeed();
// Step vii.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step viii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step ix.
if (desc.hasEnumerable() && !desc.enumerable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step x.
if (desc.hasWritable() && !desc.writable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step xi.
if (desc.hasValue()) {
double d;
if (!ToNumber(cx, desc.value(), &d))
return false;
if (obj->is<TypedArrayObject>())
TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
else
SharedTypedArrayObject::setElement(obj->as<SharedTypedArrayObject>(), index, d);
}
// Step xii.
return result.succeed();
}
if (IsTypedArrayIndex(id, &index))
return DefineTypedArrayElement(cx, obj, index, desc, result);
// Step 4.
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);

View File

@ -710,16 +710,16 @@ Walk(JSContext* cx, HandleObject holder, HandleId name, HandleValue reviver, Mut
if (!Walk(cx, obj, id, reviver, &newElement))
return false;
ObjectOpResult ignored;
if (newElement.isUndefined()) {
/* Step 2a(iii)(2). */
ObjectOpResult ignored;
/* Step 2a(iii)(2). The spec deliberately ignores strict failure. */
if (!DeleteProperty(cx, obj, id, ignored))
return false;
} else {
/* Step 2a(iii)(3). */
// XXX This definition should ignore success/failure, when
// our property-definition APIs indicate that.
if (!DefineProperty(cx, obj, id, newElement))
/* Step 2a(iii)(3). The spec deliberately ignores strict failure. */
Rooted<PropertyDescriptor> desc(cx);
desc.setDataDescriptor(newElement, JSPROP_ENUMERATE);
if (!StandardDefineProperty(cx, obj, id, desc, ignored))
return false;
}
}
@ -738,16 +738,16 @@ Walk(JSContext* cx, HandleObject holder, HandleId name, HandleValue reviver, Mut
if (!Walk(cx, obj, id, reviver, &newElement))
return false;
ObjectOpResult ignored;
if (newElement.isUndefined()) {
/* Step 2b(ii)(2). */
ObjectOpResult ignored;
/* Step 2b(ii)(2). The spec deliberately ignores strict failure. */
if (!DeleteProperty(cx, obj, id, ignored))
return false;
} else {
/* Step 2b(ii)(3). */
// XXX This definition should ignore success/failure, when
// our property-definition APIs indicate that.
if (!DefineProperty(cx, obj, id, newElement))
/* Step 2b(ii)(3). The spec deliberately ignores strict failure. */
Rooted<PropertyDescriptor> desc(cx);
desc.setDataDescriptor(newElement, JSPROP_ENUMERATE);
if (!StandardDefineProperty(cx, obj, id, desc, ignored))
return false;
}
}

View File

@ -504,21 +504,23 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
MOZ_ASSERT(end == lazy->end());
MOZ_ASSERT(lineno == lazy->lineno());
MOZ_ASSERT(column == lazy->column());
// We can assert we have no inner functions because we don't
// relazify scripts with inner functions. See
// JSFunction::createScriptForLazilyInterpretedFunction.
MOZ_ASSERT(lazy->numInnerFunctions() == 0);
}
if (!xdr->codeUint64(&packedFields))
return false;
if (mode == XDR_DECODE) {
lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
lazy.set(LazyScript::Create(cx, fun, script, enclosingScope, script,
packedFields, begin, end, lineno, column));
// As opposed to XDRLazyScript, we need to restore the runtime bits
// of the script, as we are trying to match the fact this function
// has already been parsed and that it would need to be re-lazified.
lazy->initRuntimeFields(packedFields);
MOZ_ASSERT(!lazy->sourceObject());
lazy->setParent(enclosingScope, &script->scriptSourceUnwrap());
}
}
@ -526,6 +528,9 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
if (!XDRLazyFreeVariables(xdr, lazy))
return false;
// No need to do anything with inner functions, since we asserted we don't
// have any.
return true;
}
@ -1143,7 +1148,8 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
}
if (mode == XDR_DECODE)
lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
lazy.set(LazyScript::Create(cx, fun, NullPtr(), enclosingScope, enclosingScript,
packedFields, begin, end, lineno, column));
}
// Code free variables.
@ -1167,15 +1173,6 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
}
}
if (mode == XDR_DECODE) {
MOZ_ASSERT(!lazy->sourceObject());
ScriptSourceObject* sourceObject = &enclosingScript->scriptSourceUnwrap();
// Set the enclosing scope of the lazy function, this would later be
// used to define the environment when the function would be used.
lazy->setParent(enclosingScope, sourceObject);
}
return true;
}
@ -3826,6 +3823,8 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
/* static */ LazyScript*
LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
HandleScript script, HandleObject enclosingScope,
HandleScript sourceObjectScript,
uint64_t packedFields, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column)
{
@ -3851,6 +3850,15 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
for (i = 0, num = res->numInnerFunctions(); i < num; i++)
functions[i].init(dummyFun);
// Set the enclosing scope of the lazy function, this would later be
// used to define the environment when the function would be used.
MOZ_ASSERT(!res->sourceObject());
res->setParent(enclosingScope, &sourceObjectScript->scriptSourceUnwrap());
MOZ_ASSERT(!res->maybeScript());
if (script)
res->initScript(script);
return res;
}

View File

@ -1919,7 +1919,15 @@ class LazyScript : public gc::TenuredCell
// Create a LazyScript and initialize the freeVariables and the
// innerFunctions with dummy values to be replaced in a later initialization
// phase.
//
// The "script" argument to this function can be null. If it's non-null,
// then this LazyScript should be associated with the given JSScript.
//
// The sourceObjectScript argument must be non-null and is the script that
// should be used to get the sourceObject_ of this lazyScript.
static LazyScript* Create(ExclusiveContext* cx, HandleFunction fun,
HandleScript script, HandleObject enclosingScope,
HandleScript sourceObjectScript,
uint64_t packedData, uint32_t begin, uint32_t end,
uint32_t lineno, uint32_t column);

View File

@ -336,6 +336,10 @@ function jsTestDriverBrowserInit()
{
properties.version = '1.8';
}
else if (properties.test.match(/^ecma_6\/extensions/))
{
properties.version = '1.8';
}
}
// default to language=type;text/javascript. required for

View File

@ -1,4 +1,6 @@
// Enable "let" in shell builds. So silly.
// NOTE: This only turns on 1.8.5 in shell builds. The browser requires the
// futzing in js/src/tests/browser.js (which only turns on 1.8, the most
// the browser supports).
if (typeof version != 'undefined')
version(185);

View File

@ -0,0 +1,125 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = "for-loop-with-bindings-added-at-runtime.js";
//-----------------------------------------------------------------------------
var BUGNUMBER = 1149797;
var summary =
"Don't assert when freshening the scope chain for a for-loop whose head " +
"contains a lexical declaration, where the loop body might add more " +
"bindings at runtime";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
for (let x = 0; x < 9; ++x)
eval("var y");
{
for (let x = 0; x < 9; ++x)
eval("var y");
}
function f1()
{
for (let x = 0; x < 9; ++x)
eval("var y");
}
f1();
function f2()
{
{
for (let x = 0; x < 9; ++x)
eval("var y");
}
}
f2();
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
eval("var y");
}
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
eval("var y");
}
}
function g1()
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
eval("var y");
}
}
g1();
function g2()
{
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
eval("var y");
}
}
}
g2();
for (let x = 0; x < 9; ++x) {
(function() {
eval("var y");
})();
}
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() {
eval("var y");
})();
}
}
function h1()
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() {
eval("var y");
})();
}
}
h1();
function h2()
{
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() { eval("var y"); })();
}
}
}
h2();
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -0,0 +1,126 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile =
"for-loop-with-lexical-declaration-and-nested-function-statement.js";
//-----------------------------------------------------------------------------
var BUGNUMBER = 1149797;
var summary =
"Don't assert when freshening the scope chain for a for-loop whose head " +
"contains a lexical declaration, where the loop body might add more " +
"bindings at runtime";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
for (let x = 0; x < 9; ++x)
function q1() {}
{
for (let x = 0; x < 9; ++x)
function q2() {}
}
function f1()
{
for (let x = 0; x < 9; ++x)
function q3() {}
}
f1();
function f2()
{
{
for (let x = 0; x < 9; ++x)
function q4() {}
}
}
f2();
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
function q5() {}
}
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
function q6() {}
}
}
function g1()
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
function q7() {}
}
}
g1();
function g2()
{
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
function q8() {}
}
}
}
g2();
for (let x = 0; x < 9; ++x) {
(function() {
eval("function q9() {}");
})();
}
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() {
eval("function q10() {}");
})();
}
}
function h1()
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() {
eval("function q11() {}");
})();
}
}
h1();
function h2()
{
{
for (let x = 0; x < 9; ++x)
{
// deliberately inside a block statement
(function() { eval("function q12() {}"); })();
}
}
}
h2();
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -0,0 +1,5 @@
// NOTE: This only turns on 1.8.5 in shell builds. The browser requires the
// futzing in js/src/tests/browser.js (which only turns on 1.8, the most
// the browser supports).
if (typeof version != 'undefined')
version(185);

View File

@ -567,11 +567,14 @@ struct AutoStopwatch final
ULARGE_INTEGER userTimeInt;
kernelTimeInt.LowPart = kernelFileTime.dwLowDateTime;
kernelTimeInt.HighPart = kernelFileTime.dwHighDateTime;
*systemTime = kernelTimeInt.QuadPart / 10; // 100 ns to 1 us
// Convert 100 ns to 1 us, make sure that the result is monotonic
*systemTime = runtime_-> stopwatch.systemTimeFix.monotonize(kernelTimeInt.QuadPart / 10);
userTimeInt.LowPart = userFileTime.dwLowDateTime;
userTimeInt.HighPart = userFileTime.dwHighDateTime;
*userTime = userTimeInt.QuadPart / 10; // 100 ns to 1 us
// Convert 100 ns to 1 us, make sure that the result is monotonic
*userTime = runtime_-> stopwatch.userTimeFix.monotonize(userTimeInt.QuadPart / 10);
#endif // defined(XP_UNIX) || defined(XP_WIN)
return true;

View File

@ -1111,109 +1111,6 @@ UpdateShapeTypeAndValue(ExclusiveContext* cx, NativeObject* obj, Shape* shape, c
return true;
}
static bool
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
HandleValue v, HandleValue receiver, ObjectOpResult& result);
static inline bool
DefinePropertyOrElement(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
GetterOp getter, SetterOp setter, unsigned attrs, HandleValue value,
bool callSetterAfterwards, ObjectOpResult& result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
/* Use dense storage for new indexed properties where possible. */
if (JSID_IS_INT(id) &&
!getter &&
!setter &&
attrs == JSPROP_ENUMERATE &&
(!obj->isIndexed() || !obj->containsPure(id)) &&
!IsAnyTypedArray(obj))
{
uint32_t index = JSID_TO_INT(id);
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
NativeObject::EnsureDenseResult edResult = obj->ensureDenseElements(cx, index, 1);
if (edResult == NativeObject::ED_FAILED)
return false;
if (edResult == NativeObject::ED_OK) {
obj->setDenseElementWithType(cx, index, value);
if (!CallAddPropertyHookDense(cx, obj, index, value))
return false;
return result.succeed();
}
}
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length)) {
if (!cx->shouldBeJSContext())
return false;
return ArraySetLength(cx->asJSContext(), arr, id, attrs, value, result);
}
uint32_t index;
if (IdIsIndex(id, &index)) {
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
}
}
// Don't define new indexed properties on typed arrays.
if (IsAnyTypedArray(obj)) {
uint64_t index;
if (IsTypedArrayIndex(id, &index))
return result.succeed();
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedShape shape(cx, NativeObject::putProperty(cx, obj, id, getter, setter,
SHAPE_INVALID_SLOT, attrs, 0));
if (!shape)
return false;
if (!UpdateShapeTypeAndValue(cx, obj, shape, value))
return false;
/*
* Clear any existing dense index after adding a sparse indexed property,
* and investigate converting the object to dense indexes.
*/
if (JSID_IS_INT(id)) {
if (!obj->maybeCopyElementsForWrite(cx))
return false;
uint32_t index = JSID_TO_INT(id);
NativeObject::removeDenseElementForSparseIndex(cx, obj, index);
NativeObject::EnsureDenseResult edResult = NativeObject::maybeDensifySparseElements(cx, obj);
if (edResult == NativeObject::ED_FAILED)
return false;
if (edResult == NativeObject::ED_OK) {
MOZ_ASSERT(!setter);
if (!CallAddPropertyHookDense(cx, obj, index, value))
return false;
return result.succeed();
}
}
if (!CallAddPropertyHook(cx, obj, shape, value))
return false;
if (callSetterAfterwards && setter) {
MOZ_ASSERT(!(attrs & JSPROP_GETTER));
MOZ_ASSERT(!(attrs & JSPROP_SETTER));
if (!cx->shouldBeJSContext())
return false;
RootedValue receiver(cx, ObjectValue(*obj));
return NativeSetExistingDataProperty(cx->asJSContext(), obj, shape, value, receiver,
result);
}
return result.succeed();
}
static unsigned
ApplyOrDefaultAttributes(unsigned attrs, const Shape* shape = nullptr)
{
@ -1297,10 +1194,12 @@ PurgeScopeChain(ExclusiveContext* cx, HandleObject obj, HandleId id)
*/
static inline bool
CheckAccessorRedefinition(ExclusiveContext* cx, HandleObject obj, HandleShape shape,
GetterOp getter, SetterOp setter, HandleId id, unsigned attrs)
Handle<PropertyDescriptor> desc)
{
MOZ_ASSERT(shape->isAccessorDescriptor());
if (shape->configurable() || (getter == shape->getter() && setter == shape->setter()))
if (shape->configurable())
return true;
if (desc.getter() == shape->getter() && desc.setter() == shape->setter())
return true;
/*
@ -1309,7 +1208,7 @@ CheckAccessorRedefinition(ExclusiveContext* cx, HandleObject obj, HandleShape sh
* never have such a thing on its proto chain directly on the web, so we
* should be OK optimizing access to accessors found on such an object.
*/
if ((attrs & JSPROP_REDEFINE_NONCONFIGURABLE) &&
if ((desc.attributes() & JSPROP_REDEFINE_NONCONFIGURABLE) &&
obj->is<GlobalObject>() &&
!obj->getClass()->isDOMClass())
{
@ -1319,44 +1218,134 @@ CheckAccessorRedefinition(ExclusiveContext* cx, HandleObject obj, HandleShape sh
if (!cx->isJSContext())
return false;
return Throw(cx->asJSContext(), id, JSMSG_CANT_REDEFINE_PROP);
return Throw(cx->asJSContext(), shape->propid(), JSMSG_CANT_REDEFINE_PROP);
}
static bool
AddOrChangeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
Handle<PropertyDescriptor> desc)
{
desc.assertComplete();
if (!PurgeScopeChain(cx, obj, id))
return false;
// Use dense storage for new indexed properties where possible.
if (JSID_IS_INT(id) &&
!desc.getter() &&
!desc.setter() &&
desc.attributes() == JSPROP_ENUMERATE &&
(!obj->isIndexed() || !obj->containsPure(id)) &&
!IsAnyTypedArray(obj))
{
uint32_t index = JSID_TO_INT(id);
NativeObject::EnsureDenseResult edResult = obj->ensureDenseElements(cx, index, 1);
if (edResult == NativeObject::ED_FAILED)
return false;
if (edResult == NativeObject::ED_OK) {
obj->setDenseElementWithType(cx, index, desc.value());
if (!CallAddPropertyHookDense(cx, obj, index, desc.value()))
return false;
return true;
}
}
RootedShape shape(cx, NativeObject::putProperty(cx, obj, id, desc.getter(), desc.setter(),
SHAPE_INVALID_SLOT, desc.attributes(), 0));
if (!shape)
return false;
if (!UpdateShapeTypeAndValue(cx, obj, shape, desc.value()))
return false;
// Clear any existing dense index after adding a sparse indexed property,
// and investigate converting the object to dense indexes.
if (JSID_IS_INT(id)) {
if (!obj->maybeCopyElementsForWrite(cx))
return false;
uint32_t index = JSID_TO_INT(id);
NativeObject::removeDenseElementForSparseIndex(cx, obj, index);
NativeObject::EnsureDenseResult edResult =
NativeObject::maybeDensifySparseElements(cx, obj);
if (edResult == NativeObject::ED_FAILED)
return false;
if (edResult == NativeObject::ED_OK) {
MOZ_ASSERT(!desc.setter());
return CallAddPropertyHookDense(cx, obj, index, desc.value());
}
}
return CallAddPropertyHook(cx, obj, shape, desc.value());
}
bool
js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
Handle<PropertyDescriptor> desc,
Handle<PropertyDescriptor> desc_,
ObjectOpResult& result)
{
desc.assertValid();
desc_.assertValid();
GetterOp getter = desc.getter();
SetterOp setter = desc.setter();
unsigned attrs = desc.attributes();
// Section numbers and step numbers below refer to ES6 draft rev 36
// (17 March 2015).
//
// This function aims to implement 9.1.6 [[DefineOwnProperty]] as well as
// the [[DefineOwnProperty]] methods described in 9.4.2.1 (arrays), 9.4.4.2
// (arguments), and 9.4.5.3 (typed array views).
MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
// Dispense with custom behavior of exotic native objects first.
if (obj->is<ArrayObject>()) {
// 9.4.2.1 step 2. Redefining an array's length is very special.
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length)) {
if (!cx->shouldBeJSContext())
return false;
return ArraySetLength(cx->asJSContext(), arr, id, desc_.attributes(), desc_.value(),
result);
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
// 9.4.2.1 step 3. Don't extend a fixed-length array.
uint32_t index;
if (IdIsIndex(id, &index)) {
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
}
} else if (IsAnyTypedArray(obj)) {
// 9.4.5.3 step 3. Indexed properties of typed arrays are special.
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
if (!cx->shouldBeJSContext())
return false;
return DefineTypedArrayElement(cx->asJSContext(), obj, index, desc_, result);
}
} else if (obj->is<ArgumentsObject>()) {
if (id == NameToId(cx->names().length)) {
// Either we are resolving the .length property on this object, or
// redefining it. In the latter case only, we must set a bit. To
// distinguish the two cases, we note that when resolving, the
// property won't already exist; whereas the first time it is
// redefined, it will.
if (obj->containsPure(id))
obj->as<ArgumentsObject>().markLengthOverridden();
}
}
Rooted<PropertyDescriptor> desc(cx, desc_);
RootedShape shape(cx);
RootedValue updateValue(cx, desc.value());
bool shouldDefine = true;
/*
* If defining a getter or setter, we must check for its counterpart and
* update the attributes and property ops. A getter or setter is really
* only half of a property.
*/
// If defining a getter or setter, we must check for its counterpart and
// update the attributes and property ops. A getter or setter is really
// only half of a property.
if (desc.isAccessorDescriptor()) {
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
return false;
if (shape) {
/*
* If we are defining a getter whose setter was already defined, or
* vice versa, finish the job via obj->changeProperty.
*/
// If we are defining a getter whose setter was already defined, or
// vice versa, finish the job via obj->changeProperty.
if (IsImplicitDenseOrTypedArrayElement(shape)) {
if (IsAnyTypedArray(obj)) {
/* Ignore getter/setter properties added to typed arrays. */
// Ignore getter/setter properties added to typed arrays.
return result.succeed();
}
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
@ -1364,28 +1353,35 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
shape = obj->lookup(cx, id);
}
if (shape->isAccessorDescriptor()) {
if (!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
if (!CheckAccessorRedefinition(cx, obj, shape, desc))
return false;
attrs = ApplyOrDefaultAttributes(attrs, shape);
shape = NativeObject::changeProperty(cx, obj, shape,
attrs | JSPROP_GETTER | JSPROP_SETTER,
(attrs & JSPROP_GETTER)
? getter
: shape->getter(),
(attrs & JSPROP_SETTER)
? setter
: shape->setter());
desc.setAttributes(ApplyOrDefaultAttributes(desc.attributes(), shape));
if (!desc.hasGetterObject())
desc.setGetter(shape->getter());
if (!desc.hasSetterObject())
desc.setSetter(shape->setter());
desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER;
desc.assertComplete();
shape = NativeObject::changeProperty(cx, obj, shape, desc.attributes(),
desc.getter(), desc.setter());
if (!shape)
return false;
shouldDefine = false;
if (!PurgeScopeChain(cx, obj, id))
return false;
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue(cx, obj, shape, desc.value()));
if (!CallAddPropertyHook(cx, obj, shape, desc.value()))
return false;
return result.succeed();
}
}
// Either we are converting a data property to an accessor property, or
// creating a new accessor property; either way [[Get]] and [[Set]]
// must both be filled in.
if (shouldDefine)
attrs |= JSPROP_GETTER | JSPROP_SETTER;
desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER;
} else if (desc.hasValue()) {
// If we did a normal lookup here, it would cause resolve hook recursion in
// the following case. Suppose the first script we run in a lazy global is
@ -1405,13 +1401,14 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
// If any other JSPROP_IGNORE_* attributes are present, copy the
// corresponding JSPROP_* attributes from the existing property.
if (IsImplicitDenseOrTypedArrayElement(shape)) {
attrs = ApplyAttributes(attrs, true, true, !IsAnyTypedArray(obj));
desc.setAttributes(ApplyAttributes(desc.attributes(), true, true,
!IsAnyTypedArray(obj)));
} else {
attrs = ApplyOrDefaultAttributes(attrs, shape);
desc.setAttributes(ApplyOrDefaultAttributes(desc.attributes(), shape));
// Do not redefine a nonconfigurable accessor property.
if (shape->isAccessorDescriptor()) {
if (!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
if (!CheckAccessorRedefinition(cx, obj, shape, desc))
return false;
}
}
@ -1425,11 +1422,9 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
// Don't forget about arrays.
if (IsImplicitDenseOrTypedArrayElement(shape)) {
if (IsAnyTypedArray(obj)) {
/*
* Silently ignore attempts to change individual index attributes.
* FIXME: Uses the same broken behavior as for accessors. This should
* fail.
*/
// Silently ignore attempts to change individual index attributes.
// FIXME: Uses the same broken behavior as for accessors. This should
// fail.
return result.succeed();
}
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
@ -1438,53 +1433,42 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
}
if (shape->isAccessorDescriptor() &&
!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
!CheckAccessorRedefinition(cx, obj, shape, desc))
{
return false;
}
attrs = ApplyOrDefaultAttributes(attrs, shape);
desc.setAttributes(ApplyOrDefaultAttributes(desc.attributes(), shape));
if (shape->isAccessorDescriptor() && !(attrs & JSPROP_IGNORE_READONLY)) {
if (shape->isAccessorDescriptor() && desc.hasWritable()) {
// ES6 draft 2014-10-14 9.1.6.3 step 7.c: Since [[Writable]]
// is present, change the existing accessor property to a data
// property.
updateValue = UndefinedValue();
desc.value().setUndefined();
} else {
// We are at most changing some attributes, and cannot convert
// from data descriptor to accessor, or vice versa. Take
// everything from the shape that we aren't changing.
uint32_t propMask = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
attrs = (shape->attributes() & ~propMask) | (attrs & propMask);
getter = shape->getter();
setter = shape->setter();
desc.setAttributes((shape->attributes() & ~propMask) |
(desc.attributes() & propMask));
desc.setGetter(shape->getter());
desc.setSetter(shape->setter());
if (shape->hasSlot())
updateValue = obj->getSlot(shape->slot());
desc.value().set(obj->getSlot(shape->slot()));
}
}
}
/*
* Purge the property cache of any properties named by id that are about
* to be shadowed in obj's scope chain.
*/
if (!PurgeScopeChain(cx, obj, id))
return false;
// Dispense with any remaining JSPROP_IGNORE_* attributes. Any bits that
// needed to be copied from an existing property have been copied by
// now. Since we can never get here with JSPROP_IGNORE_VALUE relevant, just
// clear it.
desc.setAttributes(ApplyOrDefaultAttributes(desc.attributes()) & ~JSPROP_IGNORE_VALUE);
if (shouldDefine) {
// Handle the default cases here. Anyone that wanted to set non-default attributes has
// cleared the IGNORE flags by now. Since we can never get here with JSPROP_IGNORE_VALUE
// relevant, just clear it.
attrs = ApplyOrDefaultAttributes(attrs) & ~JSPROP_IGNORE_VALUE;
return DefinePropertyOrElement(cx, obj, id, getter, setter,
attrs, updateValue, false, result);
}
MOZ_ASSERT(shape);
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue(cx, obj, shape, updateValue));
if (!CallAddPropertyHook(cx, obj, shape, updateValue))
// At this point, no mutation has happened yet, but all ES6 error cases
// have been dealt with.
if (!AddOrChangeProperty(cx, obj, id, desc))
return false;
return result.succeed();
}
@ -1962,6 +1946,55 @@ MaybeReportUndeclaredVarAssignment(JSContext* cx, JSString* propname)
JSMSG_UNDECLARED_VAR, bytes.ptr());
}
/*
* Finish assignment to a shapeful data property of a native object obj. This
* conforms to no standard and there is a lot of legacy baggage here.
*/
static bool
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
HandleValue v, HandleValue receiver, ObjectOpResult& result)
{
MOZ_ASSERT(obj->isNative());
MOZ_ASSERT(shape->isDataDescriptor());
if (shape->hasDefaultSetter()) {
if (shape->hasSlot()) {
// The common path. Standard data property.
// Global properties declared with 'var' will be initially
// defined with an undefined value, so don't treat the initial
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cx, shape, v, overwriting);
return result.succeed();
}
// Bizarre: shared (slotless) property that's writable but has no
// JSSetterOp. JS code can't define such a property, but it can be done
// through the JSAPI. Treat it as non-writable.
return result.fail(JSMSG_GETTER_ONLY);
}
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
uint32_t sample = cx->runtime()->propertyRemovals;
RootedId id(cx, shape->propid());
RootedValue value(cx, v);
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
return false;
// Update any slot for the shape with the value produced by the setter,
// unless the setter deleted the shape.
if (shape->hasSlot() &&
(MOZ_LIKELY(cx->runtime()->propertyRemovals == sample) ||
obj->contains(cx, shape)))
{
obj->setSlot(shape->slot(), value);
}
return true; // result is populated by CallJSSetterOp above.
}
/*
* When a [[Set]] operation finds no existing property with the given id
* or finds a writable data property on the prototype chain, we end up here.
@ -2028,13 +2061,32 @@ js::SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleId id, HandleVa
JSSetterOp setter = clasp->setProperty;
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (!receiver->is<NativeObject>())
return DefineProperty(cx, receiver, id, v, getter, setter, attrs, result);
if (!DefineProperty(cx, receiver, id, v, getter, setter, attrs, result))
return false;
// If the receiver is native, there is one more legacy wrinkle: the class
// JSSetterOp is called after defining the new property.
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, result);
if (setter && receiver->is<NativeObject>()) {
if (!result)
return true;
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
if (!cx->shouldBeJSContext())
return false;
RootedValue receiverValue(cx, ObjectValue(*receiver));
// This lookup is a bit unfortunate, but not nearly the most
// unfortunate thing about Class getters and setters. Since the above
// DefineProperty call succeeded, receiver is native, and the property
// has a setter (and thus can't be a dense element), this lookup is
// guaranteed to succeed.
RootedShape shape(cx, nativeReceiver->lookup(cx, id));
MOZ_ASSERT(shape);
return NativeSetExistingDataProperty(cx->asJSContext(), nativeReceiver, shape, v,
receiverValue, result);
}
return true;
}
// When setting |id| for |receiver| and |obj| has no property for id, continue
@ -2109,55 +2161,6 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
return result.succeed();
}
/*
* Finish assignment to a shapeful data property of a native object obj. This
* conforms to no standard and there is a lot of legacy baggage here.
*/
static bool
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
HandleValue v, HandleValue receiver, ObjectOpResult& result)
{
MOZ_ASSERT(obj->isNative());
MOZ_ASSERT(shape->isDataDescriptor());
if (shape->hasDefaultSetter()) {
if (shape->hasSlot()) {
// The common path. Standard data property.
// Global properties declared with 'var' will be initially
// defined with an undefined value, so don't treat the initial
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cx, shape, v, overwriting);
return result.succeed();
}
// Bizarre: shared (slotless) property that's writable but has no
// JSSetterOp. JS code can't define such a property, but it can be done
// through the JSAPI. Treat it as non-writable.
return result.fail(JSMSG_GETTER_ONLY);
}
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
uint32_t sample = cx->runtime()->propertyRemovals;
RootedId id(cx, shape->propid());
RootedValue value(cx, v);
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
return false;
// Update any slot for the shape with the value produced by the setter,
// unless the setter deleted the shape.
if (shape->hasSlot() &&
(MOZ_LIKELY(cx->runtime()->propertyRemovals == sample) ||
obj->contains(cx, shape)))
{
obj->setSlot(shape->slot(), value);
}
return true; // result is populated by CallJSSetterOp above.
}
/*
* Finish the assignment `receiver[id] = v` when an existing property (shape)
* has been found on a native object (pobj). This implements ES6 draft rev 32

View File

@ -1532,6 +1532,28 @@ struct JSRuntime : public JS::shadow::Runtime,
return isActive_;
}
// Some systems have non-monotonic clocks. While we cannot
// improve the precision, we can make sure that our measures
// are monotonic nevertheless. We do this by storing the
// result of the latest call to the clock and making sure
// that the next timestamp is greater or equal.
struct MonotonicTimeStamp {
MonotonicTimeStamp()
: latestGood_(0)
{}
inline uint64_t monotonize(uint64_t stamp)
{
if (stamp <= latestGood_)
return latestGood_;
latestGood_ = stamp;
return stamp;
}
private:
uint64_t latestGood_;
};
MonotonicTimeStamp systemTimeFix;
MonotonicTimeStamp userTimeFix;
private:
/**
* A map used to collapse compartments belonging to the same

View File

@ -661,32 +661,19 @@ ClonedBlockObject::copyUnaliasedValues(AbstractFramePtr frame)
}
/* static */ ClonedBlockObject*
ClonedBlockObject::clone(ExclusiveContext* cx, Handle<ClonedBlockObject*> block)
ClonedBlockObject::clone(JSContext* cx, Handle<ClonedBlockObject*> clonedBlock)
{
RootedObject enclosing(cx, &block->enclosingScope());
Rooted<StaticBlockObject*> staticBlock(cx, &clonedBlock->staticBlock());
RootedObject enclosing(cx, &clonedBlock->enclosingScope());
MOZ_ASSERT(block->getClass() == &BlockObject::class_);
RootedObjectGroup cloneGroup(cx, block->group());
RootedShape cloneShape(cx, block->lastProperty());
JSObject* obj = JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, cloneShape, cloneGroup);
if (!obj)
Rooted<ClonedBlockObject*> copy(cx, create(cx, staticBlock, enclosing));
if (!copy)
return nullptr;
ClonedBlockObject& copy = obj->as<ClonedBlockObject>();
for (uint32_t i = 0, count = staticBlock->numVariables(); i < count; i++)
copy->setVar(i, clonedBlock->var(i, DONT_CHECK_ALIASING), DONT_CHECK_ALIASING);
MOZ_ASSERT(!copy.inDictionaryMode());
MOZ_ASSERT(copy.isDelegate());
MOZ_ASSERT(block->slotSpan() == copy.slotSpan());
MOZ_ASSERT(copy.slotSpan() >= copy.numVariables() + RESERVED_SLOTS);
copy.setReservedSlot(SCOPE_CHAIN_SLOT, block->getReservedSlot(SCOPE_CHAIN_SLOT));
for (uint32_t i = 0, count = copy.numVariables(); i < count; i++)
copy.setVar(i, block->var(i, DONT_CHECK_ALIASING), DONT_CHECK_ALIASING);
return &copy;
return copy;
}
StaticBlockObject*

View File

@ -674,7 +674,7 @@ class ClonedBlockObject : public BlockObject
* Create a new ClonedBlockObject with the same enclosing scope and
* variable values as this.
*/
static ClonedBlockObject* clone(ExclusiveContext* cx, Handle<ClonedBlockObject*> block);
static ClonedBlockObject* clone(JSContext* cx, Handle<ClonedBlockObject*> block);
};
// Internal scope object used by JSOP_BINDNAME upon encountering an

View File

@ -2105,6 +2105,51 @@ js::StringIsTypedArrayIndex(const char16_t* s, size_t length, uint64_t* indexp);
template bool
js::StringIsTypedArrayIndex(const Latin1Char* s, size_t length, uint64_t* indexp);
/* ES6 draft rev 34 (2015 Feb 20) 9.4.5.3 [[DefineOwnProperty]] step 3.c. */
bool
js::DefineTypedArrayElement(JSContext *cx, HandleObject obj, uint64_t index,
Handle<PropertyDescriptor> desc, ObjectOpResult &result)
{
MOZ_ASSERT(IsAnyTypedArray(obj));
// These are all substeps of 3.c.
// Steps i-vi.
// We (wrongly) ignore out of range defines with a value.
if (index >= AnyTypedArrayLength(obj))
return result.succeed();
// Step vii.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step viii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step ix.
if (desc.hasEnumerable() && !desc.enumerable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step x.
if (desc.hasWritable() && !desc.writable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step xi.
if (desc.hasValue()) {
double d;
if (!ToNumber(cx, desc.value(), &d))
return false;
if (obj->is<TypedArrayObject>())
TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
else
SharedTypedArrayObject::setElement(obj->as<SharedTypedArrayObject>(), index, d);
}
// Step xii.
return result.succeed();
}
/* JS Friend API */
JS_FRIEND_API(bool)

View File

@ -277,6 +277,14 @@ IsTypedArrayIndex(jsid id, uint64_t* indexp)
return StringIsTypedArrayIndex(s, length, indexp);
}
/*
* Implements [[DefineOwnProperty]] for TypedArrays and SharedTypedArrays
* when the property key is a TypedArray index.
*/
bool
DefineTypedArrayElement(JSContext *cx, HandleObject arr, uint64_t index,
Handle<PropertyDescriptor> desc, ObjectOpResult &result);
static inline unsigned
TypedArrayShift(Scalar::Type viewType)
{

File diff suppressed because it is too large Load Diff

View File

@ -1937,6 +1937,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
, mHasBeenScrolledRecently(false)
, mCollapsedResizer(false)
, mShouldBuildScrollableLayer(false)
, mIsScrollableLayerInRootContainer(false)
, mHasBeenScrolled(false)
, mIsResolutionSet(false)
, mIgnoreMomentumScroll(false)
@ -2940,6 +2941,14 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// adjusted by the APZC automatically.
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
if (usingDisplayPort) {
// There is a display port for this frame, so we want to appear as having
// active scrolling, so that animated geometry roots are assigned correctly.
mShouldBuildScrollableLayer = true;
mIsScrollableLayerInRootContainer = true;
}
bool addScrollBars = mIsRoot && usingDisplayPort && !aBuilder->IsForEventDelivery();
if (addScrollBars) {
@ -3221,7 +3230,7 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
*aClipRect = scrollport;
}
if (!mShouldBuildScrollableLayer) {
if (!mShouldBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
return;
}

View File

@ -500,6 +500,12 @@ public:
// scrollable layer. Used for asynchronous scrolling.
bool mShouldBuildScrollableLayer:1;
// Whether we are the root scroll frame that is used for containerful
// scrolling with a display port. If true, the scrollable frame
// shouldn't attach frame metrics to its layers because the container
// will already have the necessary frame metrics.
bool mIsScrollableLayerInRootContainer:1;
// If true, add clipping in ScrollFrameHelper::ComputeFrameMetrics.
bool mAddClipRectToLayer:1;

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Moving the transform under the absolutely-positioned layer should cause that to invalidate</title>
<style>
.content {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid black;
}
.absolute {
position: absolute;
z-index: 2;
top: 20px;
left: 240px;
}
.reftest-no-paint {
border-color: lime;
}
.transform {
will-change: transform;
}
body {
margin: 0;
padding: 20px;
height: 3000px;
}
</style>
<div class="transform content" id="aboutToMoveUnderAbsolute">
<!--
This transform is active + prerendered, and will move under the
absolutely-positioned item.
-->
</div>
<div class="absolute reftest-no-paint content">
<!--
This absolutely-positioned element should get its own PaintedLayer above the
transform.
It shouldn't attempt to pull up an opaque background color from the page,
because the transform can move under it.
-->
</div>
<script>
function doTest() {
document.querySelector("#aboutToMoveUnderAbsolute").style.transform = "translateX(100px)";
document.documentElement.removeAttribute("class");
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrolling shouldn't invalidate the fixed layer</title>
<style>
.content {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid black;
}
.fixed {
position: fixed;
top: 20px;
left: 20px;
}
.reftest-no-paint {
border-color: lime;
}
.distanceFromTop {
margin-top: 240px;
}
body {
margin: 0;
padding: 20px;
height: 3000px;
}
</style>
<div class="distanceFromTop content">
<!--
This is just a non-uniform item that will be scrolled so that it's between
the page background and the fixed layer.
-->
</div>
<div class="fixed reftest-no-paint content">
<!--
This fixed layer gets its own PaintedLayer above the page.
It shouldn't attempt to pull up an opaque background color from the page,
because the page can move under it.
-->
</div>
<script>
function doTest() {
document.documentElement.scrollTop = 100;
document.documentElement.removeAttribute("class");
}
document.documentElement.scrollTop = 0;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrolling shouldn't invalidate the fixed items</title>
<style>
.content {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid black;
}
.fixed {
position: fixed;
top: 20px;
left: 20px;
}
.reftest-no-paint {
border-color: lime;
}
.distanceFromTop {
margin-top: 240px;
}
.clip {
width: 200px;
height: 200px;
overflow: hidden;
}
.transform {
position: relative;
will-change: transform;
}
body {
margin: 0;
padding: 20px;
height: 3000px;
}
</style>
<div class="fixed reftest-no-paint content">
<!--
This fixed layer gets its own PaintedLayer above the page.
-->
</div>
<div class="distanceFromTop clip">
<!--
This clip determines the potential pixels that can be affected by the
animated transform, *in relation to the scrolled page*. If the page
is scrolled, the clip moves relative to the fixed items, so the fixed
items need to anticipate the transform getting between them.
-->
<div class="transform content">
<!--
This is an animated transform item. It can move freely but will be
clipped by the .clip element.
-->
</div>
</div>
<div class="fixed reftest-no-paint content">
<!--
This fixed layer is above the animated transform, in z-order. The
transform is clipped in such a way that initially, the clip doesn't
intersect the fixed items, but once the page is scrolled, it does.
So this fixed item must not share a layer with the lower fixed item.
-->
</div>
<script>
function doTest() {
document.documentElement.scrollTop = 100;
document.documentElement.removeAttribute("class");
}
document.documentElement.scrollTop = 0;
document.addEventListener("MozReftestInvalidate", doTest, false);
// setTimeout(doTest, 500);
</script>

View File

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>The two items in the scroll box should share a layer, despite all the other stuff that's going on around them</title>
<style>
.content {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid blue;
background: white;
}
body {
margin: 0;
padding: 20px;
height: 3000px;
}
.opacity {
opacity: 0.9;
width: 200px;
height: 200px;
background-color: yellow;
will-change: opacity;
}
.overlap {
margin-top: -100px;
}
.scrollable {
position: absolute;
top: 20px;
left: 240px;
width: 400px;
height: 400px;
border: 1px solid black;
overflow: auto;
}
.scrollarea {
height: 800px;
padding: 40px;
}
.low-z, .mid-z, .high-z {
position: relative;
}
.low-z { z-index: 1; }
.mid-z { z-index: 2; }
.high-z { z-index: 3; }
</style>
<div class="content" reftest-assigned-layer="page-background"></div>
<div class="overlap opacity"></div>
<div class="overlap mid-z content" reftest-assigned-layer="on-top-of-opacity">
<!--
This item cannot merge into the page background layer because there's an
active container layer for the opacity in between.
-->
</div>
<div class="scrollable">
<div class="scrollarea">
<div class="low-z content" reftest-assigned-layer="scrolled-content"></div>
<div class="high-z overlap content" reftest-assigned-layer="scrolled-content"></div>
</div>
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollTop = 0;
scrollable.scrollTop = 20;
</script>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Things overlapping active scrollboxes should be in a layer on top of the scrolled contents.</title>
<style>
div {
height: 50px;
border: 1px solid;
box-model: border-box;
}
.first, .second {
border-color: blue;
margin: 50px 0;
}
.overlap {
border-color: #088;
margin-left: 100px;
width: 80px;
margin-bottom: -30px;
position: relative;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="overlap reftest-no-paint">
<!--
This item intersects with the scrollable box and is positioned above
.scrolled, in z-order, so it should be split into its own layer as soon
as the scrollbox gets active scrolling. The splitting should not wait for
.scrolled to move under .overlap.
-->
</div>
<div class="scrollable">
<div class="scrollarea">
<div class="scrolled reftest-opaque-layer">
<!--
This will move under .overlap by .scrollable being scrolled. This
action should not invalidate .overlap.
Furthermore, since the background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Things overlapping active scrollboxes should be in a layer on top of the scrolled contents, and that layer shouldn't pull up a background color through the scrollbox.</title>
<!--
This test is the same as layer-splitting-5.html, but without the scrollbox
border. The lack of a border here makes it attractive for .overlap to pull
a background color from the page background (because there's no scrollbox
border in the way), but it shouldn't do that because .scrolled can move
under it.
-->
<style>
div {
height: 50px;
border: 1px solid;
box-model: border-box;
}
.first, .second {
border-color: blue;
margin: 50px 0;
}
.overlap {
border-color: #088;
margin-left: 100px;
width: 80px;
margin-bottom: -30px;
position: relative;
}
.scrollable {
height: auto;
overflow: auto;
border: none;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="overlap reftest-no-paint">
<!--
This item intersects with the scrollable box and is positioned above
.scrolled, in z-order, so it should be split into its own layer as soon
as the scrollbox gets active scrolling. The splitting should not wait for
.scrolled to move under .overlap.
-->
</div>
<div class="scrollable">
<div class="scrollarea">
<div class="scrolled reftest-opaque-layer">
<!--
This will move under .overlap by .scrollable being scrolled. This
action should not invalidate .overlap.
Furthermore, since the background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrolling shouldn't invalidate the relatively-positioned layer</title>
<style>
.content {
box-sizing: border-box;
width: 200px;
height: 200px;
border: 1px solid black;
}
.fixed {
position: fixed;
top: 20px;
left: 20px;
}
.reftest-no-paint {
border-color: lime;
}
.distanceFromTop {
margin-top: 240px;
}
.relative {
position: relative;
}
body {
margin: 0;
padding: 20px;
height: 3000px;
}
</style>
<div class="fixed reftest-no-paint content">
<!--
This fixed layer gets its own PaintedLayer above the page.
It shouldn't attempt to pull up an opaque background color from the page,
because the page can move under it.
-->
</div>
<div class="distanceFromTop relative reftest-no-paint content">
<!--
This item is above .fixed in z-order, but it starts out not intersecting
.fixed. It should still get its own layer from the start, because it can
get scrolled on top of .fixed.
-->
</div>
<script>
function doTest() {
document.documentElement.scrollTop = 100;
document.documentElement.removeAttribute("class");
}
document.documentElement.scrollTop = 0;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -57,3 +57,10 @@ pref(layout.animated-image-layers.enabled,true) == test-animated-image-layers-ba
!= paintedlayer-recycling-7.html about:blank
!= masklayer-1.html about:blank
!= masklayer-2.html about:blank
!= layer-splitting-1.html about:blank
!= layer-splitting-2.html about:blank
!= layer-splitting-3.html about:blank
!= layer-splitting-4.html about:blank
!= layer-splitting-5.html about:blank
!= layer-splitting-6.html about:blank
!= layer-splitting-7.html about:blank

View File

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="scrollable border">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even through an opacity container layer</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: 150px;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
.opacity {
opacity: 0.9;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="opacity border">
<div class="opacity scrollable">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrollboxes with non-uniform backgrounds should prevent their contents from pulling background colors, even if those contents start out above uniform backgrounds</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrollable, in z-order.
-->
</div>
<div class="scrollable border">
<div class="scrollarea">
<div class="scrolled border reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 10;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrollboxes with non-uniform backgrounds should prevent their contents from pulling background colors, even if those contents start out above uniform backgrounds</title>
<!--
This is the same test as pull-background-3.html, but with an additional
wrapping opacity container layer.
-->
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrollable, in z-order.
-->
</div>
<div class="opacity border">
<div class="opacity scrollable">
<div class="scrollarea">
<div class="scrolled border reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 10;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if these contents are wider than the uniform area behind the scrollbox</title>
<!--
Very similar to pull-background-2.html, but with a .scrolled element that is
wider than the scrollbox.
-->
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: 150px;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 2000px;
height: 100px;
border-color: red;
}
.opacity {
opacity: 0.9;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="opacity border">
<div class="scrollable">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if these contents are wider than the uniform area behind the scrollbox</title>
<!--
Very similar to pull-background-1.html, but with a .scrolled element that is
wider than the scrollbox.
-->
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 2000px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="scrollable border">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if those contents have an animated position</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
position: relative;
}
.border {
border: 1px solid black;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
.animated-position {
position: relative;
left: 20px;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="scrollable border">
<div class="scrollarea">
<div class="scrolled border animated-position reftest-no-paint reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
var animatedLeft = document.querySelector(".animated-position");
function doTest() {
animatedLeft.style.left = "100px";
document.documentElement.removeAttribute("class");
}
// Layerize #animatedLeft
animatedLeft.offsetLeft;
animatedLeft.style.left = "40px";
animatedLeft.offsetLeft;
animatedLeft.style.left = "60px";
animatedLeft.offsetLeft;
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>

View File

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>Scrollboxes with non-uniform backgrounds should prevent their contents from pulling background colors, even if those contents start out above uniform backgrounds and have an animated position</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
position: relative;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
.animated-position {
position: relative;
left: 20px;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrollable, in z-order.
-->
</div>
<div class="scrollable border">
<div class="scrollarea">
<div class="scrolled border animated-position reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
var animatedLeft = document.querySelector(".animated-position");
function doTest() {
animatedLeft.style.left = "-40px";
document.documentElement.removeAttribute("class");
}
// Layerize #animatedLeft
animatedLeft.offsetLeft;
animatedLeft.style.left = "40px";
animatedLeft.offsetLeft;
animatedLeft.style.left = "60px";
animatedLeft.offsetLeft;
document.addEventListener("MozReftestInvalidate", doTest, false);
setTimeout(doTest, 200);
</script>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>This test fails - Layerization should respect overflow:hidden clips around things with animated position</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
position: relative;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.clip {
height: auto;
overflow: hidden;
padding: 10px 0 20px;
}
.animated-position {
position: relative;
left: 20px;
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrollable, in z-order.
-->
</div>
<div class="clip border">
<div class="border animated-position reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
However, we don't take .animated-position's clip into account when
layerizing, so .second will be pulled up into its own layer above
.animated-position. So this test will fail.
-->
</div>
<script>
var animatedLeft = document.querySelector(".animated-position");
function doTest() {
animatedLeft.style.left = "-40px";
document.documentElement.removeAttribute("class");
}
// Layerize #animatedLeft
animatedLeft.offsetLeft;
animatedLeft.style.left = "40px";
animatedLeft.offsetLeft;
animatedLeft.style.left = "60px";
animatedLeft.offsetLeft;
document.addEventListener("MozReftestInvalidate", doTest, false);
setTimeout(doTest, 200);
</script>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>This test fails - layerization should respect overflow:hidden clips around things with animated position</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
position: relative;
}
.border {
border: 1px solid black;
}
.clip {
height: auto;
overflow: hidden;
padding: 10px 0 20px;
}
.animated-position {
position: relative;
left: 20px;
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="clip border">
<div class="border animated-position reftest-no-paint reftest-opaque-layer">
<!--
The background of .clip is uniform and opaque,
.animated-position should be able to pull up that background color and
become opaque itself.
However, since this clip is not created by an animated geometry root that
is a scrollable frame, we currently fail to recognize it, so this test
will fail.
-->
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
However, since we don't recognize that .animated-position is contained in
a clip, .second gets its own layer above .animated-position, so this test
will fail.
-->
</div>
<script>
var animatedLeft = document.querySelector(".animated-position");
function doTest() {
animatedLeft.style.left = "-40px";
document.documentElement.removeAttribute("class");
}
// Layerize #animatedLeft
animatedLeft.offsetLeft;
animatedLeft.style.left = "40px";
animatedLeft.offsetLeft;
animatedLeft.style.left = "60px";
animatedLeft.offsetLeft;
document.addEventListener("MozReftestInvalidate", doTest, false);
setTimeout(doTest, 200);
</script>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait">
<meta charset="utf-8">
<title>This test fails - Opacity containers should anticipate animations of the contents when deciding whether to pull a background color</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
position: relative;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.opacity {
opacity: 0.9;
height: auto;
padding: 10px 0 20px;
}
.animated-position {
position: relative;
left: 20px;
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrollable, in z-order.
-->
</div>
<div class="border">
<div class="opacity">
<div class="border animated-position reftest-no-paint">
<!--
This item start out above solid white background but will move to
intersect .underlap, so it shouldn't pull up the background color.
However, the opacity item that wraps this item only looks at the
current bounds of its contents, so this test will fail.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var animatedLeft = document.querySelector(".animated-position");
function doTest() {
animatedLeft.style.left = "-40px";
document.documentElement.removeAttribute("class");
}
// Layerize #animatedLeft
animatedLeft.offsetLeft;
animatedLeft.style.left = "40px";
animatedLeft.offsetLeft;
animatedLeft.style.left = "60px";
animatedLeft.offsetLeft;
document.addEventListener("MozReftestInvalidate", doTest, false);
setTimeout(doTest, 200);
</script>

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if their contents have a visible region that extends beyond the scrollbox clip</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="scrollable border"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if their contents have a visible region that extends beyond the scrollbox clip, even through an opacity container layer</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: 150px;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
.opacity {
opacity: 0.9;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="opacity border">
<div class="opacity scrollable"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with non-uniform backgrounds should prevent their contents from pulling background colors, even if those contents start out above uniform backgrounds</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrolled, in z-order.
-->
</div>
<div class="scrollable border"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 10;
document.addEventListener("MozReftestInvalidate", doTest, false);
// setTimeout(doTest, 500);
</script>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en" class="reftest-wait" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with non-uniform backgrounds should prevent their contents from pulling background colors, even if those contents start out above uniform backgrounds</title>
<!--
This is the same test as pull-background-displayport-3.html, but with an additional
wrapping opacity container layer.
-->
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.underlap {
border: 1px solid #088;
margin-left: 120px;
width: 80px;
margin-bottom: -30px;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 100px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="underlap">
<!--
This item intersects with the scrollable box and is positioned below
.scrolled, in z-order.
-->
</div>
<div class="opacity border">
<div class="opacity scrollable"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-no-paint">
<!--
This box starts out above solid white background, but it will move so
that it intersects .underlap, so it shouldn't pull up a background
color to begin with so that it doesn't need to invalidate.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
function doTest() {
scrollable.scrollLeft = 100;
document.documentElement.removeAttribute("class");
}
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 10;
document.addEventListener("MozReftestInvalidate", doTest, false);
// setTimeout(doTest, 500);
</script>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="en" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if these contents are wider than the uniform area behind the scrollbox</title>
<!--
Very similar to pull-background-displayport-2.html, but with a .scrolled element that is
wider than the scrollbox.
-->
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: 150px;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 2000px;
height: 100px;
border-color: red;
}
.opacity {
opacity: 0.9;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="opacity border">
<div class="scrollable"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en" reftest-async-scroll>
<meta charset="utf-8">
<title>Scrollboxes with uniform backgrounds should pull that color into their contents, even if these contents are wider than the uniform area behind the scrollbox</title>
<style>
div {
min-height: 50px;
box-model: border-box;
}
.first, .second {
border: 1px solid blue;
margin: 50px 0;
}
.border {
border: 1px solid black;
}
.scrollable {
height: auto;
overflow: auto;
}
.scrollarea {
width: 5000px;
border: none;
padding: 10px 0 20px;
height: auto;
}
.scrolled {
margin-left: 220px;
width: 2000px;
height: 100px;
border-color: red;
}
body {
margin: 0;
padding: 0 100px;
height: 3000px;
}
</style>
<div class="first" reftest-assigned-layer="page-background">
<!--
This is just a regular box, it should end up in the page background layer.
-->
</div>
<div class="scrollable border"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="2000" reftest-displayport-h="200">
<div class="scrollarea">
<div class="scrolled border reftest-opaque-layer">
<!--
The background of .scrollable is uniform and opaque,
.scrolled should be able to pull up that background color and become
opaque itself.
-->
</div>
</div>
</div>
<div class="second" reftest-assigned-layer="page-background">
<!--
This should share a layer with .first and the page background.
-->
</div>
<script>
var scrollable = document.querySelector(".scrollable");
// Make .scrollable start out with active scrolling.
scrollable.scrollLeft = 0;
scrollable.scrollLeft = 20;
</script>

View File

@ -1,2 +1,19 @@
== move-to-background-1.html move-to-background-1-ref.html
fuzzy-if(cocoaWidget,2,6) random-if(Android&&!browserIsRemote) == component-alpha-exit-1.html component-alpha-exit-1-ref.html # bug 760275
!= pull-background-1.html about:blank
!= pull-background-2.html about:blank
!= pull-background-3.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
!= pull-background-4.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
skip-if(asyncPanZoom) != pull-background-5.html about:blank # Fails with event regions
!= pull-background-6.html about:blank
skip-if(asyncPanZoom) != pull-background-animated-position-1.html about:blank # Fails with event regions
!= pull-background-animated-position-2.html about:blank
fails != pull-background-animated-position-3.html about:blank # Fails because PaintedLayer item assignment doesn't recognize overflow:hidden clips
fails != pull-background-animated-position-4.html about:blank # Fails because PaintedLayer item assignment and background pulling don't recognize overflow:hidden clips
fails-if(!asyncPanZoom&&!Android) != pull-background-animated-position-5.html about:blank # Fails because ownLayer bounds don't anticipate changes of animated contents, but doesn't fail with event regions
skip-if(!asyncPanZoom) != pull-background-displayport-1.html about:blank
skip-if(!asyncPanZoom) != pull-background-displayport-2.html about:blank
skip-if(!asyncPanZoom) != pull-background-displayport-3.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
skip-if(!asyncPanZoom) != pull-background-displayport-4.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
fails skip-if(!asyncPanZoom) != pull-background-displayport-5.html about:blank # bug 1147673
skip-if(!asyncPanZoom) != pull-background-displayport-6.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515

View File

@ -219,7 +219,7 @@ pref(layout.css.masking.enabled,true) fuzzy-if(d2d,1,6400) == mask-type-04.svg m
== nested-viewBox-01.svg pass.svg
== nesting-invalid-01.svg nesting-invalid-01-ref.svg
fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),1,168) fuzzy-if(azureQuartz,1,122) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
fuzzy-if(Android||B2G,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
fuzzy-if(Android||B2G,1,586) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
== non-scaling-stroke-03.svg non-scaling-stroke-03-ref.svg
== objectBoundingBox-and-clipPath.svg pass.svg
# Bug 588684

View File

@ -245,7 +245,7 @@ int ConvertToI420(VideoType src_video_type,
if (src_video_type == kYV12) {
// In gralloc buffer, yv12 color format's cb and cr's strides are aligned
// to 16 Bytes boundary. See /system/core/include/system/graphics.h
int stride_y = src_width;
int stride_y = (src_width + 15) & ~0x0F;
int stride_uv = (((stride_y + 1) / 2) + 15) & ~0x0F;
return libyuv::I420Rotate(src_frame,
stride_y,

View File

@ -1332,8 +1332,10 @@ pref("network.http.spdy.default-concurrent", 100);
// alt-svc allows separation of transport routing from
// the origin host without using a proxy.
pref("network.http.altsvc.enabled", true);
pref("network.http.altsvc.oe", true);
pref("network.http.atsvc.enabled", false);
pref("network.http.atsvc.oe", false);
pref("network.http.altsvc.enabled", false);
pref("network.http.altsvc.oe", false);
pref("network.http.diagnostics", false);

View File

@ -25,8 +25,13 @@ class WebSocketChannelParent;
/**
* Class that provides an nsILoadInfo implementation.
*
* Note that there is no reason why this class should be MOZ_EXPORT, but
* Thunderbird relies on some insane hacks which require this, so we'll leave it
* as is for now, but hopefully we'll be able to remove the MOZ_EXPORT keyword
* from this class at some point. See bug 1149127 for the discussion.
*/
class LoadInfo final : public nsILoadInfo
class MOZ_EXPORT LoadInfo final : public nsILoadInfo
{
public:
NS_DECL_ISUPPORTS

View File

@ -769,7 +769,7 @@ var tests = [ test_http2_post_big
, test_http2_push2
, test_http2_push3
, test_http2_push4
, test_http2_altsvc
// , test_http2_altsvc
, test_http2_doubleheader
, test_http2_xhr
, test_http2_header

View File

@ -1,4 +1,4 @@
{
"repo": "https://hg.mozilla.org/build/mozharness",
"revision": "9c18f2f9e0c0"
"revision": "87da3e48572d"
}

View File

@ -93,8 +93,10 @@ function monotinicity_tester(source, testName) {
// Sanity check on components data.
let set = new Set();
let keys = [];
for (let item of snapshot.componentsData) {
let key = `{name: ${item.name}, addonId: ${item.addonId}}`;
let key = `{name: ${item.name}, addonId: ${item.addonId}, isSystem: ${item.isSystem}}`;
keys.push(key);
set.add(key);
sanityCheck(previous.componentsMap.get(key), item);
previous.componentsMap.set(key, item);
@ -103,13 +105,15 @@ function monotinicity_tester(source, testName) {
Assert_leq(item[k], snapshot.processData[k],
`Sanity check (${name}): component has a lower ${k} than process`);
}
for (let i = 0; i < item.durations.length; ++i) {
Assert_leq(item.durations[i], snapshot.processData.durations[i],
`Sanity check (${name}): component has a lower durations[${i}] than process.`);
}
}
// Check that we do not have duplicate components.
Assert.equal(set.size, snapshot.componentsData.length);
info(`Before deduplication, we had the following components: ${keys.sort().join(", ")}`);
info(`After deduplication, we have the following components: ${[...set.keys()].sort().join(", ")}`);
info(`Deactivating deduplication check (Bug 1150045)`);
if (false) {
Assert.equal(set.size, snapshot.componentsData.length);
}
});
let interval = window.setInterval(frameCheck, 300);
registerCleanupFunction(() => {
@ -133,11 +137,9 @@ add_task(function* test() {
info("Opening URL");
newTab.linkedBrowser.loadURI(URL);
info("Skipping monotonicity testing (1149897)");
if (false) {
monotinicity_tester(() => PerformanceStats.getSnapshot(), "parent process");
monotinicity_tester(() => promiseContentResponseOrNull(browser, "compartments-test:getStatistics", null), "content process" );
}
info("Setting up monotonicity testing");
monotinicity_tester(() => PerformanceStats.getSnapshot(), "parent process");
monotinicity_tester(() => promiseContentResponseOrNull(browser, "compartments-test:getStatistics", null), "content process" );
while (true) {
let stats = (yield promiseContentResponse(browser, "compartments-test:getStatistics", null));

View File

@ -65,16 +65,16 @@ function hasLowPrecision() {
let [sysName, sysVersion] = [Services.sysinfo.getPropertyAsAString("name"), Services.sysinfo.getPropertyAsDouble("version")];
do_print(`Running ${sysName} version ${sysVersion}`);
if (sysName != "Windows_NT") {
do_print("Not running Windows, precision should be good.");
return false;
if (sysName == "Windows_NT" && sysVersion < 6) {
do_print("Running old Windows, need to deactivate tests due to bad precision.");
return true;
}
if (sysVersion >= 6) {
do_print("Running a recent version of Windows, precision should be good.");
return false;
if (sysName == "Linux" && sysVersion <= 2.6) {
do_print("Running old Linux, need to deactivate tests due to bad precision.");
return true;
}
do_print("Running old Windows, need to deactivate tests due to bad precision.");
return true;
do_print("This platform has good precision.")
return false;
}
add_task(function* test_measure() {

View File

@ -974,6 +974,14 @@ grippy {
-moz-box-ordinal-group: 2147483646;
}
/******** scrollbar ********/
slider {
/* This is a hint to layerization that the scrollbar thumb can never leave
the scrollbar track. */
overflow: hidden;
}
/******** scrollbox ********/
scrollbox {

View File

@ -120,10 +120,10 @@ let AddonWatcher = {
let limits = {
// By default, warn if we have a total time of 1s of CPOW per 15 seconds
totalCPOWTime: Math.round(Preferences.get("browser.addon-watch.limits.totalCPOWTime", 1000) * this._interval / 15000),
totalCPOWTime: Math.round(Preferences.get("browser.addon-watch.limits.totalCPOWTime", 1000000) * this._interval / 15000),
// By default, warn if we have skipped 4 consecutive frames
// at least once during the latest slice.
longestDuration: Math.round(Math.log2(Preferences.get("browser.addon-watch.limits.longestDuration", 7))),
longestDuration: Math.round(Math.log2(Preferences.get("browser.addon-watch.limits.longestDuration", 128))),
};
for (let item of snapshot.componentsData) {

View File

@ -57,7 +57,11 @@ char* mozilla_sampler_get_profile();
JSObject *mozilla_sampler_get_profile_data(JSContext *aCx);
void mozilla_sampler_save_profile_to_file(const char* aFilename);
// Make this function easily callable from a debugger in a build without
// debugging information (work around http://llvm.org/bugs/show_bug.cgi?id=22211)
extern "C" {
void mozilla_sampler_save_profile_to_file(const char* aFilename);
}
const char** mozilla_sampler_get_features();

View File

@ -1106,7 +1106,7 @@ GfxInfo::GetGfxDriverInfo()
APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(DRIVER_OS_WINDOWS_7,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1137716),
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_BETWEEN_INCLUSIVE, V(8,7,12,5730), V(8,17,12,6901), "Nvidia driver > 8.17.12.6901");
DRIVER_BETWEEN_INCLUSIVE, V(8,17,12,5730), V(8,17,12,6901), "Nvidia driver > 8.17.12.6901");
}
return *mDriverInfo;

View File

@ -28,9 +28,6 @@ nsEnvironment::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
}
nsEnvironment* obj = new nsEnvironment();
if (!obj) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = obj->QueryInterface(aIID, aResult);
if (NS_FAILED(rv)) {

View File

@ -559,9 +559,6 @@ nsThread::DispatchInternal(nsIRunnable* aEvent, uint32_t aFlags,
nsRefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(thread, aEvent);
if (!wrapper) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = PutEvent(wrapper, aTarget);
// Don't wait for the event to finish if we didn't dispatch it...
if (NS_FAILED(rv)) {
@ -639,9 +636,6 @@ nsThread::Shutdown()
// Set mShutdownContext and wake up the thread in case it is waiting for
// events to process.
nsCOMPtr<nsIRunnable> event = new nsThreadShutdownEvent(this, &context);
if (!event) {
return NS_ERROR_OUT_OF_MEMORY;
}
// XXXroc What if posting the event fails due to OOM?
PutEvent(event, nullptr);

View File

@ -304,9 +304,6 @@ nsTimerImpl::Startup()
nsTimerEvent::Init();
gThread = new TimerThread();
if (!gThread) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(gThread);
rv = gThread->InitLocks();
@ -827,9 +824,6 @@ NS_NewTimer(nsITimer** aResult, nsTimerCallbackFunc aCallback, void* aClosure,
uint32_t aDelay, uint32_t aType)
{
nsTimerImpl* timer = new nsTimerImpl();
if (!timer) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(timer);
nsresult rv = timer->InitWithFuncCallback(aCallback, aClosure,