Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-08-20 12:42:21 -07:00
commit d8fffe1765
242 changed files with 5365 additions and 3471 deletions

View File

@ -927,8 +927,6 @@ pref("general.useragent.updates.retry", 86400); // 1 day
// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
pref("general.useragent.device_id", "");
// Make <audio> and <video> talk to the AudioChannelService.
pref("media.useAudioChannelService", true);
// Add Mozilla AudioChannel APIs.
pref("media.useAudioChannelAPI", true);

View File

@ -447,7 +447,7 @@ let gFxAccounts = {
this.openPreferences();
break;
default:
this.openAccountsPage(null, { entryPoint: "menupanel" });
this.openAccountsPage(null, { entrypoint: "menupanel" });
break;
}
@ -459,12 +459,12 @@ let gFxAccounts = {
},
openAccountsPage: function (action, urlParams={}) {
// An entryPoint param is used for server-side metrics. If the current tab
// An entrypoint param is used for server-side metrics. If the current tab
// is UITour, assume that it initiated the call to this method and override
// the entryPoint accordingly.
// the entrypoint accordingly.
if (UITour.tourBrowsersByWindow.get(window) &&
UITour.tourBrowsersByWindow.get(window).has(gBrowser.selectedBrowser)) {
urlParams.entryPoint = "uitour";
urlParams.entrypoint = "uitour";
}
let params = new URLSearchParams();
if (action) {
@ -482,7 +482,7 @@ let gFxAccounts = {
},
openSignInAgainPage: function (entryPoint) {
this.openAccountsPage("reauth", { entryPoint: entryPoint });
this.openAccountsPage("reauth", { entrypoint: entryPoint });
},
};

View File

@ -363,7 +363,6 @@ function* test_on_browser(browser) {
add_task(function*() {
yield new Promise((resolve) => {
SpecialPowers.pushPrefEnv({"set": [
["media.useAudioChannelService", true],
["browser.tabs.showAudioPlayingIcon", true],
]}, resolve);
});

View File

@ -84,7 +84,7 @@ add_task(function* test_nouser() {
Assert.ok(!panelUIFooter.hasAttribute("fxastatus"), "no fxsstatus when signed out");
Assert.ok(!panelUIFooter.hasAttribute("fxaprofileimage"), "no fxaprofileimage when signed out");
let promiseOpen = promiseTabOpen("about:accounts?entryPoint=menupanel");
let promiseOpen = promiseTabOpen("about:accounts?entrypoint=menupanel");
panelUIStatus.click();
yield promiseOpen;
});

View File

@ -211,10 +211,6 @@
- in a "receive" state. -->
<!ENTITY netmonitorUI.timings.receive "Receiving:">
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.protocol): A tooltip
- for warning icon that indicates a connection uses insecure protocol. -->
<!ENTITY netmonitorUI.security.warning.sslv3 "The protocol SSL 3.0 is deprecated and insecure.">
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.cipher): A tooltip
- for warning icon that indicates a connection uses insecure cipher suite. -->
<!ENTITY netmonitorUI.security.warning.cipher "The cipher used for encryption is deprecated and insecure.">

View File

@ -64,7 +64,7 @@ case "$target" in
kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
for version in $android_gnu_compiler_version 4.9 4.8 4.7 4.6 4.4.3; do
for version in $android_gnu_compiler_version 4.9 4.8 4.7; do
case "$target_cpu" in
arm)
target_name=arm-linux-androideabi-$version

View File

@ -19,6 +19,7 @@
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/CSPDictionariesBinding.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/URLSearchParams.h"
@ -34,6 +35,13 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
UniquePtr<URLParams> params(new URLParams());
nsAutoString value;
//
// Important: While serializing any string-valued attributes, perform a
// release-mode assertion to make sure that they don't contain characters that
// will break the quota manager when it uses the serialization for file
// naming (see addonId below).
//
if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
value.AppendInt(mAppId);
params->Set(NS_LITERAL_STRING("appId"), value);
@ -44,6 +52,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
}
if (!mAddonId.IsEmpty()) {
MOZ_RELEASE_ASSERT(mAddonId.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
params->Set(NS_LITERAL_STRING("addonId"), mAddonId);
}
@ -60,6 +69,13 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
aStr.AppendLiteral("^");
aStr.Append(NS_ConvertUTF16toUTF8(value));
}
// In debug builds, check the whole string for illegal characters too (just in case).
#ifdef DEBUG
nsAutoCString str;
str.Assign(aStr);
MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
#endif
}
namespace {

View File

@ -48,6 +48,7 @@
#include "prenv.h"
#include "nsIDOMWindow.h"
#include "nsIGlobalObject.h"
#include "nsIViewSourceChannel.h"
#include "nsIWebBrowserChrome.h"
#include "nsPoint.h"
#include "nsIObserverService.h"
@ -10395,20 +10396,18 @@ nsDocShell::DoURILoad(nsIURI* aURI,
}
if (!isSrcdoc) {
nsCOMPtr<nsILoadInfo> loadInfo =
new LoadInfo(requestingNode ? requestingNode->NodePrincipal() :
triggeringPrincipal.get(),
triggeringPrincipal,
requestingNode,
securityFlags,
aContentPolicyType,
aBaseURI);
rv = NS_NewChannelInternal(getter_AddRefs(channel),
aURI,
loadInfo,
nullptr, // loadGroup
static_cast<nsIInterfaceRequestor*>(this),
loadFlags);
requestingNode,
requestingNode
? requestingNode->NodePrincipal()
: triggeringPrincipal.get(),
triggeringPrincipal,
securityFlags,
aContentPolicyType,
nullptr, // loadGroup
static_cast<nsIInterfaceRequestor*>(this),
loadFlags);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
@ -10425,6 +10424,12 @@ nsDocShell::DoURILoad(nsIURI* aURI,
}
return rv;
}
if (aBaseURI) {
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
if (vsc) {
vsc->SetBaseURI(aBaseURI);
}
}
} else {
nsAutoCString scheme;
rv = aURI->GetScheme(scheme);
@ -10436,17 +10441,15 @@ nsDocShell::DoURILoad(nsIURI* aURI,
nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc, getter_AddRefs(channel));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadInfo> loadInfo =
new LoadInfo(requestingNode ? requestingNode->NodePrincipal() :
triggeringPrincipal.get(),
triggeringPrincipal,
requestingNode,
securityFlags,
aContentPolicyType,
aBaseURI);
channel->SetLoadInfo(loadInfo);
rv = vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc,
requestingNode,
requestingNode
? requestingNode->NodePrincipal()
: triggeringPrincipal.get(),
triggeringPrincipal,
securityFlags,
aContentPolicyType,
getter_AddRefs(channel));
} else {
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
aURI,
@ -10459,9 +10462,11 @@ nsDocShell::DoURILoad(nsIURI* aURI,
triggeringPrincipal,
securityFlags,
aContentPolicyType,
true,
aBaseURI);
true);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
MOZ_ASSERT(isc);
isc->SetBaseURI(aBaseURI);
}
}
@ -11735,7 +11740,7 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
nsCOMPtr<nsIURI> baseURI;
loadInfo->GetBaseURI(getter_AddRefs(baseURI));
inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
entry->SetBaseURI(baseURI);
}
}

View File

@ -316,7 +316,7 @@ WebappsRegistry.prototype = {
}
this.addMessageListeners(["Webapps:GetLocalizationResource:Return"]);
return this.createPromise((aResolve, aReject) => {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:GetLocalizationResource", {
manifestURL: manifestURL,
lang: aLanguage,
@ -325,10 +325,7 @@ WebappsRegistry.prototype = {
dataType: aType,
oid: this._id,
topId: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
});
},
@ -609,7 +606,7 @@ WebappsApplication.prototype = {
connect: function(aKeyword, aRules) {
this.addMessageListeners(["Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO"]);
return this.createPromise(function (aResolve, aReject) {
return this.createPromiseWithId((aResolverId) => {
let from = this._window.location.origin + this._window.location.pathname;
cpmm.sendAsyncMessage("Webapps:Connect", {
keyword: aKeyword,
@ -618,27 +615,21 @@ WebappsApplication.prototype = {
pubPageURL: from,
outerWindowID: this._id,
topWindowID: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
}.bind(this));
});
},
getConnections: function() {
this.addMessageListeners("Webapps:GetConnections:Return:OK");
return this.createPromise(function (aResolve, aReject) {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:GetConnections", {
manifestURL: this.manifestURL,
outerWindowID: this._id,
topWindowID: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
}.bind(this));
});
},
addReceipt: function(receipt) {
@ -689,22 +680,19 @@ WebappsApplication.prototype = {
export: function() {
this.addMessageListeners(["Webapps:Export:Return"]);
return this.createPromise((aResolve, aReject) => {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:Export",
{ manifestURL: this.manifestURL,
oid: this._id,
topId: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
});
},
getLocalizedValue: function(aProperty, aLang, aEntryPoint) {
this.addMessageListeners(["Webapps:GetLocalizedValue:Return"]);
return this.createPromise((aResolve, aReject) => {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:GetLocalizedValue",
{ manifestURL: this.manifestURL,
oid: this._id,
@ -712,10 +700,7 @@ WebappsApplication.prototype = {
property: aProperty,
lang: aLang,
entryPoint: aEntryPoint,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
});
},
@ -958,19 +943,16 @@ WebappsApplicationMgmt.prototype = {
},
getIcon: function(aApp, aIconID, aEntryPoint) {
return this.createPromise(function(aResolve, aReject) {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:GetIcon", {
oid: this._id,
topId: this._topId,
manifestURL: aApp.manifestURL,
iconID: aIconID,
entryPoint: aEntryPoint,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})
requestID: aResolverId
});
}.bind(this));
});
},
getNotInstalled: function() {
@ -988,29 +970,25 @@ WebappsApplicationMgmt.prototype = {
import: function(aBlob) {
let principal = this._window.document.nodePrincipal;
return this.createPromise((aResolve, aReject) => {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:Import",
{ blob: aBlob,
oid: this._id,
topId: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})}, null, principal);
requestID: aResolverId
}, null, principal);
});
},
extractManifest: function(aBlob) {
let principal = this._window.document.nodePrincipal;
return this.createPromise((aResolve, aReject) => {
return this.createPromiseWithId((aResolverId) => {
cpmm.sendAsyncMessage("Webapps:ExtractManifest",
{ blob: aBlob,
oid: this._id,
topId: this._topId,
requestID: this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
})}, null, principal);
requestID: aResolverId
}, null, principal);
});
},

View File

@ -298,6 +298,17 @@ DOMRequestIpcHelper.prototype = {
return new this._window.Promise(aPromiseInit);
},
/**
* createPromiseWithId() creates a new Promise, accepting a callback
* which is immediately called with the generated resolverId.
*/
createPromiseWithId: function(aCallback) {
return this.createPromise(function(aResolve, aReject) {
let resolverId = this.getPromiseResolverId({ resolve: aResolve, reject: aReject });
aCallback(resolverId);
}.bind(this));
},
forEachRequest: function(aCallback) {
if (!this._requests) {
return;

View File

@ -85,12 +85,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

View File

@ -30,10 +30,6 @@ var audio = new Audio();
audio.src = "audio.ogg";
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");
runTest();

View File

@ -99,7 +99,7 @@ function runTest() {
iframe.src = "data:text/html,page";
}
SpecialPowers.pushPrefEnv({ "set": [["media.useAudioChannelService", true]]}, runTest);
onload = runTest;
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -14,30 +14,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=913761
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=913761">Mozilla Bug 913761</a>
<script type="application/javascript">
function runTest() {
var transportChannel = new MessageChannel();
transportChannel.port1.onmessage = function (event) {
ok(true, 'Port Returned.');
var portToService = event.data.port;
portToService.onmessage = function (event) {
ok(true, "message received");
SimpleTest.finish();
};
portToService.postMessage('READY?');
}
var serviceChannel = new MessageChannel();
serviceChannel.port1.onmessage = function (event) {
if (event.data == 'READY?') {
this.postMessage('READY!');
}
}
transportChannel.port2.postMessage({ port: serviceChannel.port2}, [serviceChannel.port2]);
var transportChannel = new MessageChannel();
transportChannel.port1.onmessage = function (event) {
ok(true, 'Port Returned.');
var portToService = event.data.port;
portToService.onmessage = function (event) {
ok(true, "message received");
SimpleTest.finish();
};
portToService.postMessage('READY?');
}
var serviceChannel = new MessageChannel();
serviceChannel.port1.onmessage = function (event) {
if (event.data == 'READY?') {
this.postMessage('READY!');
}
}
transportChannel.port2.postMessage({ port: serviceChannel.port2}, [serviceChannel.port2]);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
</script>
</body>
</html>

View File

@ -408,6 +408,18 @@
ok(promise instanceof Promise, "Returned a Promise");
promise.then(next);
},
function() {
info("== Test createPromiseWithId()");
var _resolverId;
var promise = dummy.createPromiseWithId(function(resolverId) {
_resolverId = resolverId;
});
var resolver = dummy.getPromiseResolver(_resolverId);
ok(promise instanceof Promise, "Returned a Promise");
ok(typeof _resolverId === "string", "resolverId is a string");
ok(resolver != null, "resolverId is a valid id");
next();
},
function() {
info("== Test getResolver()");
var id;

View File

@ -107,7 +107,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=912456
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -38,10 +38,6 @@ video.onplay = video.onpause = function() {
};
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -34,10 +34,6 @@ var audio = new Audio();
audio.loop = true;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -26,10 +26,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var ac;
var tests = [
function() {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");

View File

@ -64,10 +64,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");
runTest();

View File

@ -385,7 +385,7 @@ function next() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, next);
next();
</script>
</body>
</html>

View File

@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");
runTest();

View File

@ -31,10 +31,6 @@ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
var tests = [
function() {
iframe = document.querySelector("iframe");
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
},
function() {
observerService.addObserver(observer, "audio-playback", false);
ok(true, "Observer set");
runTest();

View File

@ -9,8 +9,6 @@ SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
SpecialPowers.setBoolPref("media.useAudioChannelService", true);
function noaudio() {
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');

View File

@ -68,8 +68,4 @@ function runTest() {
iframe.src = browserElementTestHelpers.emptyPage1;
}
addEventListener('testready', () => {
// Audio channel service is needed for events
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]},
runTest);
});
addEventListener('testready', runTest);

View File

@ -47,12 +47,7 @@ function runTest() {
document.body.appendChild(iframe);
}
// This test relies on <audio> elements interacting with the audio channel
// service. This is controled by the media.useAudioChannelService pref.
addEventListener('testready', function() {
SpecialPowers.pushPrefEnv({set: [['media.useAudioChannelService', true]]},
runTest);
});
addEventListener('testready', runTest);
</script>
</body>

View File

@ -1014,7 +1014,7 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
*aColor = value.GetColorValue();
} else {
// otherwise resolve it
nsIPresShell* presShell = GetPresShell();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
nsRefPtr<nsStyleContext> parentContext;
if (mCanvasElement && mCanvasElement->IsInDoc()) {
// Inherit from the canvas element.
@ -2151,9 +2151,15 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
ErrorResult& error)
{
if (aElement && aElement->IsInDoc()) {
// inherit from the canvas element
return nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr,
presShell);
// Inherit from the canvas element.
nsRefPtr<nsStyleContext> result =
nsComputedDOMStyle::GetStyleContextForElement(aElement, nullptr,
presShell);
if (!result) {
error.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return result.forget();
}
// otherwise inherit from default (10px sans-serif)
@ -2168,7 +2174,14 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
parentRules.AppendElement(parentRule);
return presShell->StyleSet()->ResolveStyleForRules(nullptr, parentRules);
nsRefPtr<nsStyleContext> result =
presShell->StyleSet()->ResolveStyleForRules(nullptr, parentRules);
if (!result) {
error.Throw(NS_ERROR_FAILURE);
return nullptr;
}
return result.forget();
}
static bool
@ -2222,6 +2235,12 @@ GetFontStyleContext(Element* aElement, const nsAString& aFont,
return nullptr;
}
MOZ_RELEASE_ASSERT(parentContext,
"GetFontParentStyleContext should have returned an error if it couldn't get a parent context.");
MOZ_ASSERT(!presShell->IsDestroying(),
"GetFontParentStyleContext should have returned an error if the presshell is being destroyed.");
nsTArray<nsCOMPtr<nsIStyleRule>> rules;
rules.AppendElement(rule);
// add a rule to prevent text zoom from affecting the style
@ -2299,7 +2318,7 @@ CanvasRenderingContext2D::ParseFilter(const nsAString& aString,
return false;
}
nsIPresShell* presShell = GetPresShell();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!presShell) {
error.Throw(NS_ERROR_FAILURE);
return false;
@ -3034,6 +3053,13 @@ CanvasRenderingContext2D::TransformWillUpdate()
void
CanvasRenderingContext2D::SetFont(const nsAString& font,
ErrorResult& error)
{
SetFontInternal(font, error);
}
bool
CanvasRenderingContext2D::SetFontInternal(const nsAString& font,
ErrorResult& error)
{
/*
* If font is defined with relative units (e.g. ems) and the parent
@ -3046,20 +3072,20 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
if (!mCanvasElement && !mDocShell) {
NS_WARNING("Canvas element must be non-null or a docshell must be provided");
error.Throw(NS_ERROR_FAILURE);
return;
return false;
}
nsIPresShell* presShell = GetPresShell();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!presShell) {
error.Throw(NS_ERROR_FAILURE);
return;
return false;
}
nsString usedFont;
nsRefPtr<nsStyleContext> sc =
GetFontStyleContext(mCanvasElement, font, presShell, usedFont, error);
if (!sc) {
return;
return false;
}
const nsStyleFont* fontStyle = sc->StyleFont();
@ -3099,6 +3125,8 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
CurrentState().fontFont.size = fontStyle->mSize;
CurrentState().fontLanguage = fontStyle->mLanguage;
CurrentState().fontExplicitLanguage = fontStyle->mExplicitLanguage;
return true;
}
void
@ -3693,7 +3721,12 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
}
gfxFontGroup* currentFontStyle = GetCurrentFontStyle();
NS_ASSERTION(currentFontStyle, "font group is null");
if (!currentFontStyle) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(!presShell->IsDestroying(),
"GetCurrentFontStyle() should have returned null if the presshell is being destroyed");
// ensure user font set is up to date
currentFontStyle->
@ -3891,8 +3924,9 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
ErrorResult err;
NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
static float kDefaultFontSize = 10.0;
SetFont(kDefaultFontStyle, err);
if (err.Failed()) {
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
bool fontUpdated = SetFontInternal(kDefaultFontStyle, err);
if (err.Failed() || !fontUpdated) {
gfxFontStyle style;
style.size = kDefaultFontSize;
CurrentState().fontGroup =
@ -3901,9 +3935,7 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
nullptr);
if (CurrentState().fontGroup) {
CurrentState().font = kDefaultFontStyle;
nsIPresShell* presShell = GetPresShell();
if (presShell) {
if (presShell && !presShell->IsDestroying()) {
CurrentState().fontGroup->SetTextPerfMetrics(
presShell->GetPresContext()->GetTextPerfMetrics());
}
@ -3911,7 +3943,6 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
NS_ERROR("Default canvas font is invalid");
}
}
}
return CurrentState().fontGroup;

View File

@ -597,6 +597,10 @@ protected:
nsTArray<nsStyleFilter>& aFilterChain,
ErrorResult& error);
// Returns whether the font was successfully updated.
bool SetFontInternal(const nsAString& font, mozilla::ErrorResult& error);
/**
* Creates the error target, if it doesn't exist
*/
@ -631,7 +635,7 @@ protected:
*/
RenderingMode EnsureTarget(RenderingMode aRenderMode = RenderingMode::DefaultBackendMode);
/*
/**
* Disposes an old target and prepares to lazily create a new target.
*/
void ClearTarget();
@ -867,10 +871,10 @@ protected:
protected:
gfxFontGroup *GetCurrentFontStyle();
/*
* Implementation of the fillText, strokeText, and measure functions with
* the operation abstracted to a flag.
*/
/**
* Implementation of the fillText, strokeText, and measure functions with
* the operation abstracted to a flag.
*/
nsresult DrawOrMeasureText(const nsAString& text,
float x,
float y,

View File

@ -95,7 +95,7 @@ WebGLContext::ClearDepth(GLclampf v)
MakeContextCurrent();
mDepthClearValue = GLClampFloat(v);
gl->fClearDepth(v);
gl->fClearDepth(mDepthClearValue);
}
void

View File

@ -159,4 +159,4 @@ pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidV
# Check that captureStream() displays in a local video element
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
fuzzy-if(Android,3,40) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html

View File

@ -52,36 +52,30 @@ EngineeringModeAPI.prototype = {
// This returns a Promise<DOMString>
getValue: function getValue(aName) {
debug("getValue " + aName);
let promiseInit = function(resolve, reject) {
debug("promise init called for getValue " + aName);
let resolverId = this.getPromiseResolverId({resolve: resolve,
reject: reject });
debug("promise init " + resolverId);
let promiseInit = function(aResolverId) {
debug("promise init called for getValue " + aName + " has resolverId " + aResolverId);
cpmm.sendAsyncMessage("EngineeringMode:GetValue", {
requestId: resolverId,
requestId: aResolverId,
name: aName
});
}.bind(this);
return this.createPromise(promiseInit);
return this.createPromiseWithId(promiseInit);
},
// This returns a Promise<void>
setValue: function setValue(aName, aValue) {
debug("setValue " + aName + ' as ' + aValue );
let promiseInit = function(resolve, reject) {
debug("promise init called for setValue " + aName);
let resolverId = this.getPromiseResolverId({resolve: resolve,
reject: reject });
debug("promise init " + resolverId);
let promiseInit = function(aResolverId) {
debug("promise init called for getValue " + aName + " has resolverId " + aResolverId);
cpmm.sendAsyncMessage("EngineeringMode:SetValue", {
requestId: resolverId,
requestId: aResolverId,
name: aName,
value: aValue
});
}.bind(this);
return this.createPromise(promiseInit);
return this.createPromiseWithId(promiseInit);
},
set onmessage(aHandler) {

View File

@ -60,7 +60,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=848294
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>
</html>

View File

@ -135,10 +135,6 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
RegisterSwitchObserver(SWITCH_HEADPHONES, this);
}
// All of the codes below are for AudioChannel. We can directly return here
// if preferences doesn't enable AudioChannelService.
NS_ENSURE_TRUE_VOID(Preferences::GetBool("media.useAudioChannelService"));
nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
do_CreateInstance("@mozilla.org/audiochannelagent;1");
NS_ENSURE_TRUE_VOID(audioChannelAgent);

View File

@ -878,19 +878,21 @@ HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewConte
nsIntSize sz = GetWidthHeight();
nsresult rv = mCurrentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
nsresult rv = currentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = mCurrentContext->SetContextOptions(aCx, aNewContextOptions);
rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;
}
rv = mCurrentContext->SetDimensions(sz.width, sz.height);
rv = currentContext->SetDimensions(sz.width, sz.height);
if (NS_FAILED(rv)) {
mCurrentContext = nullptr;
return rv;

View File

@ -1097,11 +1097,6 @@ static bool IsAutoplayEnabled()
return Preferences::GetBool("media.autoplay.enabled");
}
static bool UseAudioChannelService()
{
return Preferences::GetBool("media.useAudioChannelService");
}
static bool UseAudioChannelAPI()
{
return Preferences::GetBool("media.useAudioChannelAPI");
@ -2411,10 +2406,6 @@ bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
bool HTMLMediaElement::CheckAudioChannelPermissions(const nsAString& aString)
{
if (!UseAudioChannelService()) {
return true;
}
// Only normal channel doesn't need permission.
if (aString.EqualsASCII("normal")) {
return true;
@ -4457,10 +4448,6 @@ ImageContainer* HTMLMediaElement::GetImageContainer()
nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
{
if (!UseAudioChannelService()) {
return NS_OK;
}
if (mAudioChannelVolume != aVolume) {
mAudioChannelVolume = aVolume;
SetVolumeInternal();
@ -4487,10 +4474,6 @@ nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
void HTMLMediaElement::UpdateAudioChannelPlayingState()
{
if (!UseAudioChannelService()) {
return;
}
bool playingThroughTheAudioChannel =
(!mPaused &&
!Muted() &&

View File

@ -394,7 +394,7 @@ MozInputMethod.prototype = {
},
removeInput: function(inputId) {
return this._sendPromise(function(resolverId) {
return this.createPromiseWithId(function(resolverId) {
let appId = this._window.document.nodePrincipal.appId;
cpmm.sendAsyncMessage('InputRegistry:Remove', {
@ -435,14 +435,6 @@ MozInputMethod.prototype = {
if (!this._isSystem) {
throw new this._window.Error("Should have 'input-manage' permssion.");
}
},
_sendPromise: function(callback) {
let self = this;
return this.createPromise(function(resolve, reject) {
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
callback(resolverId);
});
}
};
@ -786,14 +778,13 @@ MozInputContext.prototype = {
_sendPromise: function(callback) {
let self = this;
return this._ipcHelper.createPromise(function(resolve, reject) {
let resolverId = self._ipcHelper.getPromiseResolverId({ resolve: resolve, reject: reject });
return this._ipcHelper.createPromiseWithId(function(aResolverId) {
if (!WindowMap.isActive(self._window)) {
self._ipcHelper.removePromiseResolver(resolverId);
self._ipcHelper.removePromiseResolver(aResolverId);
reject('Input method is not active.');
return;
}
callback(resolverId);
callback(aResolverId);
});
}
};

View File

@ -68,7 +68,5 @@ UnsupportedHashAlg=Unsupported hash algorithm in the integrity attribute: "%1$S"
# LOCALIZATION NOTE: Do not translate "integrity"
NoValidMetadata=The integrity attribute does not contain any valid metadata.
# LOCALIZATION NOTE: Do not translate "SSL 3.0".
WeakProtocolVersionWarning=This site uses the protocol SSL 3.0 for encryption, which is deprecated and insecure.
# LOCALIZATION NOTE: Do not translate "RC4".
WeakCipherSuiteWarning=This site uses the cipher RC4 for encryption, which is deprecated and insecure.

View File

@ -26,6 +26,7 @@ public:
const nsACString& aContentType) :
mBuffer(aBuffer),
mLength(aLength),
mOffset(0),
mPrincipal(aPrincipal),
mContentType(aContentType)
{

View File

@ -105,7 +105,8 @@ UpdateStreamBlocking(MediaStream* aStream, bool aBlocking)
*/
class DecodedStreamData {
public:
DecodedStreamData(SourceMediaStream* aStream, bool aPlaying);
DecodedStreamData(SourceMediaStream* aStream, bool aPlaying,
MozPromiseHolder<GenericPromise>&& aPromise);
~DecodedStreamData();
bool IsFinished() const;
int64_t GetPosition() const;
@ -139,11 +140,10 @@ public:
// True if we need to send a compensation video frame to ensure the
// StreamTime going forward.
bool mEOSVideoCompensation;
// This promise will be resolved when the SourceMediaStream is finished.
nsRefPtr<GenericPromise> mFinishPromise;
};
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying)
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying,
MozPromiseHolder<GenericPromise>&& aPromise)
: mAudioFramesWritten(0)
, mNextVideoTime(-1)
, mNextAudioTime(-1)
@ -155,10 +155,8 @@ DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying)
, mPlaying(aPlaying)
, mEOSVideoCompensation(false)
{
MozPromiseHolder<GenericPromise> promise;
mFinishPromise = promise.Ensure(__func__);
// DecodedStreamGraphListener will resolve this promise.
mListener = new DecodedStreamGraphListener(mStream, Move(promise));
mListener = new DecodedStreamGraphListener(mStream, Move(aPromise));
mStream->AddListener(mListener);
// Block the stream if we are not playing.
@ -293,10 +291,19 @@ OutputStreamData::Remove()
mOwner->Remove(mStream);
}
MediaStreamGraph*
OutputStreamData::Graph() const
{
return mStream->Graph();
}
void
OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
// All streams must belong to the same graph.
MOZ_ASSERT(!Graph() || Graph() == aStream->Graph());
// Ensure that aStream finishes the moment mDecodedStream does.
if (aFinishWhenEnded) {
aStream->SetAutofinish(true);
@ -359,6 +366,7 @@ DecodedStream::DecodedStream(MediaQueue<MediaData>& aAudioQueue,
DecodedStream::~DecodedStream()
{
MOZ_ASSERT(mStartTime.isNothing(), "playback should've ended.");
}
nsRefPtr<GenericPromise>
@ -366,65 +374,82 @@ DecodedStream::StartPlayback(int64_t aStartTime, const MediaInfo& aInfo)
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
MOZ_ASSERT(mStartTime.isNothing(), "playback already started.");
mStartTime.emplace(aStartTime);
mInfo = aInfo;
// TODO: Unfortunately, current call flow of MDSM guarantees mData is non-null
// when StartPlayback() is called which imposes an obscure dependency on MDSM.
// We will align the life cycle of mData with {Start,Stop}Playback so that
// DecodedStream doesn't need to make assumptions about mData's life cycle.
return mData->mFinishPromise;
class R : public nsRunnable {
typedef MozPromiseHolder<GenericPromise> Promise;
typedef void(DecodedStream::*Method)(Promise&&);
public:
R(DecodedStream* aThis, Method aMethod, Promise&& aPromise)
: mThis(aThis), mMethod(aMethod)
{
mPromise = Move(aPromise);
}
NS_IMETHOD Run() override
{
(mThis->*mMethod)(Move(mPromise));
return NS_OK;
}
private:
nsRefPtr<DecodedStream> mThis;
Method mMethod;
Promise mPromise;
};
MozPromiseHolder<GenericPromise> promise;
nsRefPtr<GenericPromise> rv = promise.Ensure(__func__);
nsCOMPtr<nsIRunnable> r = new R(this, &DecodedStream::CreateData, Move(promise));
AbstractThread::MainThread()->Dispatch(r.forget());
return rv.forget();
}
void DecodedStream::StopPlayback()
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
// Playback didn't even start at all.
if (mStartTime.isNothing()) {
return;
}
mStartTime.reset();
}
void
DecodedStream::DestroyData()
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
// Avoid the redundant blocking to output stream.
if (!mData) {
// Clear mData immediately when this playback session ends so we won't
// send data to the wrong stream in SendData() in next playback session.
DecodedStreamData* data = mData.release();
// mData is not yet created on the main thread.
if (!data) {
return;
}
mOutputStreamManager.Disconnect();
mData = nullptr;
}
void
DecodedStream::RecreateData()
{
nsRefPtr<DecodedStream> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void {
self->RecreateData(nullptr);
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
self->mOutputStreamManager.Disconnect();
delete data;
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
void
DecodedStream::RecreateData(MediaStreamGraph* aGraph)
DecodedStream::CreateData(MozPromiseHolder<GenericPromise>&& aPromise)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
MOZ_ASSERT((aGraph && !mData && !HasConsumers()) || // first time
(!aGraph && mData)); // 2nd time and later
MOZ_ASSERT(!mData, "Already created.");
if (!aGraph) {
aGraph = mData->mStream->Graph();
// No need to create a source stream when there are no output streams. This
// happens when RemoveOutput() is called immediately after StartPlayback().
// We also bail out when the playback session has ended. This happens when
// StopPlayback() is called immediately after StartPlayback().
if (!mOutputStreamManager.Graph() || mStartTime.isNothing()) {
// Resolve the promise to indicate the end of playback.
aPromise.Resolve(true, __func__);
return;
}
auto source = aGraph->CreateSourceStream(nullptr);
DestroyData();
mData.reset(new DecodedStreamData(source, mPlaying));
// Note that the delay between removing ports in DestroyData
// and adding new ones won't cause a glitch since all graph operations
// between main-thread stable states take effect atomically.
auto source = mOutputStreamManager.Graph()->CreateSourceStream(nullptr);
mData.reset(new DecodedStreamData(source, mPlaying, Move(aPromise)));
mOutputStreamManager.Connect(mData->mStream);
}
@ -441,20 +466,13 @@ DecodedStream::GetReentrantMonitor() const
}
void
DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
DecodedStream::AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (!mData) {
RecreateData(aStream->Graph());
}
mOutputStreamManager.Add(aStream, aFinishWhenEnded);
}
void
DecodedStream::Remove(MediaStream* aStream)
DecodedStream::RemoveOutput(MediaStream* aStream)
{
mOutputStreamManager.Remove(aStream);
}
@ -736,6 +754,11 @@ DecodedStream::SendData()
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
MOZ_ASSERT(mStartTime.isSome(), "Must be called after StartPlayback()");
// Not yet created on the main thread. MDSM will try again later.
if (!mData) {
return;
}
// Nothing to do when the stream is finished.
if (mData->mHaveSentFinish) {
return;
@ -759,7 +782,7 @@ int64_t
DecodedStream::AudioEndTime() const
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (mStartTime.isSome() && mInfo.HasAudio()) {
if (mStartTime.isSome() && mInfo.HasAudio() && mData) {
CheckedInt64 t = mStartTime.ref() +
FramesToUsecs(mData->mAudioFramesWritten, mInfo.mAudio.mRate);
if (t.isValid()) {
@ -776,14 +799,14 @@ DecodedStream::GetPosition() const
// This is only called after MDSM starts playback. So mStartTime is
// guaranteed to be something.
MOZ_ASSERT(mStartTime.isSome());
return mStartTime.ref() + mData->GetPosition();
return mStartTime.ref() + (mData ? mData->GetPosition() : 0);
}
bool
DecodedStream::IsFinished() const
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
return mData->IsFinished();
return mData && mData->IsFinished();
}
} // namespace mozilla

View File

@ -56,6 +56,8 @@ public:
{
return mStream == aStream;
}
// Return the graph mStream belongs to.
MediaStreamGraph* Graph() const;
private:
OutputStreamManager* mOwner;
@ -81,6 +83,12 @@ public:
void Connect(MediaStream* aStream);
// Disconnect all output streams from the input stream.
void Disconnect();
// Return the graph these streams belong to or null if empty.
MediaStreamGraph* Graph() const
{
MOZ_ASSERT(NS_IsMainThread());
return !IsEmpty() ? mStreams[0].Graph() : nullptr;
}
private:
// Keep the input stream so we can connect the output streams that
@ -105,10 +113,8 @@ public:
// Mimic MDSM::StopAudioThread.
void StopPlayback();
void DestroyData();
void RecreateData();
void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
void Remove(MediaStream* aStream);
void AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
void RemoveOutput(MediaStream* aStream);
void SetPlaying(bool aPlaying);
void SetVolume(double aVolume);
@ -126,7 +132,7 @@ protected:
private:
ReentrantMonitor& GetReentrantMonitor() const;
void RecreateData(MediaStreamGraph* aGraph);
void CreateData(MozPromiseHolder<GenericPromise>&& aPromise);
void InitTracks();
void AdvanceTracks();
void SendAudio(double aVolume, bool aIsSameOrigin);

View File

@ -386,7 +386,9 @@ void MediaDecoderStateMachine::SendStreamData()
// keep decoding audio samples till the end and consume a lot of memory.
// Therefore we only discard those behind the stream clock to throttle
// the decoding speed.
if (a && a->mTime <= clockTime) {
// Note we don't discard a sample when |a->mTime == clockTime| because that
// will discard the 1st sample when clockTime is still 0.
if (a && a->mTime < clockTime) {
nsRefPtr<MediaData> releaseMe = AudioQueue().PopFront();
continue;
}
@ -1552,10 +1554,6 @@ MediaDecoderStateMachine::InitiateSeek()
"Can only seek in range [0,duration]");
mCurrentSeek.mTarget.mTime = seekTime;
if (mAudioCaptured) {
mDecodedStream->RecreateData();
}
mDropAudioUntilNextDiscontinuity = HasAudio();
mDropVideoUntilNextDiscontinuity = HasVideo();
mCurrentTimeBeforeSeek = GetMediaTime();
@ -3173,7 +3171,7 @@ void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
mDecodedStream->Connect(aStream, aFinishWhenEnded);
mDecodedStream->AddOutput(aStream, aFinishWhenEnded);
DispatchAudioCaptured();
}
@ -3181,7 +3179,7 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
{
MOZ_ASSERT(NS_IsMainThread());
DECODER_LOG("RemoveOutputStream=%p!", aStream);
mDecodedStream->Remove(aStream);
mDecodedStream->RemoveOutput(aStream);
if (!mDecodedStream->HasConsumers()) {
DispatchAudioUncaptured();
}

View File

@ -319,7 +319,6 @@ public:
if (mReader) {
mReader->BreakCycles();
}
mDecodedStream->DestroyData();
mResource = nullptr;
mDecoder = nullptr;
}

View File

@ -683,26 +683,22 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
tags=msg capturestream
[test_mediarecorder_record_no_timeslice.html]
tags=msg capturestream
skip-if = toolkit == 'gonk' && debug
[test_mediarecorder_record_nosrc.html]
tags=msg capturestream
[test_mediarecorder_record_session.html]
tags=msg capturestream
[test_mediarecorder_record_startstopstart.html]
tags=msg
skip-if = toolkit == 'gonk' && debug
[test_mediarecorder_record_stopms.html]
tags=msg
[test_mediarecorder_record_timeslice.html]
tags=msg capturestream
skip-if = toolkit == 'gonk' && debug
[test_mediarecorder_reload_crash.html]
tags=msg capturestream
[test_mediarecorder_unsupported_src.html]
tags=msg
[test_mediarecorder_record_getdata_afterstart.html]
tags=msg capturestream
skip-if = toolkit == 'gonk' && debug
[test_mediatrack_consuming_mediaresource.html]
[test_mediatrack_consuming_mediastream.html]
tags=msg

View File

@ -235,7 +235,6 @@ function setupEnvironment() {
SpecialPowers.pushPrefEnv({
'set': [
['canvas.capturestream.enabled', true],
['dom.messageChannel.enabled', true],
['media.peerconnection.enabled', true],
['media.peerconnection.identity.enabled', true],
['media.peerconnection.identity.timeout', 120000],
@ -246,7 +245,6 @@ function setupEnvironment() {
['media.getusermedia.screensharing.enabled', true],
['media.getusermedia.screensharing.allowed_domains', "mochi.test"],
['media.getusermedia.audiocapture.enabled', true],
['media.useAudioChannelService', true],
['media.recorder.audio_node.enabled', true]
]
}, setTestOptions);

View File

@ -105,8 +105,7 @@ function testMultipleFingerprints() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
set: [ [ 'dom.messageChannel.enabled', true ],
[ 'media.peerconnection.identity.enabled', true ] ]
set: [ [ 'media.peerconnection.identity.enabled', true ] ]
}, testMultipleFingerprints);
</script>
</body>

View File

@ -162,9 +162,7 @@ function run_all_tests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
set: [ [ 'dom.messageChannel.enabled', true ] ]
}, run_all_tests);
run_all_tests();
</script>
</body>
</html>

View File

@ -305,11 +305,6 @@ private:
bool mSuspended;
};
static bool UseAudioChannelService()
{
return Preferences::GetBool("media.useAudioChannelService");
}
static bool UseAudioChannelAPI()
{
return Preferences::GetBool("media.useAudioChannelAPI");
@ -597,10 +592,6 @@ AudioDestinationNode::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& a
bool
AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
{
if (!UseAudioChannelService()) {
return true;
}
// Only normal channel doesn't need permission.
if (aValue == AudioChannel::Normal) {
return true;
@ -636,7 +627,7 @@ AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
void
AudioDestinationNode::CreateAudioChannelAgent()
{
if (mIsOffline || !UseAudioChannelService()) {
if (mIsOffline) {
return;
}

View File

@ -141,8 +141,7 @@ function runTest() {
test();
}
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true ],
["media.useAudioChannelService", true ]]}, runTest);
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true ]]}, runTest);
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);

View File

@ -6,7 +6,6 @@
#include "MessageChannel.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/MessageChannelBinding.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/Navigator.h"
@ -30,149 +29,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
namespace {
bool gPrefInitialized = false;
bool gPrefEnabled = false;
bool
CheckPermission(nsIPrincipal* aPrincipal, bool aCallerChrome)
{
MOZ_ASSERT(NS_IsMainThread());
if (!gPrefInitialized) {
Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
gPrefInitialized = true;
}
// Enabled by pref
if (gPrefEnabled) {
return true;
}
// Chrome callers are allowed.
if (aCallerChrome) {
return true;
}
nsCOMPtr<nsIURI> uri;
if (NS_FAILED(aPrincipal->GetURI(getter_AddRefs(uri))) || !uri) {
return false;
}
bool isResource = false;
if (NS_FAILED(uri->SchemeIs("resource", &isResource))) {
return false;
}
return isResource;
}
nsIPrincipal*
GetPrincipalFromWorkerPrivate(workers::WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(NS_IsMainThread());
nsIPrincipal* principal = aWorkerPrivate->GetPrincipal();
if (principal) {
return principal;
}
// Walk up to our containing page
workers::WorkerPrivate* wp = aWorkerPrivate;
while (wp->GetParent()) {
wp = wp->GetParent();
}
nsPIDOMWindow* window = wp->GetWindow();
if (!window) {
return nullptr;
}
nsIDocument* doc = window->GetExtantDoc();
if (!doc) {
return nullptr;
}
return doc->NodePrincipal();
}
// A WorkerMainThreadRunnable to synchronously dispatch the call of
// CheckPermission() from the worker thread to the main thread.
class CheckPermissionRunnable final : public workers::WorkerMainThreadRunnable
{
public:
bool mResult;
bool mCallerChrome;
explicit CheckPermissionRunnable(workers::WorkerPrivate* aWorkerPrivate)
: workers::WorkerMainThreadRunnable(aWorkerPrivate)
, mResult(false)
, mCallerChrome(false)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
mCallerChrome = aWorkerPrivate->UsesSystemPrincipal();
}
protected:
virtual bool
MainThreadRun() override
{
MOZ_ASSERT(NS_IsMainThread());
nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
if (!principal) {
return true;
}
bool isNullPrincipal;
nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
if (NS_WARN_IF(isNullPrincipal)) {
return true;
}
mResult = CheckPermission(principal, mCallerChrome);
return true;
}
};
} // namespace
/* static */ bool
MessageChannel::Enabled(JSContext* aCx, JSObject* aGlobal)
{
if (NS_IsMainThread()) {
JS::Rooted<JSObject*> global(aCx, aGlobal);
nsCOMPtr<nsPIDOMWindow> win = Navigator::GetWindowFromGlobal(global);
if (!win) {
return false;
}
nsIDocument* doc = win->GetExtantDoc();
if (!doc) {
return false;
}
return CheckPermission(doc->NodePrincipal(),
nsContentUtils::IsCallerChrome());
}
workers::WorkerPrivate* workerPrivate =
workers::GetWorkerPrivateFromContext(aCx);
workerPrivate->AssertIsOnWorkerThread();
nsRefPtr<CheckPermissionRunnable> runnable =
new CheckPermissionRunnable(workerPrivate);
runnable->Dispatch(aCx);
return runnable->mResult;
}
MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
{

View File

@ -28,9 +28,6 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
static bool Enabled(JSContext* aCx, JSObject* aGlobal);
public:
nsPIDOMWindow*
GetParentObject() const
{

View File

@ -14,7 +14,6 @@ support-files =
[test_messageChannel_cloning.html]
[test_messageChannel_pingpong.html]
[test_messageChannel_post.html]
[test_messageChannel_pref.html]
[test_messageChannel_start.html]
[test_messageChannel_transferable.html]
[test_messageChannel_unshipped.html]

View File

@ -21,29 +21,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
</pre>
<script type="application/javascript">
function runTest() {
/** Test for Bug 677638 **/
var a = new MessageChannel();
ok(a, "MessageChannel created");
/** Test for Bug 677638 **/
var a = new MessageChannel();
ok(a, "MessageChannel created");
var port1 = a.port1;
ok(port1, "MessageChannel.port1 exists");
is(port1, a.port1, "MessageChannel.port1 is port1");
var port1 = a.port1;
ok(port1, "MessageChannel.port1 exists");
is(port1, a.port1, "MessageChannel.port1 is port1");
var port2 = a.port2;
ok(port2, "MessageChannel.port1 exists");
is(port2, a.port2, "MessageChannel.port2 is port2");
var port2 = a.port2;
ok(port2, "MessageChannel.port1 exists");
is(port2, a.port2, "MessageChannel.port2 is port2");
[ 'postMessage', 'start', 'close' ].forEach(function(e) {
ok(e in port1, "MessagePort1." + e + " exists");
ok(e in port2, "MessagePort2." + e + " exists");
});
[ 'postMessage', 'start', 'close' ].forEach(function(e) {
ok(e in port1, "MessagePort1." + e + " exists");
ok(e in port2, "MessagePort2." + e + " exists");
});
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
</script>
</body>
</html>

View File

@ -109,7 +109,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>
</html>

View File

@ -32,7 +32,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1178076
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>
</html>

View File

@ -64,7 +64,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>
</html>

View File

@ -16,21 +16,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1176034
</pre>
<script type="application/javascript">
function runTests() {
var mc = new MessageChannel();
var mc = new MessageChannel();
try {
postMessage(42, "*", [ mc.port1, window ]);
ok(false, "Something went wrong.");
} catch(e) {
ok(true, "PostMessage should fail and we should not leak.");
}
SimpleTest.finish();
try {
postMessage(42, "*", [ mc.port1, window ]);
ok(false, "Something went wrong.");
} catch(e) {
ok(true, "PostMessage should fail and we should not leak.");
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
</script>
</body>
</html>

View File

@ -71,7 +71,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>
</html>

View File

@ -70,7 +70,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, start);
start();
</script>
</body>
</html>

View File

@ -1,42 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 677638 - pref</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
<div id="content"></div>
<pre id="test">
</pre>
<script type="application/javascript">
function runTest(what) {
var status;
try {
status = MessageChannel;
ok(what, "Should MessageChannel exist?");
} catch(e) {
ok(!what, "Should MessageChannel exist?");
}
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", false]]},
function() {
runTest(false);
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]},
function() {
runTest(true);
SimpleTest.finish();
});
});
</script>
</body>
</html>

View File

@ -16,7 +16,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
</pre>
<script type="application/javascript">
function runTest() {
var a = new MessageChannel();
var status = false;
@ -27,11 +26,7 @@ function runTest() {
}
ok(status, "Transfering the same port should throw");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
</script>
</body>
</html>

View File

@ -20,19 +20,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
</pre>
<script type="application/javascript">
function runTest() {
var a = new SharedWorker('sharedWorker_messageChannel.js');
a.port.onmessage = function(evt) {
is(evt.ports.length, 1, "We received a port.");
evt.ports[0].onmessage = function(e) {
is(e.data, 42, "Message reiceved back!");
SimpleTest.finish();
}
evt.ports[0].postMessage(42);
var a = new SharedWorker('sharedWorker_messageChannel.js');
a.port.onmessage = function(evt) {
is(evt.ports.length, 1, "We received a port.");
evt.ports[0].onmessage = function(e) {
is(e.data, 42, "Message reiceved back!");
SimpleTest.finish();
}
evt.ports[0].postMessage(42);
}
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -15,22 +15,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
<script type="application/javascript">
function runTest() {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', "iframe_messageChannel_sharedWorker2.html");
document.getElementById('content').appendChild(iframe);
var iframe = document.createElement('iframe');
iframe.setAttribute('src', "iframe_messageChannel_sharedWorker2.html");
document.getElementById('content').appendChild(iframe);
var a = new SharedWorker('sharedWorker2_messageChannel.js');
a.port.onmessage = function(evt) {
is(evt.ports.length, 1, "We received a port.");
evt.ports[0].onmessage = function(e) {
is(e.data, "Hello from the iframe!", "Message reiceved from the iframe!");
SimpleTest.finish();
}
var a = new SharedWorker('sharedWorker2_messageChannel.js');
a.port.onmessage = function(evt) {
is(evt.ports.length, 1, "We received a port.");
evt.ports[0].onmessage = function(e) {
is(e.data, "Hello from the iframe!", "Message reiceved from the iframe!");
SimpleTest.finish();
}
}
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
SimpleTest.waitForExplicitFinish();
</script>
</body>

View File

@ -229,7 +229,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
runTests();
</script>
</body>
</html>

View File

@ -105,7 +105,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
runTests();
</script>
</body>
</html>

View File

@ -117,7 +117,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
runTests();
</script>
</body>
</html>

View File

@ -54,7 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
runTests();
</script>
</body>
</html>

View File

@ -37,11 +37,8 @@ NfcCallback.prototype = {
_requestId: null,
_createPromise: function _createPromise() {
this.promise = this.createPromise((aResolve, aReject) => {
this._requestId = btoa(this.getPromiseResolverId({
resolve: aResolve,
reject: aReject
}));
this.promise = this.createPromiseWithId((aResolverId) => {
this._requestId = btoa(aResolverId);
});
},

View File

@ -104,10 +104,9 @@ PresentationDeviceInfoManager.prototype = {
getAll: function() {
log("getAll");
let self = this;
return this.createPromise(function(aResolve, aReject) {
let resolverId = self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
return this.createPromiseWithId(function(aResolverId) {
cpmm.sendAsyncMessage("PresentationDeviceInfoManager:GetAll", {
requestId: resolverId,
requestId: aResolverId,
});
});
},

View File

@ -92,6 +92,12 @@ namespace mozilla {
namespace dom {
namespace quota {
// We want profiles to be platform-independent so we always need to replace
// the same characters on every platform. Windows has the most extensive set
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
// FILE_PATH_SEPARATOR.
const char QuotaManager::kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
namespace {
/*******************************************************************************
@ -1075,19 +1081,14 @@ public:
void
SanitizeOriginString(nsCString& aOrigin)
{
// We want profiles to be platform-independent so we always need to replace
// the same characters on every platform. Windows has the most extensive set
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
// FILE_PATH_SEPARATOR.
static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
#ifdef XP_WIN
NS_ASSERTION(!strcmp(kReplaceChars,
NS_ASSERTION(!strcmp(QuotaManager::kReplaceChars,
FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR),
"Illegal file characters have changed!");
#endif
aOrigin.ReplaceChar(kReplaceChars, '+');
aOrigin.ReplaceChar(QuotaManager::kReplaceChars, '+');
}
bool

View File

@ -124,6 +124,8 @@ public:
NS_DECL_NSIQUOTAMANAGER
NS_DECL_NSIOBSERVER
static const char kReplaceChars[];
// Returns a non-owning reference.
static QuotaManager*
GetOrCreate();

View File

@ -46,9 +46,8 @@ RequestSyncManager.prototype = {
sendMessage: function(aMsg, aObj) {
let self = this;
return this.createPromise(function(aResolve, aReject) {
aObj.requestID =
self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
return this.createPromiseWithId(function(aResolverId) {
aObj.requestID = aResolverId;
cpmm.sendAsyncMessage(aMsg, aObj, null,
self._window.document.nodePrincipal);
});

View File

@ -68,9 +68,8 @@ RequestSyncScheduler.prototype = {
sendMessage: function(aMsg, aObj) {
let self = this;
return this.createPromise(function(aResolve, aReject) {
aObj.requestID =
self.getPromiseResolverId({ resolve: aResolve, reject: aReject });
return this.createPromiseWithId(function(aResolverId) {
aObj.requestID = aResolverId;
cpmm.sendAsyncMessage(aMsg, aObj, null,
self._window.document.nodePrincipal);
});

View File

@ -146,18 +146,6 @@ function ResourceStatsManager() {
ResourceStatsManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_getPromise: function(aCallback) {
let self = this;
return this.createPromise(function(aResolve, aReject) {
let resolverId = self.getPromiseResolverId({
resolve: aResolve,
reject: aReject
});
aCallback(resolverId);
});
},
// Check time range.
_checkTimeRange: function(aStart, aEnd) {
if (DEBUG) {
@ -180,7 +168,7 @@ ResourceStatsManager.prototype = {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:GetStats", {
resolverId: aResolverId,
type: self.type,
@ -198,7 +186,7 @@ ResourceStatsManager.prototype = {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:ClearStats", {
resolverId: aResolverId,
type: self.type,
@ -213,7 +201,7 @@ ResourceStatsManager.prototype = {
clearAllStats: function() {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:ClearAllStats", {
resolverId: aResolverId,
type: self.type,
@ -239,7 +227,7 @@ ResourceStatsManager.prototype = {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:AddAlarm", {
resolverId: aResolverId,
type: self.type,
@ -255,7 +243,7 @@ ResourceStatsManager.prototype = {
getAlarms: function(aStatsOptions) {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:GetAlarms", {
resolverId: aResolverId,
type: self.type,
@ -268,7 +256,7 @@ ResourceStatsManager.prototype = {
removeAlarm: function(aAlarmId) {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:RemoveAlarm", {
resolverId: aResolverId,
type: self.type,
@ -281,7 +269,7 @@ ResourceStatsManager.prototype = {
removeAllAlarms: function() {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:RemoveAllAlarms", {
resolverId: aResolverId,
type: self.type,
@ -293,7 +281,7 @@ ResourceStatsManager.prototype = {
getAvailableComponents: function() {
// Create Promise.
let self = this;
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.cpmm.sendAsyncMessage("ResourceStats:GetComponents", {
resolverId: aResolverId,
type: self.type,

View File

@ -62,12 +62,8 @@ PromiseHelpersSubclass.prototype = {
callback(resolverId);
};
return this.createPromise((resolve, reject) => {
let resolverId = this.getPromiseResolverId({
resolve: resolve,
reject: reject
});
ctxCallback(resolverId);
return this.createPromiseWithId((aResolverId) => {
ctxCallback(aResolverId);
});
},

View File

@ -225,7 +225,7 @@ SystemUpdateManager.prototype = {
},
getProviders: function() {
return this._sendPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
cpmm.sendAsyncMessage("SystemUpdate:GetProviders", {
requestId: aResolverId,
});
@ -233,7 +233,7 @@ SystemUpdateManager.prototype = {
},
getActiveProvider: function() {
return this._sendPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
cpmm.sendAsyncMessage("SystemUpdate:GetActiveProvider", {
requestId: aResolverId,
});
@ -241,21 +241,12 @@ SystemUpdateManager.prototype = {
},
setActiveProvider: function(aUuid) {
return this._sendPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
cpmm.sendAsyncMessage("SystemUpdate:SetActiveProvider", {
requestId: aResolverId,
uuid: aUuid
});
});
},
_sendPromise: function(aCallback) {
let self = this;
return this.createPromise(function(aResolve, aReject) {
let resolverId = self.getPromiseResolverId({resolve: aResolve,
reject: aReject});
aCallback(resolverId);
});
}
};

View File

@ -40,19 +40,6 @@ TetheringManager.prototype = {
this.initDOMRequestHelper(aWindow, messages);
},
_getPromise: function(aCallback) {
let self = this;
return this.createPromise(function(aResolve, aReject) {
let resolverId = self.getPromiseResolverId({
resolve: aResolve,
reject: aReject
});
aCallback(resolverId);
});
},
// TODO : aMessage format may be different after supporting bt/usb.
// for now, use wifi format first.
receiveMessage: function(aMessage) {
@ -77,7 +64,7 @@ TetheringManager.prototype = {
let self = this;
switch (aType) {
case TETHERING_TYPE_WIFI:
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
let data = { resolverId: aResolverId, enabled: aEnabled, config: aConfig };
cpmm.sendAsyncMessage("WifiManager:setWifiTethering", { data: data});
});
@ -85,7 +72,7 @@ TetheringManager.prototype = {
case TETHERING_TYPE_USB:
default:
debug("tethering type(" + aType + ") doesn't support");
return this._getPromise(function(aResolverId) {
return this.createPromiseWithId(function(aResolverId) {
self.takePromiseResolver(aResolverId).reject();
});
}

View File

@ -7,8 +7,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
*/
[Constructor, Func="MessageChannel::Enabled",
Exposed=(Window,Worker)]
[Constructor, Exposed=(Window,Worker)]
interface MessageChannel {
readonly attribute MessagePort port1;
readonly attribute MessagePort port2;

View File

@ -202,7 +202,6 @@
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.interception.enabled", true],
["dom.messageChannel.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.testing.enabled", true],

View File

@ -1,9 +1,9 @@
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == empty-1.xul empty-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != empty-2.xul empty-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
# There is no way to simulate an autocomplete textbox in windows XP/Vista/7 default theme using CSS.
# There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
# Therefore, the equlity tests below should be marked as failing.
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == autocomplete-1.xul autocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == autocomplete-1.xul autocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != emptymultiline-1.xul emptymultiline-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-1.xul emptytextbox-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
@ -15,10 +15,10 @@ fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-5.
# Therefore, the equlity tests below should be marked as failing.
skip-if((B2G&&browserIsRemote)||Mulet) != number-1.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != number-2.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-3.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-3.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != number-4.xul number-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-5.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-5.xul number-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == passwd-1.xul passwd-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == passwd-2.xul passwd-ref.xul # bug 783658 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != passwd-3.xul passwd-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
@ -26,4 +26,4 @@ fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == plain-1.xul pla
fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == textbox-1.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) != textbox-disabled.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
# Read-only textboxes look like normal textboxes in windows Vista/7 default theme
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x206\.[012]/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) != textbox-readonly.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) != textbox-readonly.xul textbox-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -2083,9 +2083,9 @@ UpdatePluginWindowState(uint64_t aId)
bool shouldComposePlugin = !!lts.mRoot &&
!!lts.mRoot->GetParent();
bool shouldHidePlugin = (!lts.mRoot ||
!lts.mRoot->GetParent()) &&
!lts.mUpdatedPluginDataAvailable;
bool shouldHidePlugin = !lts.mRoot ||
!lts.mRoot->GetParent();
if (shouldComposePlugin) {
if (!lts.mPluginData.Length()) {
// We will pass through here in cases where the previous shadow layer

View File

@ -188,7 +188,10 @@ static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
InfallibleTArray<PTextureChild*> textures;
sImageBridgeChildSingleton->ManagedPTextureChild(textures);
for (int i = textures.Length() - 1; i >= 0; --i) {
TextureClient::AsTextureClient(textures[i])->ForceRemove();
TextureClient* client = TextureClient::AsTextureClient(textures[i]);
if (client) {
client->ForceRemove();
}
}
sImageBridgeChildSingleton->SendWillStop();
sImageBridgeChildSingleton->MarkShutDown();

View File

@ -27,6 +27,35 @@ TEST(GfxWidgets, Split) {
ASSERT_TRUE(SplitDriverVersion("25.4.0.8", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
ASSERT_TRUE(SplitDriverVersion("424.143.84437.3", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8443 && atoi(dStr) == 3);
ASSERT_FALSE(SplitDriverVersion("25.4.0.8.", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
ASSERT_TRUE(SplitDriverVersion("424.143.8.3143243", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8 && atoi(dStr) == 3143);
ASSERT_FALSE(SplitDriverVersion("25.4.0.8..", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
ASSERT_FALSE(SplitDriverVersion("424.143.8.3143243.", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 424 && atoi(bStr) == 143 && atoi(cStr) == 8 && atoi(dStr) == 3143);
ASSERT_FALSE(SplitDriverVersion("25.4.0.8.13", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
ASSERT_FALSE(SplitDriverVersion("4.1.8.13.24.35", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 4 && atoi(bStr) == 1 && atoi(cStr) == 8 && atoi(dStr) == 13);
ASSERT_TRUE(SplitDriverVersion("28...74", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 28 && atoi(bStr) == 0 && atoi(cStr) == 0 && atoi(dStr) == 74);
ASSERT_FALSE(SplitDriverVersion("4.1.8.13.24.35", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 4 && atoi(bStr) == 1 && atoi(cStr) == 8 && atoi(dStr) == 13);
ASSERT_TRUE(SplitDriverVersion("35..42.0", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 35 && atoi(bStr) == 0 && atoi(cStr) == 42 && atoi(dStr) == 0);
}
TEST(GfxWidgets, Versioning) {

View File

@ -90,15 +90,18 @@ Decoder::Init()
}
nsresult
Decoder::Decode()
Decoder::Decode(IResumable* aOnResume)
{
MOZ_ASSERT(mInitialized, "Should be initialized here");
MOZ_ASSERT(mIterator, "Should have a SourceBufferIterator");
// If no IResumable was provided, default to |this|.
IResumable* onResume = aOnResume ? aOnResume : this;
// We keep decoding chunks until the decode completes or there are no more
// chunks available.
while (!GetDecodeDone() && !HasError()) {
auto newState = mIterator->AdvanceOrScheduleResume(this);
auto newState = mIterator->AdvanceOrScheduleResume(onResume);
if (newState == SourceBufferIterator::WAITING) {
// We can't continue because the rest of the data hasn't arrived from the

View File

@ -36,13 +36,16 @@ public:
void Init();
/**
* Decodes, reading all data currently available in the SourceBuffer. If more
* data is needed, Decode() automatically ensures that it will be called again
* on a DecodePool thread when the data becomes available.
* Decodes, reading all data currently available in the SourceBuffer.
*
* If more data is needed, Decode() will schedule @aOnResume to be called when
* more data is available. If @aOnResume is null or unspecified, the default
* implementation resumes decoding on a DecodePool thread. Most callers should
* use the default implementation.
*
* Any errors are reported by setting the appropriate state on the decoder.
*/
nsresult Decode();
nsresult Decode(IResumable* aOnResume = nullptr);
/**
* Given a maximum number of bytes we're willing to decode, @aByteLimit,

View File

@ -213,10 +213,6 @@ SourceBuffer::AddWaitingConsumer(IResumable* aConsumer)
MOZ_ASSERT(!mStatus, "Waiting when we're complete?");
if (MOZ_UNLIKELY(NS_IsMainThread())) {
NS_WARNING("SourceBuffer consumer on the main thread needed to wait");
}
mWaitingConsumers.AppendElement(aConsumer);
}

View File

@ -0,0 +1,249 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "Common.h"
#include "Decoder.h"
#include "DecoderFactory.h"
#include "decoders/nsBMPDecoder.h"
#include "imgIContainer.h"
#include "imgITools.h"
#include "ImageFactory.h"
#include "mozilla/gfx/2D.h"
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#include "nsIRunnable.h"
#include "nsIThread.h"
#include "mozilla/nsRefPtr.h"
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "ProgressTracker.h"
#include "SourceBuffer.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::image;
TEST(ImageDecoders, ImageModuleAvailable)
{
// We can run into problems if XPCOM modules get initialized in the wrong
// order. It's important that this test run first, both as a sanity check and
// to ensure we get the module initialization order we want.
nsCOMPtr<imgITools> imgTools =
do_CreateInstance("@mozilla.org/image/tools;1");
EXPECT_TRUE(imgTools != nullptr);
}
static void
CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
{
EXPECT_TRUE(aDecoder->GetDecodeDone());
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
aDecoder->HasError());
EXPECT_TRUE(!aDecoder->WasAborted());
// Verify that the decoder made the expected progress.
Progress progress = aDecoder->TakeProgress();
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
bool(progress & FLAG_HAS_ERROR));
if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
return; // That's all we can check for bad images.
}
EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
bool(progress & FLAG_HAS_TRANSPARENCY));
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
bool(progress & FLAG_IS_ANIMATED));
// The decoder should get the correct size.
IntSize size = aDecoder->GetSize();
EXPECT_EQ(aTestCase.mSize.width, size.width);
EXPECT_EQ(aTestCase.mSize.height, size.height);
// Get the current frame, which is always the first frame of the image
// because CreateAnonymousDecoder() forces a first-frame-only decode.
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
nsRefPtr<SourceSurface> surface = currentFrame->GetSurface();
// Verify that the resulting surfaces matches our expectations.
EXPECT_EQ(SurfaceType::DATA, surface->GetType());
EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
surface->GetFormat() == SurfaceFormat::B8G8R8A8);
EXPECT_EQ(aTestCase.mSize, surface->GetSize());
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
aTestCase.mFlags & TEST_CASE_IS_FUZZY));
}
static void
CheckDecoderSingleChunk(const ImageTestCase& aTestCase)
{
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
ASSERT_TRUE(inputStream != nullptr);
// Figure out how much data we have.
uint64_t length;
nsresult rv = inputStream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Write the data into a SourceBuffer.
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
sourceBuffer->ExpectLength(length);
rv = sourceBuffer->AppendFromInputStream(inputStream, length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
sourceBuffer->Complete(NS_OK);
// Create a decoder.
DecoderType decoderType =
DecoderFactory::GetDecoderType(aTestCase.mMimeType);
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
DefaultSurfaceFlags());
ASSERT_TRUE(decoder != nullptr);
// Run the full decoder synchronously.
decoder->Decode();
CheckDecoderResults(aTestCase, decoder);
}
class NoResume : public IResumable
{
public:
NS_INLINE_DECL_REFCOUNTING(NoResume, override)
virtual void Resume() override { }
private:
~NoResume() { }
};
static void
CheckDecoderMultiChunk(const ImageTestCase& aTestCase)
{
nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
ASSERT_TRUE(inputStream != nullptr);
// Figure out how much data we have.
uint64_t length;
nsresult rv = inputStream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Create a SourceBuffer and a decoder.
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
sourceBuffer->ExpectLength(length);
DecoderType decoderType =
DecoderFactory::GetDecoderType(aTestCase.mMimeType);
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
DefaultSurfaceFlags());
ASSERT_TRUE(decoder != nullptr);
// Decode synchronously, using a |NoResume| IResumable so the Decoder doesn't
// attempt to schedule itself on a nonexistent DecodePool when we write more
// data into the SourceBuffer.
nsRefPtr<NoResume> noResume = new NoResume();
for (uint64_t read = 0; read < length ; ++read) {
uint64_t available = 0;
rv = inputStream->Available(&available);
ASSERT_TRUE(available > 0);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = sourceBuffer->AppendFromInputStream(inputStream, 1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
decoder->Decode(noResume);
}
sourceBuffer->Complete(NS_OK);
decoder->Decode(noResume);
CheckDecoderResults(aTestCase, decoder);
}
TEST(ImageDecoders, PNGSingleChunk)
{
CheckDecoderSingleChunk(GreenPNGTestCase());
}
TEST(ImageDecoders, PNGMultiChunk)
{
CheckDecoderMultiChunk(GreenPNGTestCase());
}
TEST(ImageDecoders, GIFSingleChunk)
{
CheckDecoderSingleChunk(GreenGIFTestCase());
}
TEST(ImageDecoders, GIFMultiChunk)
{
CheckDecoderMultiChunk(GreenGIFTestCase());
}
TEST(ImageDecoders, JPGSingleChunk)
{
CheckDecoderSingleChunk(GreenJPGTestCase());
}
TEST(ImageDecoders, JPGMultiChunk)
{
CheckDecoderMultiChunk(GreenJPGTestCase());
}
TEST(ImageDecoders, BMPSingleChunk)
{
CheckDecoderSingleChunk(GreenBMPTestCase());
}
TEST(ImageDecoders, BMPMultiChunk)
{
CheckDecoderMultiChunk(GreenBMPTestCase());
}
TEST(ImageDecoders, ICOSingleChunk)
{
CheckDecoderSingleChunk(GreenICOTestCase());
}
// XXX(seth): Disabled. We'll fix this in bug 1196066.
TEST(ImageDecoders, DISABLED_ICOMultiChunk)
{
CheckDecoderMultiChunk(GreenICOTestCase());
}
TEST(ImageDecoders, AnimatedGIFSingleChunk)
{
CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
}
TEST(ImageDecoders, AnimatedGIFMultiChunk)
{
CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
}
TEST(ImageDecoders, AnimatedPNGSingleChunk)
{
CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
}
TEST(ImageDecoders, AnimatedPNGMultiChunk)
{
CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase());
}
TEST(ImageDecoders, CorruptSingleChunk)
{
CheckDecoderSingleChunk(CorruptTestCase());
}
TEST(ImageDecoders, CorruptMultiChunk)
{
CheckDecoderMultiChunk(CorruptTestCase());
}

View File

@ -10,6 +10,7 @@ FAIL_ON_WARNINGS = True
UNIFIED_SOURCES = [
'Common.cpp',
'TestDecoders.cpp',
'TestDecodeToSurface.cpp',
'TestMetadata.cpp',
]

View File

@ -1,2 +1,2 @@
skip-if(!winWidget) skip-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761.sjs bug415761.ico
skip-if(!winWidget) skip-if(/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761cleanup.sjs about:blank
skip-if(!winWidget) skip-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761.sjs bug415761.ico # See Bug 850194
skip-if(!winWidget) skip-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu)) HTTP == bug415761cleanup.sjs about:blank

222
js/public/UbiNodeCensus.h Normal file
View File

@ -0,0 +1,222 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_UbiNodeCensus_h
#define js_UbiNodeCensus_h
#include "mozilla/Move.h"
#include "js/UbiNode.h"
#include "js/UbiNodeTraverse.h"
// A census is a ubi::Node traversal that assigns each node to one or more
// buckets, and returns a report with the size of each bucket.
//
// We summarize the results of a census with counts broken down according to
// criteria selected by the API consumer code that is requesting the census. For
// example, the following breakdown might give an interesting overview of the
// heap:
//
// - all nodes
// - objects
// - objects with a specific [[Class]] *
// - strings
// - scripts
// - all other Node types
// - nodes with a specific ubi::Node::typeName *
//
// Obviously, the parts of this tree marked with * represent many separate
// counts, depending on how many distinct [[Class]] values and ubi::Node type
// names we encounter.
//
// The supported types of breakdowns are documented in
// js/src/doc/Debugger/Debugger.Memory.md.
//
// When we parse the 'breakdown' argument to takeCensus, we build a tree of
// CountType nodes. For example, for the breakdown shown in the
// Debugger.Memory.prototype.takeCensus, documentation:
//
// {
// by: "coarseType",
// objects: { by: "objectClass" },
// other: { by: "internalType" }
// }
//
// we would build the following tree of CountType subclasses:
//
// ByCoarseType
// objects: ByObjectClass
// each class: SimpleCount
// scripts: SimpleCount
// strings: SimpleCount
// other: ByUbinodeType
// each type: SimpleCount
//
// The interior nodes are all breakdown types that categorize nodes according to
// one characteristic or another; and the leaf nodes are all SimpleType.
//
// Each CountType has its own concrete C++ type that holds the counts it
// produces. SimpleCount::Count just holds totals. ByObjectClass::Count has a
// hash table whose keys are object class names and whose values are counts of
// some other type (in the example above, SimpleCount).
//
// To keep actual count nodes small, they have no vtable. Instead, each count
// points to its CountType, which knows how to carry out all the operations we
// need on a Count. A CountType can produce new count nodes; process nodes as we
// visit them; build a JS object reporting the results; and destruct count
// nodes.
namespace JS {
namespace ubi {
struct Census;
class CountBase;
struct CountDeleter {
void operator()(CountBase*);
};
using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
// Abstract base class for CountType nodes.
struct CountType {
explicit CountType(Census& census) : census(census) { }
virtual ~CountType() { }
// Destruct a count tree node that this type instance constructed.
virtual void destructCount(CountBase& count) = 0;
// Return a fresh node for the count tree that categorizes nodes according
// to this type. Return a nullptr on OOM.
virtual CountBasePtr makeCount() = 0;
// Trace |count| and all its children, for garbage collection.
virtual void traceCount(CountBase& count, JSTracer* trc) = 0;
// Implement the 'count' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool count(CountBase& count, const Node& node) = 0;
// Implement the 'report' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool report(CountBase& count, MutableHandleValue report) = 0;
protected:
Census& census;
};
using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
// An abstract base class for count tree nodes.
class CountBase {
// In lieu of a vtable, each CountBase points to its type, which
// carries not only the implementations of the CountBase methods, but also
// additional parameters for the type's behavior, as specified in the
// breakdown argument passed to takeCensus.
CountType& type;
protected:
~CountBase() { }
public:
explicit CountBase(CountType& type) : type(type), total_(0) { }
// Categorize and count |node| as appropriate for this count's type.
bool count(const Node& node) { return type.count(*this, node); }
// Construct a JavaScript object reporting the counts recorded in this
// count, and store it in |report|. Return true on success, or false on
// failure.
bool report(MutableHandleValue report) { return type.report(*this, report); }
// Down-cast this CountBase to its true type, based on its 'type' member,
// and run its destructor.
void destruct() { return type.destructCount(*this); }
// Trace this count for garbage collection.
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
size_t total_;
};
class RootedCount : JS::CustomAutoRooter {
CountBasePtr count;
void trace(JSTracer* trc) override { count->trace(trc); }
public:
RootedCount(JSContext* cx, CountBasePtr&& count)
: CustomAutoRooter(cx),
count(Move(count))
{ }
CountBase* operator->() const { return count.get(); }
explicit operator bool() const { return count.get(); }
operator CountBasePtr&() { return count; }
};
// Common data for a census traversal, shared across all CountType nodes.
struct Census {
JSContext* const cx;
// If the targetZones set is non-empty, then only consider nodes whose zone
// is an element of the set. If the targetZones set is empty, then nodes in
// all zones are considered.
JS::ZoneSet targetZones;
Zone* atomsZone;
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
bool init();
// A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
// census's context, but don't charge the memory allocated to our context's
// GC pressure counters.
template<typename T, typename... Args>
T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
void* memory = js_malloc(sizeof(T));
if (MOZ_UNLIKELY(!memory)) {
return nullptr;
}
return new(memory) T(mozilla::Forward<Args>(args)...);
}
};
// A BreadthFirst handler type that conducts a census, using a CountBase to
// categorize and count each node.
class CensusHandler {
Census& census;
CountBasePtr& rootCount;
public:
CensusHandler(Census& census, CountBasePtr& rootCount)
: census(census),
rootCount(rootCount)
{ }
bool report(MutableHandleValue report) {
return rootCount->report(report);
}
// This class needs to retain no per-node data.
class NodeData { };
bool operator() (BreadthFirst<CensusHandler>& traversal,
Node origin, const Edge& edge,
NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst<CensusHandler>;
// Examine the census options supplied by the API consumer, and use that to
// build a CountType tree.
bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
CountTypePtr& outResult);
} // namespace ubi
} // namespace JS
#endif // js_UbiNodeCensus_h

View File

@ -87,7 +87,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
bool maybeSetSourceMapFromOptions();
bool emitFinalReturn();
bool initGlobalBindings(ParseContext<FullParseHandler>& pc);
void markFunctionsWithinEvalScript();
bool maybeCompleteCompressSource();
AutoCompilationTraceLogger traceLogger;
@ -519,29 +518,6 @@ BytecodeCompiler::initGlobalBindings(ParseContext<FullParseHandler>& pc)
return true;
}
void
BytecodeCompiler::markFunctionsWithinEvalScript()
{
// Mark top level functions in an eval script as being within an eval.
if (!script->hasObjects())
return;
ObjectArray* objects = script->objects();
size_t start = script->innerObjectsStart();
for (size_t i = start; i < objects->length; i++) {
JSObject* obj = objects->vector[i];
if (obj->is<JSFunction>()) {
JSFunction* fun = &obj->as<JSFunction>();
if (fun->hasScript())
fun->nonLazyScript()->setDirectlyInsideEval();
else if (fun->isInterpretedLazy())
fun->lazyScript()->setDirectlyInsideEval();
}
}
}
bool
BytecodeCompiler::maybeCompleteCompressSource()
{
@ -621,12 +597,6 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
return nullptr;
}
// Note that this marking must happen before we tell Debugger
// about the new script, in case Debugger delazifies the script's
// inner functions.
if (options.forEval)
markFunctionsWithinEvalScript();
emitter->tellDebuggerAboutCompiledScript(cx);
if (!maybeCompleteCompressSource())
@ -790,8 +760,6 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
script->bindings = pn->pn_funbox->bindings;
if (lazy->directlyInsideEval())
script->setDirectlyInsideEval();
if (lazy->usesArgumentsApplyAndThis())
script->setUsesArgumentsApplyAndThis();
if (lazy->hasBeenCloned())

View File

@ -13,6 +13,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Maybe.h"
#include "mozilla/PodOperations.h"
#include "mozilla/UniquePtr.h"
@ -48,6 +49,8 @@ using namespace js;
using namespace js::gc;
using namespace js::frontend;
using mozilla::Maybe;
using mozilla::Some;
using mozilla::DebugOnly;
using mozilla::NumberIsInt32;
using mozilla::PodCopy;
@ -107,16 +110,6 @@ struct frontend::LoopStmtInfo : public StmtInfoBCE
}
};
void
FunctionBox::switchStaticScopeToFunction()
{
if (staticScope_->is<StaticFunctionBoxScopeObject>()) {
MOZ_ASSERT(staticScope_->as<StaticFunctionBoxScopeObject>().functionBox() == this);
staticScope_ = function();
}
MOZ_ASSERT(staticScope_ == function());
}
BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
Parser<FullParseHandler>* parser, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
@ -1512,57 +1505,65 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
return true;
}
size_t hops = 0;
// Walk the static scope chain and look for an aliased binding with
// the name pn->pn_atom.
uint32_t hops = 0;
Maybe<uint32_t> slot;
FunctionBox* funbox = sc->asFunctionBox();
if (funbox->hasExtensibleScope())
return false;
if (funbox->function()->isNamedLambda() && funbox->function()->atom() == pn->pn_atom)
return false;
if (funbox->isHeavyweight()) {
hops++;
if (funbox->function()->isNamedLambda())
hops++;
}
if (script->directlyInsideEval())
return false;
RootedObject outerScope(cx, script->enclosingStaticScope());
for (StaticScopeIter<CanGC> ssi(cx, outerScope); !ssi.done(); ssi++) {
if (ssi.type() != StaticScopeIter<CanGC>::Function) {
if (ssi.type() == StaticScopeIter<CanGC>::Block) {
// Use generic ops if a catch block is encountered.
return false;
}
if (ssi.hasSyntacticDynamicScopeObject())
hops++;
PropertyName* name = pn->pn_atom->asPropertyName();
for (StaticScopeIter<NoGC> ssi(funbox->staticScope()); !ssi.done(); ssi++) {
// Don't optimize names through eval.
if (ssi.type() == StaticScopeIter<NoGC>::Eval)
return false;
if (!ssi.hasSyntacticDynamicScopeObject())
continue;
}
RootedScript script(cx, ssi.funScript());
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
return false;
if (ssi.hasSyntacticDynamicScopeObject()) {
uint32_t slot;
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
JSOp op;
switch (pn->getOp()) {
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
default: return false;
// Look up for name in function and block scopes.
if (ssi.type() == StaticScopeIter<NoGC>::Function) {
RootedScript funScript(cx, ssi.funScript());
if (funScript->funHasExtensibleScope() || ssi.fun().atom() == pn->pn_atom)
return false;
// Skip the current function, since we're trying to convert a
// free name.
if (script != funScript) {
uint32_t slot_;
if (lookupAliasedName(funScript, name, &slot_, pn)) {
slot = Some(slot_);
break;
}
pn->setOp(op);
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, slot));
return true;
}
hops++;
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
RootedShape shape(cx, ssi.block().lookupAliasedName(name));
if (shape) {
// Don't optimize setting a 'const' binding. Let the slow
// path do the error checking.
if (!shape->writable() && pn->getOp() == JSOP_SETNAME)
return false;
slot = Some(shape->slot());
pn->pn_dflags |= PND_LEXICAL;
break;
}
} else {
MOZ_ASSERT(ssi.type() != StaticScopeIter<NoGC>::With);
}
// If this walk up and check for directlyInsideEval is ever removed,
// we'll need to adjust CompileLazyFunction to better communicate
// whether we're inside eval to the BytecodeEmitter. For now, this
// walk is why CompileLazyFunction can claim that it's never inside
// eval.
if (script->funHasExtensibleScope() || script->directlyInsideEval())
return false;
hops++;
}
// If we found a scope binding name, convert the name op to an aliased
// var op.
if (slot.isSome()) {
JSOp op;
switch (pn->getOp()) {
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
default: return false;
}
pn->setOp(op);
MOZ_ALWAYS_TRUE(pn->pn_scopecoord.set(parser->tokenStream, hops, *slot));
return true;
}
}
@ -7007,8 +7008,11 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
isIndex = true;
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
// EmitClass took care of constructor already.
if (type == ClassBody && key->pn_atom == cx->names().constructor)
if (type == ClassBody && key->pn_atom == cx->names().constructor &&
!propdef->as<ClassMethod>().isStatic())
{
continue;
}
// The parser already checked for atoms representing indexes and
// used PNK_NUMBER instead, but also watch for ids which TI treats

View File

@ -1160,8 +1160,8 @@ ObjectBox::trace(JSTracer* trc)
if (box->isFunctionBox()) {
FunctionBox* funbox = box->asFunctionBox();
funbox->bindings.trace(trc);
if (funbox->staticScope_)
TraceRoot(trc, &funbox->staticScope_, "funbox-staticScope");
if (funbox->enclosingStaticScope_)
TraceRoot(trc, &funbox->enclosingStaticScope_, "funbox-enclosingStaticScope");
}
box = box->traceLink;
}

View File

@ -48,6 +48,22 @@ using mozilla::Maybe;
using JS::AutoGCRooter;
JSFunction::AutoParseUsingFunctionBox::AutoParseUsingFunctionBox(ExclusiveContext* cx,
frontend::FunctionBox* funbox)
: fun_(cx, funbox->function()),
oldEnv_(cx, fun_->environment())
{
fun_->setFunctionBox(funbox);
funbox->computeAllowSyntax(fun_);
funbox->computeInWith(fun_);
}
JSFunction::AutoParseUsingFunctionBox::~AutoParseUsingFunctionBox()
{
fun_->unsetFunctionBox();
fun_->setEnvironment(oldEnv_);
}
namespace js {
namespace frontend {
@ -613,12 +629,12 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
template <typename ParseHandler>
FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
JSObject* staticScope, ParseContext<ParseHandler>* outerpc,
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* outerpc,
Directives directives, bool extraWarnings, GeneratorKind generatorKind)
: ObjectBox(fun, traceListHead),
SharedContext(cx, directives, extraWarnings),
bindings(),
staticScope_(staticScope),
enclosingStaticScope_(enclosingStaticScope),
bufStart(0),
bufEnd(0),
length(0),
@ -636,22 +652,17 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
// baked into JIT code, so they must be allocated tenured. They are held by
// the JSScript so cannot be collected during a minor GC anyway.
MOZ_ASSERT(fun->isTenured());
if (staticScope->is<StaticFunctionBoxScopeObject>())
staticScope->as<StaticFunctionBoxScopeObject>().setFunctionBox(this);
computeAllowSyntax(staticScope);
computeInWith(staticScope);
}
template <typename ParseHandler>
FunctionBox*
Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
ParseContext<ParseHandler>* outerpc,
Directives inheritedDirectives,
GeneratorKind generatorKind,
JSObject* staticScope)
Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
ParseContext<ParseHandler>* outerpc,
Directives inheritedDirectives,
GeneratorKind generatorKind,
JSObject* enclosingStaticScope)
{
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
MOZ_ASSERT(fun);
/*
@ -662,9 +673,8 @@ Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
* function.
*/
FunctionBox* funbox =
alloc.new_<FunctionBox>(context, traceListHead, fun, staticScope, outerpc,
inheritedDirectives,
options().extraWarningsOption,
alloc.new_<FunctionBox>(context, traceListHead, fun, enclosingStaticScope, outerpc,
inheritedDirectives, options().extraWarningsOption,
generatorKind);
if (!funbox) {
ReportOutOfMemory(context);
@ -678,29 +688,6 @@ Parser<ParseHandler>::newFunctionBoxWithScope(Node fn, JSFunction* fun,
return funbox;
}
template <typename ParseHandler>
FunctionBox*
Parser<ParseHandler>::newFunctionBox(Node fn, HandleFunction fun,
ParseContext<ParseHandler>* outerpc,
Directives inheritedDirectives,
GeneratorKind generatorKind,
HandleObject enclosingStaticScope)
{
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
StaticFunctionBoxScopeObject* scope =
StaticFunctionBoxScopeObject::create(context, enclosingStaticScope);
if (!scope)
return nullptr;
FunctionBox* funbox = newFunctionBoxWithScope(fn, fun, outerpc, inheritedDirectives,
generatorKind, scope);
if (!funbox)
return nullptr;
return funbox;
}
template <typename ParseHandler>
void
Parser<ParseHandler>::trace(JSTracer* trc)
@ -1305,10 +1292,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
break;
case Method:
MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
if (generatorKind == NotGenerator)
flags = JSFunction::INTERPRETED_METHOD;
else
flags = JSFunction::INTERPRETED_METHOD_GENERATOR;
flags = (generatorKind == NotGenerator
? JSFunction::INTERPRETED_METHOD
: JSFunction::INTERPRETED_METHOD_GENERATOR);
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
break;
case ClassConstructor:
@ -1325,8 +1311,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
break;
default:
flags = JSFunction::INTERPRETED_NORMAL;
break;
flags = (generatorKind == NotGenerator
? JSFunction::INTERPRETED_NORMAL
: JSFunction::INTERPRETED_GENERATOR);
}
fun = NewFunctionWithProto(context, nullptr, 0, flags, nullptr, atom, proto,

View File

@ -106,6 +106,11 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
Node maybeFunction; /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */
// If sc->isFunctionBox(), this is used to temporarily link up the
// FunctionBox with the JSFunction so the static scope chain may be walked
// without a JSScript.
mozilla::Maybe<JSFunction::AutoParseUsingFunctionBox> parseUsingFunctionBox;
// lastYieldOffset stores the offset of the last yield that was parsed.
// NoYieldOffset is its initial value.
static const uint32_t NoYieldOffset = UINT32_MAX;
@ -270,6 +275,8 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
inDeclDestructuring(false)
{
prs->pc = this;
if (sc->isFunctionBox())
parseUsingFunctionBox.emplace(prs->context, sc->asFunctionBox());
}
~ParseContext();
@ -463,17 +470,10 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
* cx->tempLifoAlloc.
*/
ObjectBox* newObjectBox(JSObject* obj);
FunctionBox* newFunctionBoxWithScope(Node fn, JSFunction* fun,
ParseContext<ParseHandler>* outerpc,
Directives directives, GeneratorKind generatorKind,
JSObject* staticScope);
private:
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext<ParseHandler>* outerpc,
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* outerpc,
Directives directives, GeneratorKind generatorKind,
HandleObject enclosingStaticScope);
JSObject* enclosingStaticScope);
public:
// Use when the funbox is the outermost.
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
GeneratorKind generatorKind, HandleObject enclosingStaticScope)

View File

@ -191,10 +191,6 @@ class SharedContext
bool inWith_;
bool superScopeAlreadyNeedsHomeObject_;
protected:
void computeAllowSyntax(JSObject* staticScope);
void computeInWith(JSObject* staticScope);
public:
SharedContext(ExclusiveContext* cx, Directives directives,
bool extraWarnings)
@ -215,6 +211,8 @@ class SharedContext
// for the static scope. FunctionBoxes are LifoAlloc'd and need to
// manually trace their static scope.
virtual JSObject* staticScope() const = 0;
void computeAllowSyntax(JSObject* staticScope);
void computeInWith(JSObject* staticScope);
virtual ObjectBox* toObjectBox() { return nullptr; }
inline bool isFunctionBox() { return toObjectBox() && toObjectBox()->isFunctionBox(); }
@ -277,7 +275,7 @@ class FunctionBox : public ObjectBox, public SharedContext
{
public:
Bindings bindings; /* bindings for this function */
JSObject* staticScope_;
JSObject* enclosingStaticScope_;
uint32_t bufStart;
uint32_t bufEnd;
uint32_t startLine;
@ -285,7 +283,6 @@ class FunctionBox : public ObjectBox, public SharedContext
uint16_t length;
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
bool inWith_:1; /* some enclosing scope is a with-statement */
bool inGenexpLambda:1; /* lambda from generator expression */
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
bool useAsm:1; /* see useAsmOrInsideUseAsm */
@ -300,13 +297,13 @@ class FunctionBox : public ObjectBox, public SharedContext
template <typename ParseHandler>
FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
JSObject* staticScope, ParseContext<ParseHandler>* pc,
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* pc,
Directives directives, bool extraWarnings, GeneratorKind generatorKind);
ObjectBox* toObjectBox() override { return this; }
JSFunction* function() const { return &object->as<JSFunction>(); }
JSObject* staticScope() const override { return staticScope_; }
void switchStaticScopeToFunction();
JSObject* staticScope() const override { return function(); }
JSObject* enclosingStaticScope() const { return enclosingStaticScope_; }
GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
bool isGenerator() const { return generatorKind() != NotGenerator; }

View File

@ -0,0 +1,6 @@
function entryFrame_1(d) {
assertJitStackInvariants();
}
for (i = 0Xa; i < 40; i++) {
new entryFrame_1();
}

View File

@ -0,0 +1,15 @@
// |jit-test| error: TypeError
load(libdir + "class.js");
var test = `
class test {
constructor() {};
}
(function() {
test()
})();
`;
if (classesEnabled())
eval(test);

Some files were not shown because too many files have changed in this diff Show More