Merge pull request #15 from classilla/master

Keep up with head
This commit is contained in:
Riccardo 2018-10-22 23:30:26 +02:00 committed by GitHub
commit 06ee05da83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 5279 additions and 1536 deletions

View File

@ -138,6 +138,8 @@ ImageAccessible::DoAction(uint8_t aIndex)
nsCOMPtr<nsPIDOMWindow> tmp;
return NS_SUCCEEDED(piWindow->Open(spec, EmptyString(), EmptyString(),
/* aLoadInfo = */ nullptr,
/* aForceNoOpener = */ false,
getter_AddRefs(tmp)));
}

View File

@ -1763,6 +1763,7 @@ let remote = false;
var aForceNotRemote;
var aNoReferrer;
var aUserContextId;
var aSkipBackgroundNotify;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@ -1780,6 +1781,7 @@ let remote = false;
aForceNotRemote = params.forceNotRemote;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aSkipBackgroundNotify = params.skipBackgroundNotify;
}
// if we're adding tabs, we're past interrupt mode, ditch the owner
@ -1794,6 +1796,11 @@ let remote = false;
t.setAttribute("usercontextid", aUserContextId);
t.setAttribute("crop", "end");
t.setAttribute("onerror", "this.removeAttribute('image');");
if (aSkipBackgroundNotify) {
t.setAttribute("skipbackgroundnotify", true);
}
t.className = "tabbrowser-tab";
// The new browser should be remote if this is an e10s window and
@ -5184,10 +5191,10 @@ let remote = false;
selected.left - scrollRect.left);
}
if (!this._animateElement.hasAttribute("notifybgtab")) {
this._animateElement.setAttribute("notifybgtab", "true");
if (!this._animateElement.hasAttribute("highlight")) {
this._animateElement.setAttribute("highlight", "true");
setTimeout(function (ele) {
ele.removeAttribute("notifybgtab");
ele.removeAttribute("highlight");
}, 150, this._animateElement);
}
]]></body>
@ -5278,7 +5285,7 @@ let remote = false;
if (tab.getAttribute("selected") == "true") {
//this._fillTrailingGap();
this._handleTabSelect();
} else {
} else if (!tab.hasAttribute("skipbackgroundnotify")) {
this._notifyBackgroundTab(tab);
}

View File

@ -2932,6 +2932,7 @@ var SessionStoreInternal = {
tabbrowser.addTab("about:blank", {
skipAnimation: true,
forceNotRemote: true,
skipBackgroundNotify: true,
}));
if (winData.tabs[t].pinned)

View File

@ -32,7 +32,8 @@ var TabAttributesInternal = {
// 'muted' should not be accessed directly but handled by using the
// tab.linkedBrowser.audioMuted/toggleMuteAudio methods.
// 'pending' is used internal by sessionstore and managed accordingly.
_skipAttrs: new Set(["image", "muted", "pending"]),
// 'skipbackgroundnotify' is used to speed up startup time (bug 1342849).
_skipAttrs: new Set(["image", "muted", "pending", "skipbackgroundnotify"]),
persist: function (name) {
if (this._attrs.has(name) || this._skipAttrs.has(name)) {

View File

@ -2645,7 +2645,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
transition: 1s background-color ease-out;
}
.tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] {
.tabbrowser-arrowscrollbox > .scrollbutton-down[highlight] {
background-color: Highlight;
transition: none;
}

View File

@ -1144,6 +1144,14 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
BLOK("synchrobox.adswizz.com") ||
BLOK("delivery-cdn-cf.adswizz.com") ||
BLOK("router.infolinks.com") ||
BLOK("rps-uk.rockpapershotgun.com") || // XXX?
BLOK("buy.tinypass.com") ||
BLOK("cdn.tinypass.com") ||
0) {
#undef BLOK
// Yup.

View File

@ -9592,9 +9592,20 @@ nsDocShell::InternalLoad(nsIURI* aURI,
if (aWindowTarget && *aWindowTarget) {
// Locate the target DocShell.
nsCOMPtr<nsIDocShellTreeItem> targetItem;
rv = FindItemWithName(aWindowTarget, nullptr, this,
getter_AddRefs(targetItem));
NS_ENSURE_SUCCESS(rv, rv);
nsDependentString name(aWindowTarget);
// Only _self, _parent, and _top are supported in noopener case. But we
// have to be careful to not apply that to the noreferrer case. See bug
// 1358469.
bool allowNamedTarget = !(aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) ||
(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
if (allowNamedTarget ||
name.LowerCaseEqualsLiteral("_self") ||
name.LowerCaseEqualsLiteral("_parent") ||
name.LowerCaseEqualsLiteral("_top")) {
rv = FindItemWithName(aWindowTarget, nullptr, this,
getter_AddRefs(targetItem));
NS_ENSURE_SUCCESS(rv, rv);
}
targetDocShell = do_QueryInterface(targetItem);
// If the targetDocShell doesn't exist, then this is a new docShell
@ -9737,11 +9748,60 @@ nsDocShell::InternalLoad(nsIURI* aURI,
NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
nsDependentString name(aWindowTarget);
nsCOMPtr<nsIDOMWindow> newWin;
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
// If we are a noopener load, we just hand the whole thing over to our
// window.
if (aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) {
// Various asserts that we know to hold because NO_OPENER loads can only
// happen for links.
MOZ_ASSERT(!aLoadReplace);
/* MOZ_ASSERT(aPrincipalToInherit == aTriggeringPrincipal); */
MOZ_ASSERT(aFlags == INTERNAL_LOAD_FLAGS_NO_OPENER ||
aFlags == (INTERNAL_LOAD_FLAGS_NO_OPENER |
INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
MOZ_ASSERT(!aPostData);
MOZ_ASSERT(!aHeadersData);
MOZ_ASSERT(aLoadType == LOAD_LINK);
MOZ_ASSERT(!aSHEntry);
MOZ_ASSERT(aFirstParty); // Windowwatcher will assume this.
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
rv = CreateLoadInfo(getter_AddRefs(loadInfo));
if (NS_FAILED(rv)) {
return rv;
}
// Set up our loadinfo so it will do the load as much like we would have
// as possible.
loadInfo->SetReferrer(aReferrer);
loadInfo->SetReferrerPolicy(aReferrerPolicy);
loadInfo->SetSendReferrer(!(aFlags &
INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
loadInfo->SetOriginalURI(aOriginalURI);
loadInfo->SetLoadReplace(aLoadReplace);
loadInfo->SetOwner(loadingPrincipal); // SetTriggeringPrincipal
loadInfo->SetInheritOwner( /* SetInheritPrincipal _INHERIT_PRINCIPAL */
!!(aFlags & INTERNAL_LOAD_FLAGS_INHERIT_OWNER));
// Explicit principal because we do not want any guesses as to what the
// principal to inherit is: it should be aTriggeringPrincipal.
loadInfo->SetOwnerIsExplicit(true); // SetPrincipalIsExplicit(true);
loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
nsCOMPtr<nsPIDOMWindow> newWin;
rv = win->Open(NS_ConvertUTF8toUTF16(spec),
name, // window name
EmptyString(), // Features
loadInfo,
true, // aForceNoOpener
getter_AddRefs(newWin));
MOZ_ASSERT(!newWin);
return rv;
}
nsCOMPtr<nsIDOMWindow> newWin;
rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
name, // window name
EmptyString(), // Features
@ -9756,11 +9816,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
if (!newDoc || newDoc->IsInitialDocument()) {
isNewWindow = true;
aFlags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
// set opener object to null for noreferrer
if (aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) {
piNewWin->SetOpenerWindow(nullptr, false);
}
}
}
@ -13497,11 +13552,16 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
while (tok.hasMoreTokens()) {
if (tok.nextToken().LowerCaseEqualsLiteral("noreferrer")) {
const nsAString& token = tok.nextToken();
if (token.LowerCaseEqualsLiteral("noreferrer")) {
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
INTERNAL_LOAD_FLAGS_NO_OPENER;
// We now have all the flags we could possibly have, so just stop.
break;
}
if (token.LowerCaseEqualsLiteral("noopener")) {
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
}
}
}

View File

@ -51,6 +51,7 @@
#include "nsJSUtils.h"
#include "jsapi.h" // for JSAutoRequest
#include "jswrapper.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsReadableUtils.h"
#include "nsDOMClassInfo.h"
#include "nsJSEnvironment.h"
@ -1483,9 +1484,20 @@ void
nsGlobalWindow::MaybeForgiveSpamCount()
{
if (IsOuterWindow() &&
IsPopupSpamWindow())
{
SetPopupSpamWindow(false);
IsPopupSpamWindow()) {
SetIsPopupSpamWindow(false);
}
}
void
nsGlobalWindow::SetIsPopupSpamWindow(bool aIsPopupSpam)
{
MOZ_ASSERT(IsOuterWindow());
mIsPopupSpam = aIsPopupSpam;
if (aIsPopupSpam) {
++gOpenPopupSpamCount;
} else {
--gOpenPopupSpamCount;
NS_ASSERTION(gOpenPopupSpamCount >= 0,
"Unbalanced decrement of gOpenPopupSpamCount");
@ -1644,7 +1656,7 @@ nsGlobalWindow::ClearControllers()
}
void
nsGlobalWindow::FreeInnerObjects()
nsGlobalWindow::FreeInnerObjects(bool aForDocumentOpen)
{
NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
@ -1697,8 +1709,10 @@ nsGlobalWindow::FreeInnerObjects()
mDocumentURI = mDoc->GetDocumentURI();
mDocBaseURI = mDoc->GetDocBaseURI();
while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, false);
if (!aForDocumentOpen) {
while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, false);
}
}
// Note: we don't have to worry about eAnimationsOnly suppressions because
@ -2510,6 +2524,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
bool handleDocumentOpen = false;
JS::Rooted<JSObject*> newInnerGlobal(cx);
if (reUseInnerWindow) {
// We're reusing the current inner window.
@ -2592,6 +2608,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (currentInner && currentInner->GetWrapperPreserveColor()) {
if (oldDoc == aDocument) {
handleDocumentOpen = true;
// Move the navigator from the old inner window to the new one since
// this is a document.write. This is safe from a same-origin point of
// view because document.write can only be used by the same origin.
@ -2617,7 +2634,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// Don't free objects on our current inner window if it's going to be
// held in the bfcache.
if (!currentInner->IsFrozen()) {
currentInner->FreeInnerObjects();
currentInner->FreeInnerObjects(handleDocumentOpen);
}
}
@ -5718,11 +5735,18 @@ GetCallerDocShellTreeItem()
bool
nsGlobalWindow::WindowExists(const nsAString& aName,
bool aForceNoOpener,
bool aLookForCallerOnJSStack)
{
NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
NS_PRECONDITION(mDocShell, "Must have docshell");
if (aForceNoOpener) {
return aName.LowerCaseEqualsLiteral("_self") ||
aName.LowerCaseEqualsLiteral("_top") ||
aName.LowerCaseEqualsLiteral("_parent");
}
nsCOMPtr<nsIDocShellTreeItem> caller;
if (aLookForCallerOnJSStack) {
caller = GetCallerDocShellTreeItem();
@ -7532,14 +7556,6 @@ nsGlobalWindow::FirePopupBlockedEvent(nsIDocument* aDoc,
aDoc->DispatchEvent(event, &defaultActionEnabled);
}
static void FirePopupWindowEvent(nsIDocument* aDoc)
{
// Fire a "PopupWindow" event
nsContentUtils::DispatchTrustedEvent(aDoc, aDoc,
NS_LITERAL_STRING("PopupWindow"),
true, true);
}
// static
bool
nsGlobalWindow::CanSetProperty(const char *aPrefName)
@ -7608,13 +7624,9 @@ nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
return abuse;
}
/* If a window open is blocked, fire the appropriate DOM events.
aBlocked signifies we just blocked a popup.
aWindow signifies we just opened what is probably a popup.
*/
/* If a window open is blocked, fire the appropriate DOM events. */
void
nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
const nsAString &aPopupURL,
nsGlobalWindow::FireAbuseEvents(const nsAString &aPopupURL,
const nsAString &aPopupWindowName,
const nsAString &aPopupWindowFeatures)
{
@ -7645,13 +7657,8 @@ nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL,
getter_AddRefs(popupURI));
// fire an event chock full of informative URIs
if (aBlocked) {
FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
aPopupWindowFeatures);
}
if (aWindow)
FirePopupWindowEvent(topDoc);
FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
aPopupWindowFeatures);
}
already_AddRefed<nsIDOMWindow>
@ -7675,9 +7682,11 @@ nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
nsresult
nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions, nsPIDOMWindow **_retval)
const nsAString& aOptions, nsIDocShellLoadInfo* aLoadInfo,
bool aForceNoOpener, nsPIDOMWindow **_retval)
{
FORWARD_TO_OUTER(Open, (aUrl, aName, aOptions, _retval),
FORWARD_TO_OUTER(Open, (aUrl, aName, aOptions, aLoadInfo, aForceNoOpener,
_retval),
NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIDOMWindow> window;
nsresult rv = OpenInternal(aUrl, aName, aOptions,
@ -7687,6 +7696,8 @@ nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
false, // aDoJSFixups
true, // aNavigate
nullptr, nullptr, // No args
aLoadInfo,
aForceNoOpener,
GetPrincipal(), // aCalleePrincipal
nullptr, // aJSCallerContext
getter_AddRefs(window));
@ -7708,6 +7719,8 @@ nsGlobalWindow::OpenJS(const nsAString& aUrl, const nsAString& aName,
true, // aDoJSFixups
true, // aNavigate
nullptr, nullptr, // No args
nullptr, // aLoadInfo
false, // aForceNoOpener
GetPrincipal(), // aCalleePrincipal
nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
_retval);
@ -7728,6 +7741,8 @@ nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
false, // aDoJSFixups
true, // aNavigate
nullptr, aExtraArgument, // Arguments
nullptr, // aLoadInfo
false, // aForceNoOpener
GetPrincipal(), // aCalleePrincipal
nullptr, // aJSCallerContext
_retval);
@ -7748,6 +7763,8 @@ nsGlobalWindow::OpenNoNavigate(const nsAString& aUrl,
false, // aDoJSFixups
false, // aNavigate
nullptr, nullptr, // No args
nullptr, // aLoadInfo
false, // aForceNoOpener
GetPrincipal(), // aCalleePrincipal
nullptr, // aJSCallerContext
_retval);
@ -7778,6 +7795,8 @@ nsGlobalWindow::OpenDialogOuter(JSContext* aCx, const nsAString& aUrl,
false, // aDoJSFixups
true, // aNavigate
argvArray, nullptr, // Arguments
nullptr, // aLoadInfo
false, // aForceNoOpener
GetPrincipal(), // aCalleePrincipal
aCx, // aJSCallerContext
getter_AddRefs(dialog));
@ -8858,6 +8877,8 @@ nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgumen
true, // aDoJSFixups
true, // aNavigate
nullptr, argHolder, // args
nullptr, // aLoadInfo
false, // aForceNoOpener
GetPrincipal(), // aCalleePrincipal
nullptr, // aJSCallerContext
getter_AddRefs(dlgWin));
@ -11292,6 +11313,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
bool aDoJSFixups, bool aNavigate,
nsIArray *argv,
nsISupports *aExtraArgument,
nsIDocShellLoadInfo* aLoadInfo,
bool aForceNoOpener,
nsIPrincipal *aCalleePrincipal,
JSContext *aJSCallerContext,
nsIDOMWindow **aReturn)
@ -11333,8 +11356,32 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
nsIPrincipal::APP_STATUS_INSTALLED;
}
nsAutoCString options;
bool forceNoOpener = aForceNoOpener;
// Unlike other window flags, "noopener" comes from splitting on commas with
// HTML whitespace trimming...
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
aOptions, ',');
while (tok.hasMoreTokens()) {
auto nextTok = tok.nextToken();
if (nextTok.EqualsLiteral("noopener")) {
forceNoOpener = true;
continue;
}
// Want to create a copy of the options without 'noopener' because having
// 'noopener' in the options affects other window features.
if (!options.IsEmpty()) {
options.Append(',');
}
AppendUTF16toUTF8(nextTok, options);
}
// XXXbz When this gets fixed to not use LegacyIsCallerNativeCode()
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
// But note that if you change this to GetEntryGlobal(), say, then
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript.
const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
!isApp && !aDialog && !WindowExists(aName, !aCalledNoScript);
!isApp && !aDialog && !WindowExists(aName, forceNoOpener, !aCalledNoScript);
// Note: it's very important that this be an nsXPIDLCString, since we want
// .get() on it to return nullptr until we write stuff to it. The window
@ -11377,7 +11424,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
}
}
FireAbuseEvents(true, false, aUrl, aName, aOptions);
FireAbuseEvents(aUrl, aName, aOptions);
return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
}
}
@ -11388,15 +11435,21 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
NS_ENSURE_TRUE(wwatch, rv);
NS_ConvertUTF16toUTF8 options(aOptions);
NS_ConvertUTF16toUTF8 name(aName);
const char *options_ptr = aOptions.IsEmpty() ? nullptr : options.get();
const char *options_ptr = options.IsEmpty() ? nullptr : options.get();
const char *name_ptr = aName.IsEmpty() ? nullptr : name.get();
nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
NS_ENSURE_STATE(pwwatch);
MOZ_ASSERT_IF(checkForPopup, abuseLevel < openAbused);
// At this point we should know for a fact that if checkForPopup then
// abuseLevel < openAbused, so we could just check for abuseLevel ==
// openControlled. But let's be defensive just in case and treat anything
// that fails the above assert as a spam popup too, if it ever happens.
bool isPopupSpamWindow = checkForPopup && (abuseLevel >= openControlled);
{
// Reset popup state while opening a window to prevent the
// current state from being active the whole time a modal
@ -11409,6 +11462,9 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
/* aCalledFromScript = */ true,
aDialog, aNavigate, nullptr, argv,
isPopupSpamWindow,
forceNoOpener,
aLoadInfo,
getter_AddRefs(domReturn));
} else {
// Force a system caller here so that the window watcher won't screw us
@ -11425,10 +11481,12 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
nojsapi.emplace();
}
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
/* aCalledFromScript = */ false,
aDialog, aNavigate, nullptr, aExtraArgument,
isPopupSpamWindow,
forceNoOpener,
aLoadInfo,
getter_AddRefs(domReturn));
}
@ -11463,18 +11521,6 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
}
}
if (checkForPopup) {
if (abuseLevel >= openControlled) {
nsGlobalWindow *opened = static_cast<nsGlobalWindow *>(*aReturn);
if (!opened->IsPopupSpamWindow()) {
opened->SetPopupSpamWindow(true);
++gOpenPopupSpamCount;
}
}
if (abuseLevel >= openAbused)
FireAbuseEvents(false, true, aUrl, aName, aOptions);
}
return rv;
}

View File

@ -901,7 +901,10 @@ public:
const nsAString& aOptions,
mozilla::ErrorResult& aError);
nsresult Open(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions, nsPIDOMWindow **_retval) override;
const nsAString& aOptions,
nsIDocShellLoadInfo* aLoadInfo,
bool aForceNoOpener,
nsPIDOMWindow **_retval) override;
mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
nsIDOMNavigator* GetNavigator() override;
nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
@ -1308,7 +1311,7 @@ protected:
}
}
void FreeInnerObjects();
void FreeInnerObjects(bool aForDocumentOpen = false);
nsGlobalWindow *CallerInnerWindow();
// Only to be called on an inner window.
@ -1321,6 +1324,7 @@ protected:
// Get the parent, returns null if this is a toplevel window
nsIDOMWindow* GetParentInternal();
public:
// popup tracking
bool IsPopupSpamWindow()
{
@ -1331,17 +1335,10 @@ protected:
return GetOuterWindowInternal()->mIsPopupSpam;
}
void SetPopupSpamWindow(bool aPopup)
{
if (IsInnerWindow() && !mOuterWindow) {
NS_ERROR("SetPopupSpamWindow() called on inner window w/o an outer!");
return;
}
GetOuterWindowInternal()->mIsPopupSpam = aPopup;
}
// Outer windows only.
void SetIsPopupSpamWindow(bool aIsPopupSpam);
protected:
// Window Control Functions
// Outer windows only.
@ -1386,15 +1383,21 @@ private:
* three args, if present, will be aUrl, aName, and aOptions. So this
* param only matters if there are more than 3 arguments.
*
* @param argc The number of arguments in argv.
*
* @param aExtraArgument Another way to pass arguments in. This is mutually
* exclusive with the argv/argc approach.
* exclusive with the argv approach.
*
* @param aLoadInfo to be passed on along to the windowwatcher.
*
* @param aForceNoOpener if true, will act as if "noopener" were passed in
* aOptions, but without affecting any other window
* features.
*
* @param aJSCallerContext The calling script's context. This must be null
* when aCalledNoScript is true.
*
* @param aReturn [out] The window that was opened, if any.
* @param aReturn [out] The window that was opened, if any. Will be null if
* aForceNoOpener is true of if aOptions contains
* "noopener".
*
* Outer windows only.
*/
@ -1408,6 +1411,8 @@ private:
bool aNavigate,
nsIArray *argv,
nsISupports *aExtraArgument,
nsIDocShellLoadInfo* aLoadInfo,
bool aForceNoOpener,
nsIPrincipal *aCalleePrincipal,
JSContext *aJSCallerContext,
nsIDOMWindow **aReturn);
@ -1471,8 +1476,7 @@ public:
bool PopupWhitelisted();
PopupControlState RevisePopupAbuseLevel(PopupControlState);
void FireAbuseEvents(bool aBlocked, bool aWindow,
const nsAString &aPopupURL,
void FireAbuseEvents(const nsAString &aPopupURL,
const nsAString &aPopupWindowName,
const nsAString &aPopupWindowFeatures);
void FireOfflineStatusEventIfChanged();
@ -1538,7 +1542,8 @@ public:
// If aLookForCallerOnJSStack is true, this method will look at the JS stack
// to determine who the caller is. If it's false, it'll use |this| as the
// caller.
bool WindowExists(const nsAString& aName, bool aLookForCallerOnJSStack);
bool WindowExists(const nsAString& aName, bool aForceNoOpener,
bool aLookForCallerOnJSStack);
already_AddRefed<nsIWidget> GetMainWidget();
nsIWidget* GetNearestWidget() const;

View File

@ -1684,6 +1684,7 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
endCCTime = PR_Now();
}
#if(0)
// Log information about the CC via telemetry, JSON and the console.
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_FINISH_IGC, gCCStats.mAnyLockedOut);
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_SYNC_SKIPPABLE, gCCStats.mRanSyncForgetSkippable);
@ -1695,10 +1696,11 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
uint32_t timeBetween = TimeBetween(sLastCCEndTime, gCCStats.mBeginTime) / 1000;
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_TIME_BETWEEN, timeBetween);
}
#endif
sLastCCEndTime = endCCTimeStamp;
Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_MAX,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
// Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_MAX,
// sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
PRTime delta = GetCollectionTimeDelta();

View File

@ -22,6 +22,7 @@
#include "nsIExternalProtocolHandler.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIObjectFrame.h"
#include "nsIOService.h"
#include "nsIPermissionManager.h"
#include "nsPluginHost.h"
#include "nsPluginInstanceOwner.h"
@ -2525,7 +2526,13 @@ nsObjectLoadingContent::OpenChannel()
true, // aInheritForAboutBlank
false); // aForceInherit
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
if (inherit) {
bool isData;
bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() &&
NS_SUCCEEDED(mURI->SchemeIs("data", &isData)) &&
isData;
if (inherit && !isURIUniqueOrigin) {
securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
if (isSandBoxed) {

View File

@ -25,6 +25,7 @@ class nsIArray;
class nsIContent;
class nsICSSDeclaration;
class nsIDocShell;
class nsIDocShellLoadInfo;
class nsIDocument;
class nsIIdleObserver;
class nsIScriptTimeoutHandler;
@ -795,8 +796,14 @@ public:
virtual already_AddRefed<nsISelection> GetSelection() = 0;
virtual already_AddRefed<nsPIDOMWindow> GetOpener() = 0;
virtual already_AddRefed<nsIDOMWindowCollection> GetFrames() = 0;
// aLoadInfo will be passed on through to the windowwatcher.
// aForceNoOpener will act just like a "noopener" feature in aOptions except
// will not affect any other window features.
virtual nsresult Open(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions, nsPIDOMWindow **_retval) = 0;
const nsAString& aOptions,
nsIDocShellLoadInfo* aLoadInfo,
bool aForceNoOpener,
nsPIDOMWindow **_retval) = 0;
virtual nsresult OpenDialog(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions,
nsISupports* aExtraArgument, nsIDOMWindow** _retval) = 0;

View File

@ -42,6 +42,7 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
// static
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
"noreferrer",
"noopener",
nullptr
};

View File

@ -5576,8 +5576,13 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
const char* name = aName.IsVoid() ? nullptr : NS_ConvertUTF16toUTF8(aName).get();
const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
#if(0)
// Needs update for issue 522
*aResult = pwwatch->OpenWindow2(parent, uri, name, features, aCalledFromJS,
false, false, thisTabParent, nullptr, getter_AddRefs(window));
#else
MOZ_ASSERT(0);
#endif
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;

View File

@ -1327,6 +1327,7 @@ static bool
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
{
MOZ_ASSERT(false, "See bug 1114580, 2f9eb93beee9"); // NYI XXX TenFourFox 392
NPObject *npobj = GetNPObject(cx, obj);
if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||

View File

@ -608,6 +608,13 @@ private:
nullptr,
nullptr,
false, false, true, nullptr, nullptr,
// Not a spammy popup; we got permission, we swear!
/* aIsPopupSpam = */ false,
// Don't force noopener. We're not passing in an
// opener anyway, and we _do_ want the returned
// window.
/* aForceNoOpener = */ false,
/* aLoadInfo = */ nullptr,
getter_AddRefs(newWindow));
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(newWindow);
pwindow.forget(aWindow);

View File

@ -16,8 +16,9 @@ interface nsIWebBrowserChrome;
interface nsIDocShellTreeItem;
interface nsIArray;
interface nsITabParent;
interface nsIDocShellLoadInfo;
[uuid(0f2d9d75-c46b-4114-802e-83b4655e61d2)]
[uuid(0f2d9d75-c46b-4114-802e-83b4655e61d3)]
interface nsPIWindowWatcher : nsISupports
{
@ -56,6 +57,18 @@ interface nsPIWindowWatcher : nsISupports
nsITabParent is a remote tab belonging to aParent. Can
be nullptr if this window is not being opened from a tab.
@param aArgs Window argument
@param aIsPopupSpam true if the window is a popup spam window; used for
popup blocker internals.
@param aForceNoOpener If true, force noopener behavior. This means not
looking for existing windows with the given name,
not setting an opener on the newly opened window,
and returning null from this method.
@param aLoadInfo if aNavigate is true, this allows the caller to pass in
an nsIDocShellLoadInfo to use for the navigation.
Callers can pass in null if they want the windowwatcher
to just construct a loadinfo itself. If aNavigate is
false, this argument is ignored.
@return the new window
@note This method may examine the JS context stack for purposes of
@ -70,7 +83,10 @@ interface nsPIWindowWatcher : nsISupports
in string aName, in string aFeatures,
in boolean aCalledFromScript, in boolean aDialog,
in boolean aNavigate, in nsITabParent aOpeningTab,
in nsISupports aArgs);
in nsISupports aArgs,
in boolean aIsPopupSpam,
in boolean aForceNoOpener,
in nsIDocShellLoadInfo aLoadInfo);
/**
* Find a named docshell tree item amongst all windows registered

View File

@ -18,6 +18,7 @@
#include "nsJSUtils.h"
#include "plstr.h"
#include "nsGlobalWindow.h"
#include "nsIBaseWindow.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIDocShell.h"
@ -366,7 +367,11 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow* aParent,
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
/* calledFromJS = */ false, dialog,
/* navigate = */ true, nullptr, argv, aResult);
/* navigate = */ true, nullptr, argv,
/* aIsPopupSpam = */ false,
/* aForceNoOpener = */ false,
/* aLoadInfo = */ nullptr,
aResult);
}
struct SizeSpec
@ -424,6 +429,9 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent,
bool aNavigate,
nsITabParent* aOpeningTab,
nsISupports* aArguments,
bool aIsPopupSpam,
bool aForceNoOpener,
nsIDocShellLoadInfo* aLoadInfo,
nsIDOMWindow** aResult)
{
nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
@ -443,7 +451,11 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent,
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
aCalledFromScript, dialog,
aNavigate, aOpeningTab, argv, aResult);
aNavigate, aOpeningTab, argv,
aIsPopupSpam,
aForceNoOpener,
aLoadInfo,
aResult);
}
nsresult
@ -456,6 +468,9 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
bool aNavigate,
nsITabParent* aOpeningTab,
nsIArray* aArgv,
bool aIsPopupSpam,
bool aForceNoOpener,
nsIDocShellLoadInfo* aLoadInfo,
nsIDOMWindow** aResult)
{
nsresult rv = NS_OK;
@ -531,7 +546,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
// know or care about names - unless we're opening named windows from chrome.
if (!aOpeningTab) {
// try to find an extant window with the given name
nsCOMPtr<nsIDOMWindow> foundWindow = SafeGetWindowByName(name, aParent);
nsCOMPtr<nsIDOMWindow> foundWindow =
SafeGetWindowByName(name, aForceNoOpener, aParent);
GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
}
@ -828,7 +844,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
}
}
rv = ReadyOpenedDocShellItem(newDocShellItem, aParent, windowIsNew, aResult);
rv = ReadyOpenedDocShellItem(newDocShellItem, aParent, windowIsNew,
aForceNoOpener, aResult);
if (NS_FAILED(rv)) {
return rv;
}
@ -900,6 +917,16 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
// SetInitialPrincipalToSubject is safe to call multiple times.
if (newWindow) {
newWindow->SetInitialPrincipalToSubject();
if (aIsPopupSpam) {
nsGlobalWindow* globalWin = static_cast<nsGlobalWindow*>(newWindow.get());
MOZ_ASSERT(!globalWin->IsPopupSpamWindow(),
"Who marked it as popup spam already???");
if (!globalWin->IsPopupSpamWindow()) { // Make sure we don't mess up our
// counter even if the above
// assert fails.
globalWin->SetIsPopupSpamWindow(true);
}
}
}
}
@ -944,8 +971,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
}
}
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
if (uriToLoad && aNavigate) {
nsCOMPtr<nsIDocShellLoadInfo> loadInfo = aLoadInfo;
if (uriToLoad && aNavigate && !loadInfo) {
newDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
@ -1069,6 +1096,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
}
}
if (aForceNoOpener && windowIsNew) {
NS_RELEASE(*aResult);
}
return NS_OK;
}
@ -1857,8 +1888,18 @@ nsWindowWatcher::GetCallerTreeItem(nsIDocShellTreeItem* aParentItem)
nsPIDOMWindow*
nsWindowWatcher::SafeGetWindowByName(const nsAString& aName,
bool aForceNoOpener,
nsIDOMWindow* aCurrentWindow)
{
if (aForceNoOpener) {
if (!aName.LowerCaseEqualsLiteral("_self") &&
!aName.LowerCaseEqualsLiteral("_top") &&
!aName.LowerCaseEqualsLiteral("_parent")) {
// Ignore all other names in the noopener case.
return nullptr;
}
}
nsCOMPtr<nsIDocShellTreeItem> startItem;
GetWindowTreeItem(aCurrentWindow, getter_AddRefs(startItem));
@ -1887,6 +1928,7 @@ nsresult
nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
nsIDOMWindow* aParent,
bool aWindowIsNew,
bool aForceNoOpener,
nsIDOMWindow** aOpenedWindow)
{
nsresult rv = NS_ERROR_FAILURE;
@ -1897,7 +1939,9 @@ nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
nsCOMPtr<nsPIDOMWindow> piOpenedWindow = aOpenedItem->GetWindow();
if (piOpenedWindow) {
if (aParent) {
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
if (!aForceNoOpener) {
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
}
if (aWindowIsNew) {
#ifdef DEBUG

View File

@ -70,7 +70,9 @@ protected:
// Unlike GetWindowByName this will look for a caller on the JS
// stack, and then fall back on aCurrentWindow if it can't find one.
// It also knows to not look for things if aForceNoOpener is set.
nsPIDOMWindow* SafeGetWindowByName(const nsAString& aName,
bool aForceNoOpener,
nsIDOMWindow* aCurrentWindow);
// Just like OpenWindowJS, but knows whether it got called via OpenWindowJS
@ -84,6 +86,9 @@ protected:
bool aNavigate,
nsITabParent* aOpeningTab,
nsIArray* aArgv,
bool aIsPopupSpam,
bool aForceNoOpener,
nsIDocShellLoadInfo* aLoadInfo,
nsIDOMWindow** aResult);
static nsresult URIfromURL(const char* aURL,
@ -105,6 +110,7 @@ protected:
static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
nsIDOMWindow* aParent,
bool aWindowIsNew,
bool aForceNoOpener,
nsIDOMWindow** aOpenedWindow);
static void SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
nsIDOMWindow* aParent,

View File

@ -164,7 +164,7 @@ NS_IMETHODIMP mozEnglishWordUtils::FindNextWord(const char16_t *word, uint32_t l
// before we spend more time looking to see if the word is a url, look for a url identifer
// and make sure that identifer isn't the last character in the word fragment.
if ( (*p == ':' || *p == '@' || *p == '.') && p < endbuf - 1) {
if ((p < endbuf - 1) && (*p == ':' || *p == '@' || *p == '.')) {
// ok, we have a possible url...do more research to find out if we really have one
// and determine the length of the url so we can skip over it.

View File

@ -847,6 +847,10 @@ enum ESClassValue {
ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer,
ESClass_Date, ESClass_Set, ESClass_Map,
/** Not yet implemented (TenFourFox issue 392). */
ESClass_Promise, ESClass_MapIterator, ESClass_SetIterator,
ESClass_Arguments, ESClass_Error,
/** None of the above. */
ESClass_Other
};

View File

@ -6429,7 +6429,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line, unsigned* c
AsmJSParseContext* outerpc = m.parser().pc;
Directives directives(outerpc);
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator);
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator, SyncFunction);
if (!funbox)
return false;

View File

@ -732,6 +732,7 @@ function ArrayValuesAt(n) {
function ArrayValues() {
return CreateArrayIterator(this, ITEM_KIND_VALUE);
}
_SetCanonicalName(ArrayValues, "values");
function ArrayEntries() {
return CreateArrayIterator(this, ITEM_KIND_KEY_AND_VALUE);

View File

@ -88,6 +88,7 @@ function LegacyGeneratorNext(val) {
throw e;
}
}
_SetCanonicalName(LegacyGeneratorNext, "next");
function LegacyGeneratorThrow(val) {
if (!IsObject(this) || !IsLegacyGeneratorObject(this))

View File

@ -100,8 +100,8 @@ function removeUnicodeExtensions(locale) {
if (pos < 0)
pos = locale.length;
var left = callFunction(std_String_substring, locale, 0, pos);
var right = callFunction(std_String_substring, locale, pos);
var left = callFunction(String_substring, locale, 0, pos);
var right = callFunction(String_substring, locale, pos);
var extensions;
var unicodeLocaleExtensionSequenceRE = getUnicodeLocaleExtensionSequenceRE();
@ -332,7 +332,7 @@ function IsStructurallyValidLanguageTag(locale) {
return true;
var pos = callFunction(std_String_indexOf, locale, "-x-");
if (pos !== -1)
locale = callFunction(std_String_substring, locale, 0, pos);
locale = callFunction(String_substring, locale, 0, pos);
// Check for duplicate variant or singleton subtags.
var duplicateVariantRE = getDuplicateVariantRE();
@ -401,7 +401,7 @@ function CanonicalizeLanguageTag(locale) {
// 4-character subtags are script codes; their first character
// needs to be capitalized. "hans" -> "Hans"
subtag = callFunction(std_String_toUpperCase, subtag[0]) +
callFunction(std_String_substring, subtag, 1);
callFunction(String_substring, subtag, 1);
} else if (i !== 0 && subtag.length === 2) {
// 2-character subtags that are not in initial position are region
// codes; they need to be upper case. "bu" -> "BU"
@ -678,7 +678,7 @@ function CanonicalizeLocaleList(locales) {
if (!IsStructurallyValidLanguageTag(tag))
ThrowRangeError(JSMSG_INVALID_LANGUAGE_TAG, tag);
tag = CanonicalizeLanguageTag(tag);
if (callFunction(std_Array_indexOf, seen, tag) === -1)
if (callFunction(ArrayIndexOf, seen, tag) === -1)
callFunction(std_Array_push, seen, tag);
}
k++;
@ -726,7 +726,7 @@ function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLoca
if (pos >= 2 && candidate[pos - 2] === "-")
pos -= 2;
candidate = callFunction(std_String_substring, candidate, 0, pos);
candidate = callFunction(String_substring, candidate, 0, pos);
}
}
@ -879,7 +879,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 11.g.
if (extensionSubtags !== undefined) {
// Step 11.g.i.
var keyPos = callFunction(std_Array_indexOf, extensionSubtags, key);
var keyPos = callFunction(ArrayIndexOf, extensionSubtags, key);
// Step 11.g.ii.
if (keyPos !== -1) {
@ -891,7 +891,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
var requestedValue = extensionSubtags[keyPos + 1];
// Step 11.g.ii.1.b.
valuePos = callFunction(std_Array_indexOf, keyLocaleData, requestedValue);
valuePos = callFunction(ArrayIndexOf, keyLocaleData, requestedValue);
// Step 11.g.ii.1.c.
if (valuePos !== -1) {
@ -905,7 +905,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// and true is an allowed value, it's used.
// Step 11.g.ii.2.a.
valuePos = callFunction(std_Array_indexOf, keyLocaleData, "true");
valuePos = callFunction(ArrayIndexOf, keyLocaleData, "true");
// Step 11.g.ii.2.b.
if (valuePos !== -1)
@ -921,7 +921,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 11.h, 11.h.ii.
if (optionsValue !== undefined &&
callFunction(std_Array_indexOf, keyLocaleData, optionsValue) !== -1)
callFunction(ArrayIndexOf, keyLocaleData, optionsValue) !== -1)
{
// Step 11.h.ii.1.
if (optionsValue !== value) {
@ -938,8 +938,8 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 12.
if (supportedExtension.length > 2) {
var preExtension = callFunction(std_String_substring, foundLocale, 0, extensionIndex);
var postExtension = callFunction(std_String_substring, foundLocale, extensionIndex);
var preExtension = callFunction(String_substring, foundLocale, 0, extensionIndex);
var postExtension = callFunction(String_substring, foundLocale, extensionIndex);
foundLocale = preExtension + supportedExtension + postExtension;
}
@ -1060,7 +1060,7 @@ function GetOption(options, property, type, values, fallback) {
assert(false, "GetOption");
// Step 2.d.
if (values !== undefined && callFunction(std_Array_indexOf, values, value) === -1)
if (values !== undefined && callFunction(ArrayIndexOf, values, value) === -1)
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, property, value);
// Step 2.e.
@ -2612,8 +2612,8 @@ function BasicFormatMatcher(options, formats) {
score -= removalPenalty;
} else {
// Step 11.c.vi.
var optionsPropIndex = callFunction(std_Array_indexOf, values, optionsProp);
var formatPropIndex = callFunction(std_Array_indexOf, values, formatProp);
var optionsPropIndex = callFunction(ArrayIndexOf, values, optionsProp);
var formatPropIndex = callFunction(ArrayIndexOf, values, formatProp);
var delta = std_Math_max(std_Math_min(formatPropIndex - optionsPropIndex, 2), -2);
if (delta === 2)
score -= longMorePenalty;

View File

@ -25,7 +25,7 @@ function MapForEach(callbackfn, thisArg = undefined) {
/* Step 6-8. */
var entries = callFunction(std_Map_iterator, M);
while (true) {
var result = callFunction(std_Map_iterator_next, entries);
var result = callFunction(MapIteratorNext, entries);
if (result.done)
break;
var entry = result.value;
@ -88,3 +88,4 @@ function MapSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(MapSpecies, "get [Symbol.species]");

View File

@ -171,7 +171,8 @@ GlobalObject::initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, base));
if (!proto)
return false;
if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods))
if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods) ||
!DefineToStringTag(cx, proto, cx->names().MapIterator))
return false;
global->setReservedSlot(MAP_ITERATOR_PROTO, ObjectValue(*proto));
return true;
@ -320,6 +321,10 @@ MapObject::initClass(JSContext* cx, JSObject* obj)
RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0))
return nullptr;
// Define Map.prototype[@@toStringTag].
if (!DefineToStringTag(cx, proto, cx->names().Map))
return nullptr;
}
return proto;
}
@ -897,7 +902,8 @@ GlobalObject::initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, base));
if (!proto)
return false;
if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods))
if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods) ||
!DefineToStringTag(cx, proto, cx->names().SetIterator))
return false;
global->setReservedSlot(SET_ITERATOR_PROTO, ObjectValue(*proto));
return true;
@ -1051,6 +1057,10 @@ SetObject::initClass(JSContext* cx, JSObject* obj)
RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0))
return nullptr;
// Define Set.prototype[@@toStringTag].
if (!DefineToStringTag(cx, proto, cx->names().Set))
return nullptr;
}
return proto;
}

View File

@ -306,63 +306,141 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
}
#endif /* JS_HAS_TOSOURCE */
JSString*
JS_BasicObjectToString(JSContext* cx, HandleObject obj)
{
// Some classes are really common, don't allocate new strings for them.
// The ordering below is based on the measurements in bug 966264.
if (obj->is<PlainObject>())
return cx->names().objectObject;
if (obj->is<StringObject>())
return cx->names().objectString;
if (obj->is<ArrayObject>())
return cx->names().objectArray;
if (obj->is<JSFunction>())
return cx->names().objectFunction;
if (obj->is<NumberObject>())
return cx->names().objectNumber;
const char* className = GetObjectClassName(cx, obj);
if (strcmp(className, "Window") == 0)
return cx->names().objectWindow;
StringBuffer sb(cx);
if (!sb.append("[object ") || !sb.append(className, strlen(className)) ||
!sb.append("]"))
{
return nullptr;
}
return sb.finishString();
}
/* ES5 15.2.4.2. Note steps 1 and 2 are errata. */
/* ES6 19.1.3.6 (after bug 1114580/TenFourFox issue 392) */
bool
js::obj_toString(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
// Step 1.
if (args.thisv().isUndefined()) {
args.rval().setString(cx->names().objectUndefined);
return true;
}
/* Step 2. */
// Step 2.
if (args.thisv().isNull()) {
args.rval().setString(cx->names().objectNull);
return true;
}
/* Step 3. */
// Step 3.
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
/* Steps 4-5. */
JSString* str = JS_BasicObjectToString(cx, obj);
// Step 4.
bool isArray;
if (!IsArray(cx, obj, &isArray))
return false;
// Step 5.
RootedString builtinTag(cx);
if (isArray) {
builtinTag = cx->names().objectArray;
} else {
// Steps 6-13.
ESClassValue cls;
if (!GetBuiltinClass(cx, obj, &cls))
return false;
switch (cls) {
case ESClass_String:
builtinTag = cx->names().objectString;
break;
case ESClass_Arguments: // NYI XXX
builtinTag = cx->names().objectArguments;
break;
case ESClass_Error: // NYI XXX
builtinTag = cx->names().objectError;
break;
case ESClass_Boolean:
builtinTag = cx->names().objectBoolean;
break;
case ESClass_Number:
builtinTag = cx->names().objectNumber;
break;
case ESClass_Date:
builtinTag = cx->names().objectDate;
break;
case ESClass_RegExp:
builtinTag = cx->names().objectRegExp;
break;
default:
if (obj->isCallable()) {
// Non-standard: Prevent <object> from showing up as Function.
RootedObject unwrapped(cx, CheckedUnwrap(obj));
if (!unwrapped || !unwrapped->getClass()->isDOMClass())
builtinTag = cx->names().objectFunction;
}
break;
}
}
// Step 14.
// Currently omitted for non-standard fallback.
// Step 15.
RootedValue tag(cx);
RootedId toStringTagId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag));
if (!GetProperty(cx, obj, obj, toStringTagId, &tag)) {
if (IsProxy(obj)) {
// XXX: This is a dirty hack for jit-test/tests/basic/bug807623.js.
// Just pass through if the property lookup fails; assume that we
// didn't have a tag set in that situation. Proxy::get sets the tag
// to undefined for us in that case. TenFourFox issue 392.
//
// Note that this isn't an issue for current Firefox because
// Proxy.create() was removed. We can't do this because of our
// backwards compatibility, and other tests also rely on it
// currently (see M892903), but fortunately using proper ES6 Proxy
// methods works as expected even without this hack:
//
// var h={}; var p=new Proxy({[Symbol.toStringTag]:"abc"}, h);
// print(Object.prototype.toString.call(p)); /* [object abc] */
//
// Thus, this code path is only entered in the legacy case, which
// shouldn't know about @@toStringTag anyway.
//
RootedValue receiver(cx, ObjectValue(*obj));
(void)proxy_GetProperty(cx, obj, receiver, toStringTagId, &tag);
cx->clearPendingException();
} else
return false;
}
// Step 16.
if (!tag.isString()) {
// Non-standard (bug 1277801): Use ClassName as a fallback in the interim
if (!builtinTag) {
const char* className = GetObjectClassName(cx, obj);
StringBuffer sb(cx);
if (!sb.append("[object ") || !sb.append(className, strlen(className)) ||
!sb.append("]"))
{
return false;
}
builtinTag = sb.finishString();
if (!builtinTag)
return false;
}
args.rval().setString(builtinTag);
return true;
}
// Step 17.
StringBuffer sb(cx);
if (!sb.append("[object ") || !sb.append(tag.toString()) || !sb.append("]"))
return false;
RootedString str(cx, sb.finishString());
if (!str)
return false;
args.rval().setString(str);
return true;
}

View File

@ -35,6 +35,7 @@ function RegExpFlagsGetter() {
// Step 19.
return result;
}
_SetCanonicalName(RegExpFlagsGetter, "get flags");
// ES6 draft rc1 21.2.5.14.
function RegExpToString()
@ -53,3 +54,4 @@ function RegExpToString()
// Step 7.
return '/' + pattern + '/' + flags;
}
_SetCanonicalName(RegExpToString, "toString");

View File

@ -34,6 +34,11 @@
// stored.
#define LAZY_FUNCTION_NAME_SLOT 0
// The extended slot which contains a boolean value that indicates whether
// that the canonical name of the self-hosted builtins is set in self-hosted
// global. This slot is used only in debug build.
#define HAS_SELFHOSTED_CANONICAL_NAME_SLOT 0
// Stores the private WeakMap slot used for WeakSets
#define WEAKSET_MAP_SLOT 0

View File

@ -38,3 +38,4 @@ function SetSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(SetSpecies, "get [Symbol.species]");

View File

@ -277,7 +277,7 @@ function StringIteratorNext() {
}
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
result.value = callFunction(std_String_substring, S, index, index + charCount);
result.value = callFunction(String_substring, S, index, index + charCount);
return result;
}
@ -482,14 +482,14 @@ function EscapeAttributeValue(v) {
var chunkStart = 0;
for (var i = 0; i < inputLen; i++) {
if (inputStr[i] === '"') {
outputStr += callFunction(std_String_substring, inputStr, chunkStart, i) + '&quot;';
outputStr += callFunction(String_substring, inputStr, chunkStart, i) + '&quot;';
chunkStart = i + 1;
}
}
if (chunkStart === 0)
return inputStr;
if (chunkStart < inputLen)
outputStr += callFunction(std_String_substring, inputStr, chunkStart);
outputStr += callFunction(String_substring, inputStr, chunkStart);
return outputStr;
}

View File

@ -79,6 +79,7 @@ SymbolObject::initClass(JSContext* cx, HandleObject obj)
if (!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
!DefineToStringTag(cx, proto, cx->names().Symbol) ||
!DefinePropertiesAndFunctions(cx, ctor, nullptr, staticMethods) ||
!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Symbol, ctor, proto))
{

View File

@ -964,6 +964,7 @@ function TypedArrayValues() {
// Step 7.
return CreateArrayIterator(O, ITEM_KIND_VALUE);
}
_SetCanonicalName(TypedArrayValues, "values");
// Proposed for ES7:
// https://github.com/tc39/Array.prototype.includes/blob/7c023c19a0/spec.md
@ -1166,3 +1167,25 @@ function TypedArrayStaticOf(/*...items*/) {
// Step 8.
return newObj;
}
// ES 2016 draft Mar 25, 2016 22.2.2.4.
function TypedArraySpecies() {
// Step 1.
return this;
}
// ES 2017 draft June 2, 2016 22.2.3.32
function TypedArrayToStringTag() {
// Step 1.
var O = this;
// Steps 2-3.
if (!IsObject(O) || !IsTypedArray(O))
return undefined;
// Steps 4-6.
// Modified to retrieve the [[TypedArrayName]] from the constructor.
return _NameForTypedArray(O);
}
_SetCanonicalName(TypedArrayToStringTag, "get [Symbol.toStringTag]");

View File

@ -36,15 +36,13 @@
// code are installed via the std_functions JSFunctionSpec[] in
// SelfHosting.cpp.
//
// The few items below here are either self-hosted or installing them under a
// std_Foo name would require ugly contortions, so they just get aliased here.
var std_Array_indexOf = ArrayIndexOf;
var std_String_substring = String_substring;
// Do not create an alias to a self-hosted builtin, otherwise it will be cloned
// twice.
//
// WeakMap is a bare constructor without properties or methods.
var std_WeakMap = WeakMap;
// StopIteration is a bare constructor without properties or methods.
var std_StopIteration = StopIteration;
var std_Map_iterator_next = MapIteratorNext;
/********** List specification type **********/
@ -152,6 +150,19 @@ function GetIterator(obj, method) {
return iterator;
}
var _builtinCtorsCache = {__proto__: null};
function GetBuiltinConstructor(builtinName) {
var ctor = _builtinCtorsCache[builtinName] ||
(_builtinCtorsCache[builtinName] = GetBuiltinConstructorImpl(builtinName));
assert(ctor, `No builtin with name "${builtinName}" found`);
return ctor;
}
function GetBuiltinPrototype(builtinName) {
return (_builtinCtorsCache[builtinName] || GetBuiltinConstructor(builtinName)).prototype;
}
// ES6 draft 20150317 7.3.20.
function SpeciesConstructor(obj, defaultConstructor) {
// Step 1.

View File

@ -455,6 +455,8 @@ InitWeakMapClass(JSContext* cx, HandleObject obj, bool defineMembers)
if (defineMembers) {
if (!DefinePropertiesAndFunctions(cx, proto, nullptr, weak_map_methods))
return nullptr;
if (!DefineToStringTag(cx, proto, cx->names().WeakMap))
return nullptr;
}
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakMap, ctor, proto))

View File

@ -53,6 +53,7 @@ WeakSetObject::initClass(JSContext* cx, JSObject* obj)
if (!ctor ||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
!DefineToStringTag(cx, proto, cx->names().WeakSet) ||
!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakSet, ctor, proto))
{
return nullptr;

View File

@ -312,6 +312,7 @@ BytecodeCompiler::saveCallerFun(HandleScript evalCaller)
Directives directives(/* strict = */ options.strictOption);
ObjectBox* funbox = parser->newFunctionBox(/* fn = */ nullptr, fun,
directives, fun->generatorKind(),
fun->asyncKind(),
enclosingStaticScope);
if (!funbox)
return false;
@ -635,7 +636,7 @@ BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun,
ParseNode* fn;
do {
Directives newDirectives = directives;
fn = parser->standaloneFunctionBody(fun, formals, generatorKind, directives,
fn = parser->standaloneFunctionBody(fun, formals, generatorKind, SyncFunction, directives,
&newDirectives, enclosingStaticScope);
if (!fn && !handleParseFailure(newDirectives))
return false;
@ -796,7 +797,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
MOZ_ASSERT(!lazy->isLegacyGenerator());
ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind());
ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind(), lazy->asyncKind());
if (!pn)
return false;

View File

@ -6401,6 +6401,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA);
pn->setOp(JSOP_FUNWITHPROTO);
}
if (pn->getOp() == JSOP_DEFFUN) {
if (!emitIndex32(JSOP_LAMBDA, index))
return false;
return emit1(JSOP_DEFFUN);
}
return emitIndex32(pn->getOp(), index);
}
@ -6441,7 +6448,9 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
MOZ_ASSERT(pn->pn_scopecoord.isFree());
MOZ_ASSERT(pn->getOp() == JSOP_NOP);
switchToPrologue();
if (!emitIndex32(JSOP_DEFFUN, index))
if (!emitIndex32(JSOP_LAMBDA, index))
return false;
if (!emit1(JSOP_DEFFUN))
return false;
if (!updateSourceCoordNotes(pn->pn_pos.begin))
return false;

View File

@ -689,7 +689,8 @@ Parser<FullParseHandler>::cloneParseTree(ParseNode* opn)
RootedFunction fun(context, opn->pn_funbox->function());
NULLCHECK(pn->pn_funbox = newFunctionBox(pn, fun, pc,
Directives(/* strict = */ opn->pn_funbox->strict()),
opn->pn_funbox->generatorKind()));
opn->pn_funbox->generatorKind(),
opn->pn_funbox->asyncKind()));
NULLCHECK(pn->pn_body = cloneParseTree(opn->pn_body));
pn->pn_scopecoord = opn->pn_scopecoord;
pn->pn_dflags = opn->pn_dflags;

View File

@ -30,6 +30,7 @@
#include "asmjs/AsmJSValidate.h"
#include "builtin/ModuleObject.h"
#include "builtin/SelfHostingDefines.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/FoldConstants.h"
#include "frontend/ParseMaps.h"
@ -760,7 +761,8 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
template <typename ParseHandler>
FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* outerpc,
Directives directives, bool extraWarnings, GeneratorKind generatorKind)
Directives directives, bool extraWarnings, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
: ObjectBox(fun, traceListHead),
SharedContext(cx, directives, extraWarnings),
bindings(),
@ -771,6 +773,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
startColumn(0),
length(0),
generatorKindBits_(GeneratorKindAsBits(generatorKind)),
asyncKindBits_(AsyncKindAsBits(asyncKind)),
inGenexpLambda(false),
hasDestructuringArgs(false),
useAsm(false),
@ -794,6 +797,7 @@ Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
ParseContext<ParseHandler>* outerpc,
Directives inheritedDirectives,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
JSObject* enclosingStaticScope)
{
MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope());
@ -809,7 +813,7 @@ Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun,
FunctionBox* funbox =
alloc.new_<FunctionBox>(context, traceListHead, fun, enclosingStaticScope, outerpc,
inheritedDirectives, options().extraWarningsOption,
generatorKind);
generatorKind, asyncKind);
if (!funbox) {
ReportOutOfMemory(context);
return nullptr;
@ -1140,6 +1144,7 @@ ParseNode*
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
Handle<PropertyNameVector> formals,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
Directives inheritedDirectives,
Directives* newDirectives,
HandleObject enclosingStaticScope)
@ -1155,7 +1160,7 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
return null();
fn->pn_body = argsbody;
FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind,
FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind, asyncKind,
enclosingStaticScope);
if (!funbox)
return null();
@ -1606,7 +1611,8 @@ struct BindData
template <typename ParseHandler>
JSFunction*
Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
GeneratorKind generatorKind, HandleObject proto)
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
HandleObject proto)
{
MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
@ -1614,6 +1620,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
JSFunction::Flags flags;
#ifdef DEBUG
bool isGlobalSelfHostedBuiltin = false;
#endif
switch (kind) {
case Expression:
flags = (generatorKind == NotGenerator
@ -1647,6 +1656,13 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
break;
default:
MOZ_ASSERT(kind == Statement);
#ifdef DEBUG
if (options().selfHostingMode && !pc->sc->isFunctionBox()) {
isGlobalSelfHostedBuiltin = true;
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
}
#endif
flags = (generatorKind == NotGenerator
? JSFunction::INTERPRETED_NORMAL
: JSFunction::INTERPRETED_GENERATOR);
@ -1656,8 +1672,13 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind, TenuredObject);
if (!fun)
return nullptr;
if (options().selfHostingMode)
if (options().selfHostingMode) {
fun->setIsSelfHostedBuiltin();
#ifdef DEBUG
if (isGlobalSelfHostedBuiltin)
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(false));
#endif
}
return fun;
}
@ -2507,7 +2528,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
RootedFunction fun(context, handler.nextLazyInnerFunction());
MOZ_ASSERT(!fun->isLegacyGenerator());
FunctionBox* funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false),
fun->generatorKind());
fun->generatorKind(), fun->asyncKind());
if (!funbox)
return false;
@ -2715,11 +2736,12 @@ Parser<ParseHandler>::templateLiteral(YieldHandling yieldHandling)
return nodeList;
}
/* ::functionDefinition */
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHandling,
HandlePropertyName funName, FunctionSyntaxKind kind,
GeneratorKind generatorKind, InvokedPrediction invoked,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, InvokedPrediction invoked,
Node* assignmentForAnnexBOut)
{
MOZ_ASSERT_IF(kind == Statement, funName);
@ -2750,7 +2772,7 @@ Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHand
if (!proto)
return null();
}
RootedFunction fun(context, newFunction(funName, kind, generatorKind, proto));
RootedFunction fun(context, newFunction(funName, kind, generatorKind, asyncKind, proto));
if (!fun)
return null();
@ -2765,7 +2787,7 @@ Parser<ParseHandler>::functionDef(InHandling inHandling, YieldHandling yieldHand
tokenStream.tell(&start);
while (true) {
if (functionArgsAndBody(inHandling, pn, fun, kind, generatorKind, directives,
if (functionArgsAndBody(inHandling, pn, fun, kind, generatorKind, asyncKind, directives,
&newDirectives))
{
break;
@ -2836,6 +2858,7 @@ Parser<SyntaxParseHandler>::finishFunctionDefinition(Node pn, FunctionBox* funbo
if (pc->sc->strict())
lazy->setStrict();
lazy->setGeneratorKind(funbox->generatorKind());
lazy->setAsyncKind(funbox->asyncKind());
if (funbox->isLikelyConstructorWrapper())
lazy->setLikelyConstructorWrapper();
if (funbox->isDerivedClassConstructor())
@ -2848,18 +2871,19 @@ Parser<SyntaxParseHandler>::finishFunctionDefinition(Node pn, FunctionBox* funbo
return true;
}
/* ::trySyntaxParseInnerFunction */
template <>
bool
Parser<FullParseHandler>::functionArgsAndBody(InHandling inHandling, ParseNode* pn,
HandleFunction fun, FunctionSyntaxKind kind,
GeneratorKind generatorKind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
Directives inheritedDirectives,
Directives* newDirectives)
{
ParseContext<FullParseHandler>* outerpc = pc;
// Create box for fun->object early to protect against last-ditch GC.
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, asyncKind);
if (!funbox)
return false;
@ -2953,13 +2977,14 @@ bool
Parser<SyntaxParseHandler>::functionArgsAndBody(InHandling inHandling, Node pn, HandleFunction fun,
FunctionSyntaxKind kind,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
Directives inheritedDirectives,
Directives* newDirectives)
{
ParseContext<SyntaxParseHandler>* outerpc = pc;
// Create box for fun->object early to protect against last-ditch GC.
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, asyncKind);
if (!funbox)
return false;
@ -3003,7 +3028,8 @@ Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
template <>
ParseNode*
Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict,
GeneratorKind generatorKind)
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
{
MOZ_ASSERT(checkOptionsCalled);
@ -3018,7 +3044,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
RootedObject enclosing(context, fun->lazyScript()->enclosingScope());
Directives directives(/* strict = */ strict);
FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, enclosing);
FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, asyncKind, enclosing);
if (!funbox)
return null();
funbox->length = fun->nargs() - fun->hasRest();
@ -3226,7 +3252,7 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
Node assignmentForAnnexB;
Node fun = functionDef(InAllowed, yieldHandling, name, Statement, generatorKind,
PredictUninvoked, &assignmentForAnnexB);
SyncFunction, PredictUninvoked, &assignmentForAnnexB);
if (!fun)
return null();
@ -3284,7 +3310,7 @@ Parser<ParseHandler>::functionExpr(InvokedPrediction invoked)
}
YieldHandling yieldHandling = generatorKind != NotGenerator ? YieldIsKeyword : YieldIsName;
return functionDef(InAllowed, yieldHandling, name, Expression, generatorKind, invoked);
return functionDef(InAllowed, yieldHandling, name, Expression, generatorKind, SyncFunction, invoked);
}
/*
@ -7748,7 +7774,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
return null();
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator, SyncFunction);
if (!arrowFunc)
return null();
@ -8626,13 +8652,13 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
}
RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression,
comprehensionKind, proto));
comprehensionKind, SyncFunction, proto));
if (!fun)
return null();
// Create box for fun->object early to root it.
Directives directives(/* strict = */ outerpc->sc->strict());
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind);
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind, SyncFunction);
if (!genFunbox)
return null();
@ -9872,7 +9898,7 @@ Parser<ParseHandler>::methodDefinition(YieldHandling yieldHandling, PropertyType
{
FunctionSyntaxKind kind = FunctionSyntaxKindFromPropertyType(propType);
GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType);
return functionDef(InAllowed, yieldHandling, funName, kind, generatorKind);
return functionDef(InAllowed, yieldHandling, funName, kind, generatorKind, SyncFunction);
}
template <typename ParseHandler>

View File

@ -126,6 +126,10 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
bool isStarGenerator() const { return generatorKind() == StarGenerator; }
bool isAsync() const {
return sc->isFunctionBox() && sc->asFunctionBox()->isAsync();
}
bool isArrowFunction() const {
return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow();
}
@ -579,22 +583,26 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
ObjectBox* newObjectBox(JSObject* obj);
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* outerpc,
Directives directives, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
JSObject* enclosingStaticScope);
// Use when the funbox is the outermost.
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
GeneratorKind generatorKind, HandleObject enclosingStaticScope)
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
HandleObject enclosingStaticScope)
{
return newFunctionBox(fn, fun, nullptr, directives, generatorKind,
asyncKind,
enclosingStaticScope);
}
// Use when the funbox should be linked to the outerpc's innermost scope.
FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext<ParseHandler>* outerpc,
Directives directives, GeneratorKind generatorKind)
Directives directives, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
{
RootedObject enclosing(context, outerpc->innermostStaticScope());
return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing);
return newFunctionBox(fn, fun, outerpc, directives, generatorKind, asyncKind, enclosing);
}
ModuleBox* newModuleBox(Node pn, HandleModuleObject module);
@ -604,7 +612,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
* a function expression).
*/
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind,
HandleObject proto);
FunctionAsyncKind asyncKind, HandleObject proto);
bool generateBlockId(JSObject* staticScope, uint32_t* blockIdOut) {
if (blockScopes.length() == StmtInfoPC::BlockIdLimit) {
@ -671,12 +679,15 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
// Generator constructors.
Node standaloneFunctionBody(HandleFunction fun, Handle<PropertyNameVector> formals,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
Directives inheritedDirectives, Directives* newDirectives,
HandleObject enclosingStaticScope);
// Parse a function, given only its arguments and body. Used for lazily
// parsed functions.
Node standaloneLazyFunction(HandleFunction fun, bool strict, GeneratorKind generatorKind);
Node standaloneLazyFunction(HandleFunction fun, bool strict,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind);
/*
* Parse a function body. Pass StatementListBody if the body is a list of
@ -874,10 +885,12 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node functionDef(InHandling inHandling, YieldHandling uieldHandling, HandlePropertyName name,
FunctionSyntaxKind kind, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
InvokedPrediction invoked = PredictUninvoked,
Node* assignmentForAnnexBOut = nullptr);
bool functionArgsAndBody(InHandling inHandling, Node pn, HandleFunction fun,
FunctionSyntaxKind kind, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
Directives inheritedDirectives, Directives* newDirectives);
Node unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin);

View File

@ -333,6 +333,7 @@ class FunctionBox : public ObjectBox, public SharedContext
uint16_t length;
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
uint8_t asyncKindBits_; /* The FunctionAsyncKing of this function. */
bool inGenexpLambda:1; /* lambda from generator expression */
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
bool useAsm:1; /* see useAsmOrInsideUseAsm */
@ -350,7 +351,8 @@ class FunctionBox : public ObjectBox, public SharedContext
template <typename ParseHandler>
FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
JSObject* enclosingStaticScope, ParseContext<ParseHandler>* pc,
Directives directives, bool extraWarnings, GeneratorKind generatorKind);
Directives directives, bool extraWarnings, GeneratorKind generatorKind,
FunctionAsyncKind asyncKind);
ObjectBox* toObjectBox() override { return this; }
JSFunction* function() const { return &object->as<JSFunction>(); }
@ -365,6 +367,8 @@ class FunctionBox : public ObjectBox, public SharedContext
bool isGenerator() const { return generatorKind() != NotGenerator; }
bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
bool isStarGenerator() const { return generatorKind() == StarGenerator; }
FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
bool isAsync() const { return asyncKind() == AsyncFunction; }
bool isArrow() const { return function()->isArrow(); }
void setGeneratorKind(GeneratorKind kind) {

View File

@ -107,6 +107,7 @@
macro(THROW, "keyword 'throw'") \
macro(DEBUGGER, "keyword 'debugger'") \
macro(YIELD, "keyword 'yield'") \
macro(AWAIT, "keyword 'await'") \
macro(LET, "keyword 'let'") \
macro(EXPORT, "keyword 'export'") \
macro(IMPORT, "keyword 'import'") \

View File

@ -981,6 +981,12 @@ TokenStream::putIdentInTokenbuf(const char16_t* identStart)
bool
TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
{
if (!awaitIsKeyword && kw->tokentype == TOK_AWAIT) {
if (ttp)
*ttp = TOK_NAME;
return true;
}
if (kw->tokentype == TOK_RESERVED)
return reportError(JSMSG_RESERVED_ID, kw->chars);

View File

@ -32,6 +32,8 @@ struct KeywordInfo;
namespace js {
namespace frontend {
class AutoAwaitIsKeyword;
struct TokenPos {
uint32_t begin; // Offset of the token's first char.
uint32_t end; // Offset of 1 past the token's last char.
@ -452,6 +454,9 @@ class MOZ_STACK_CLASS TokenStream
{}
};
bool awaitIsKeyword = false;
friend class AutoAwaitIsKeyword;
public:
typedef Token::Modifier Modifier;
static MOZ_CONSTEXPR_VAR Modifier None = Token::None;
@ -1034,6 +1039,25 @@ class MOZ_STACK_CLASS TokenStream
StrictModeGetter* strictModeGetter; // used to test for strict mode
};
class MOZ_STACK_CLASS AutoAwaitIsKeyword
{
private:
TokenStream* ts_;
bool oldAwaitIsKeyword_;
public:
AutoAwaitIsKeyword(TokenStream* ts, bool awaitIsKeyword) {
ts_ = ts;
oldAwaitIsKeyword_ = ts_->awaitIsKeyword;
ts_->awaitIsKeyword = awaitIsKeyword;
}
~AutoAwaitIsKeyword() {
ts_->awaitIsKeyword = oldAwaitIsKeyword_;
ts_ = nullptr;
}
};
// Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error
// message have const char16_t* type, not const char*.
#define JSREPORT_UC 0x100

View File

@ -13,11 +13,7 @@ assertEq(Map.length, 0);
assertEq(Map.name, "Map");
assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype);
assertEq("toStringTag" in Symbol, false,
"if this fails, congratulations! implement " +
"Map.prototype[Symbol.toStringTag] = 'Map' in SpiderMonkey and make " +
"the next test check for '[object Map]' again");
assertEq(Object.prototype.toString.call(Map.prototype), "[object Object]");
assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]");
assertEq(Object.prototype.toString.call(new Map()), "[object Map]");
assertEq(Object.keys(Map.prototype).join(), "");
assertEq(Map.prototype.constructor, Map);

View File

@ -13,11 +13,7 @@ assertEq(Set.length, 0);
assertEq(Set.name, "Set");
assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype);
assertEq("toStringTag" in Symbol, false,
"if this fails, congratulations! implement " +
"Set.prototype[Symbol.toStringTag] = 'Set' in SpiderMonkey and make " +
"the next test check for '[object Set]' again");
assertEq(Object.prototype.toString.call(Set.prototype), "[object Object]");
assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]");
assertEq(Object.prototype.toString.call(new Set()), "[object Set]");
assertEq(Object.keys(Set.prototype).join(), "");
assertEq(Set.prototype.constructor, Set);

View File

@ -11,7 +11,7 @@ assertEq(WeakMap.length, 0);
assertEq(WeakMap.name, "WeakMap");
assertEq(Object.getPrototypeOf(WeakMap.prototype), Object.prototype);
assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object Object]");
assertEq(Object.prototype.toString.call(WeakMap.prototype), "[object WeakMap]");
assertEq(Object.prototype.toString.call(new WeakMap()), "[object WeakMap]");
assertEq(Object.keys(WeakMap.prototype).join(), "");
assertEq(WeakMap.prototype.constructor, WeakMap);

View File

@ -11,7 +11,7 @@ assertEq(WeakSet.length, 0);
assertEq(WeakSet.name, "WeakSet");
assertEq(Object.getPrototypeOf(WeakSet.prototype), Object.prototype);
assertEq(Object.prototype.toString.call(WeakSet.prototype), "[object Object]");
assertEq(Object.prototype.toString.call(WeakSet.prototype), "[object WeakSet]");
assertEq(Object.prototype.toString.call(new WeakSet), "[object WeakSet]");
assertEq(Object.keys(WeakSet.prototype).length, 0);
assertEq(WeakSet.prototype.constructor, WeakSet);

View File

@ -9,13 +9,9 @@ function test(constructor) {
var iter = new constructor()[Symbol.iterator]();
assertDeepEq(Reflect.ownKeys(iter), []);
// Iterator prototypes only have a .next property.
// At least until we support @@toStringTag.
// Iterator prototypes only have a .next and @@toStringTag property.
var proto1 = Object.getPrototypeOf(iter);
var names = Reflect.ownKeys(proto1);
names.sort();
assertDeepEq(Reflect.ownKeys(proto1), ['next']);
assertDeepEq(Reflect.ownKeys(proto1), ['next', Symbol.toStringTag]);
var desc = Object.getOwnPropertyDescriptor(proto1, 'next');
assertEq(desc.configurable, true);

View File

@ -12,7 +12,7 @@ dbg.onDebuggerStatement = function (frame) {
assertEq(arr[3].class, "Date");
assertEq(arr[4].class, "Object");
assertEq(arr[5].class, "Function");
assertEq(arr[6].class, "Date");
assertEq(arr[6].class, "Object");
hits++;
};
g.f(Object.prototype, [], eval, new Date,

View File

@ -11,8 +11,8 @@ var p2 = r2.proxy;
assertThrowsInstanceOf(() => ({} instanceof p), TypeError);
assertThrowsInstanceOf(() => ({} instanceof p2), TypeError);
assertEq(Object.prototype.toString.call(p), "[object Object]");
assertEq(Object.prototype.toString.call(p2), "[object Function]");
assertThrowsInstanceOf(() => Object.prototype.toString.call(p), TypeError);
assertThrowsInstanceOf(() => Object.prototype.toString.call(p2), TypeError);
assertThrowsInstanceOf(() => RegExp.prototype.exec.call(p, ""), TypeError);
assertThrowsInstanceOf(() => RegExp.prototype.exec.call(p2, ""), TypeError);

View File

@ -0,0 +1,13 @@
let getCtor = getSelfHostedValue('GetBuiltinConstructor');
assertEq(getCtor('Array'), Array);
let origArray = Array;
Array = function(){};
assertEq(getCtor('Array') == Array, false);
assertEq(getCtor('Array'), origArray);
let origMap = Map;
Map = function(){};
assertEq(getCtor('Map') == Map, false);
assertEq(getCtor('Map'), origMap);

View File

@ -2679,15 +2679,14 @@ static const VMFunction DefFunOperationInfo = FunctionInfo<DefFunOperationFn>(De
bool
BaselineCompiler::emit_JSOP_DEFFUN()
{
RootedFunction fun(cx, script->getFunction(GET_UINT32_INDEX(pc)));
frame.syncStack(0);
masm.loadPtr(frame.addressOfScopeChain(), R0.scratchReg());
frame.popRegsAndSync(1);
masm.unboxObject(R0, R0.scratchReg());
masm.loadPtr(frame.addressOfScopeChain(), R1.scratchReg());
prepareVMCall();
pushArg(ImmGCPtr(fun));
pushArg(R0.scratchReg());
pushArg(R1.scratchReg());
pushArg(ImmGCPtr(script));
return callVM(DefFunOperationInfo);

View File

@ -4368,7 +4368,8 @@ CodeGenerator::visitDefFun(LDefFun* lir)
{
Register scopeChain = ToRegister(lir->scopeChain());
pushArg(ImmGCPtr(lir->mir()->fun()));
Register fun = ToRegister(lir->fun());
pushArg(fun);
pushArg(scopeChain);
pushArg(ImmGCPtr(current->mir()->info().script()));

View File

@ -12927,13 +12927,9 @@ IonBuilder::jsop_deflexical(uint32_t index)
bool
IonBuilder::jsop_deffun(uint32_t index)
{
JSFunction* fun = script()->getFunction(index);
if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
return abort("asm.js module function");
MOZ_ASSERT(analysis().usesScopeChain());
MDefFun* deffun = MDefFun::New(alloc(), fun, current->scopeChain());
MDefFun* deffun = MDefFun::New(alloc(), current->pop(), current->scopeChain());
current->add(deffun);
return resumeAfter(deffun);

View File

@ -164,7 +164,11 @@ LIRGenerator::visitDefLexical(MDefLexical* ins)
void
LIRGenerator::visitDefFun(MDefFun* ins)
{
LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(ins->scopeChain()));
MDefinition* fun = ins->fun();
MOZ_ASSERT(fun->type() == MIRType_Object);
LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(fun),
useRegisterAtStart(ins->scopeChain()));
add(lir, ins);
assignSafepoint(lir, ins);
}

View File

@ -7423,30 +7423,28 @@ class MDefLexical
};
class MDefFun
: public MUnaryInstruction,
public NoTypePolicy::Data
: public MBinaryInstruction,
public SingleObjectPolicy::Data
{
CompilerFunction fun_;
private:
MDefFun(JSFunction* fun, MDefinition* scopeChain)
: MUnaryInstruction(scopeChain),
fun_(fun)
MDefFun(MDefinition* fun, MDefinition* scopeChain)
: MBinaryInstruction(fun, scopeChain)
{}
public:
INSTRUCTION_HEADER(DefFun)
static MDefFun* New(TempAllocator& alloc, JSFunction* fun, MDefinition* scopeChain) {
static MDefFun* New(TempAllocator& alloc, MDefinition* fun, MDefinition* scopeChain) {
return new(alloc) MDefFun(fun, scopeChain);
}
JSFunction* fun() const {
return fun_;
}
MDefinition* scopeChain() const {
MDefinition* fun() const {
return getOperand(0);
}
MDefinition* scopeChain() const {
return getOperand(1);
}
bool possiblyCalls() const override {
return true;
}

View File

@ -1238,19 +1238,23 @@ class LDefLexical : public LCallInstructionHelper<0, 0, 0>
}
};
class LDefFun : public LCallInstructionHelper<0, 1, 0>
class LDefFun : public LCallInstructionHelper<0, 2, 0>
{
public:
LIR_HEADER(DefFun)
explicit LDefFun(const LAllocation& scopeChain)
LDefFun(const LAllocation& fun, const LAllocation& scopeChain)
{
setOperand(0, scopeChain);
setOperand(0, fun);
setOperand(1, scopeChain);
}
const LAllocation* scopeChain() {
const LAllocation* fun() {
return getOperand(0);
}
const LAllocation* scopeChain() {
return getOperand(1);
}
MDefFun* mir() const {
return mir_->toDefFun();
}

View File

@ -35,6 +35,7 @@ static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
void
MacroAssemblerX86::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
{
#error check TenFourFox issue 526 and bug 1499198. may be safest to just always use the SSE2 routine
// SUBPD needs SSE2, HADDPD needs SSE3.
if (!HasSSE3()) {
convertUInt32ToDouble(src.high, dest);

View File

@ -4561,6 +4561,7 @@ GetSymbolDescription(HandleSymbol symbol);
macro(match) \
macro(species) \
macro(toPrimitive) \
macro(toStringTag) \
macro(unscopables)
enum class SymbolCode : uint32_t {

View File

@ -291,6 +291,13 @@ class JSFunction : public js::NativeObject
flags_ |= RESOLVED_NAME;
}
void setAsyncKind(js::FunctionAsyncKind asyncKind) {
if (isInterpretedLazy())
lazyScript()->setAsyncKind(asyncKind);
else
nonLazyScript()->setAsyncKind(asyncKind);
}
JSAtom* atom() const { return hasGuessedAtom() ? nullptr : atom_.get(); }
js::PropertyName* name() const {
@ -299,6 +306,8 @@ class JSFunction : public js::NativeObject
void initAtom(JSAtom* atom) { atom_.init(atom); }
void setAtom(JSAtom* atom) { atom_ = atom; }
JSAtom* displayAtom() const {
return atom_;
}
@ -471,6 +480,18 @@ class JSFunction : public js::NativeObject
bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
js::FunctionAsyncKind asyncKind() const {
return isInterpretedLazy() ? lazyScript()->asyncKind() : nonLazyScript()->asyncKind();
}
bool isAsync() const {
if (isInterpretedLazy())
return lazyScript()->asyncKind() == js::AsyncFunction;
if (hasScript())
return nonLazyScript()->asyncKind() == js::AsyncFunction;
return false;
}
void setScript(JSScript* script_) {
mutableScript() = script_;
}

View File

@ -1473,7 +1473,9 @@ GlobalObject::initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global
const Class* cls = &ArrayIteratorPrototypeClass;
RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto));
if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods))
if (!proto ||
!DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods) ||
!DefineToStringTag(cx, proto, cx->names().ArrayIterator))
return false;
global->setReservedSlot(ARRAY_ITERATOR_PROTO, ObjectValue(*proto));
@ -1492,7 +1494,9 @@ GlobalObject::initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> globa
const Class* cls = &StringIteratorPrototypeClass;
RootedObject proto(cx, global->createBlankPrototypeInheriting(cx, cls, iteratorProto));
if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, string_iterator_methods))
if (!proto ||
!DefinePropertiesAndFunctions(cx, proto, nullptr, string_iterator_methods) ||
!DefineToStringTag(cx, proto, cx->names().StringIterator))
return false;
global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto));

View File

@ -1647,6 +1647,8 @@ js::InitMathClass(JSContext* cx, HandleObject obj)
return nullptr;
if (!JS_DefineConstDoubles(cx, Math, math_constants))
return nullptr;
if (!DefineToStringTag(cx, Math, cx->names().Math))
return nullptr;
obj->as<GlobalObject>().setConstructor(JSProto_Math, ObjectValue(*Math));

View File

@ -954,6 +954,9 @@ js::InitJSONClass(JSContext* cx, HandleObject obj)
if (!JS_DefineFunctions(cx, JSON, json_static_methods))
return nullptr;
if (!DefineToStringTag(cx, JSON, cx->names().JSON))
return nullptr;
global->setConstructor(JSProto_JSON, ObjectValue(*JSON));
return JSON;

View File

@ -867,6 +867,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
return false;
if (mode == XDR_DECODE) {
/* XXX: AsyncFunction and isAsync not implemented. */
if (!JSScript::partiallyInit(cx, script, nconsts, nobjects, nregexps, ntrynotes,
nblockscopes, nyieldoffsets, nTypeSets))
{
@ -2751,6 +2752,7 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
script->setSourceObject(sourceObject);
script->sourceStart_ = bufStart;
script->sourceEnd_ = bufEnd;
script->isAsync_ = false;
return script;
}
@ -2915,6 +2917,7 @@ JSScript::linkToFunctionFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScrip
script->isGeneratorExp_ = funbox->inGenexpLambda;
script->setGeneratorKind(funbox->generatorKind());
script->setAsyncKind(funbox->asyncKind());
// Link the function and the script to each other, so that StaticScopeIter
// may walk the scope chain of currently compiling scripts.
@ -2940,6 +2943,7 @@ JSScript::linkToModuleFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScript*
script->funLength_ = 0;
script->isGeneratorExp_ = false;
script->isAsync_ = false;
script->setGeneratorKind(NotGenerator);
// Link the module and the script to each other, so that StaticScopeIter
@ -3575,6 +3579,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
dst->hasInnerFunctions_ = src->hasInnerFunctions();
dst->isGeneratorExp_ = src->isGeneratorExp();
dst->setGeneratorKind(src->generatorKind());
dst->isAsync_ = src->asyncKind() == AsyncFunction;
if (nconsts != 0) {
HeapValue* vector = Rebase<HeapValue>(dst, src, src->consts()->vector);
@ -4275,6 +4280,7 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
// Reset runtime flags to obtain a fresh LazyScript.
p.hasBeenCloned = false;
p.treatAsRunOnce = false;
p.isAsync = false;
size_t bytes = (p.numFreeVariables * sizeof(FreeVariable))
+ (p.numInnerFunctions * sizeof(HeapPtrFunction));
@ -4306,6 +4312,7 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
p.version = version;
p.numFreeVariables = numFreeVariables;
p.isAsync = false;
p.numInnerFunctions = numInnerFunctions;
p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
p.strict = false;

View File

@ -894,6 +894,7 @@ class ScriptSourceObject : public NativeObject
};
enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
enum FunctionAsyncKind { SyncFunction, AsyncFunction };
static inline unsigned
GeneratorKindAsBits(GeneratorKind generatorKind) {
@ -906,6 +907,17 @@ GeneratorKindFromBits(unsigned val) {
return static_cast<GeneratorKind>(val);
}
static inline unsigned
AsyncKindAsBits(FunctionAsyncKind asyncKind) {
return static_cast<unsigned>(asyncKind);
}
static inline FunctionAsyncKind
AsyncKindFromBits(unsigned val) {
MOZ_ASSERT(val <= AsyncFunction);
return static_cast<FunctionAsyncKind>(val);
}
/*
* NB: after a successful XDR_DECODE, XDRScript callers must do any required
* subsequent set-up of owning function or script object and then call
@ -1190,6 +1202,8 @@ class JSScript : public js::gc::TenuredCell
bool isDerivedClassConstructor_:1;
bool isAsync_:1;
// Add padding so JSScript is gc::Cell aligned. Make padding protected
// instead of private to suppress -Wunused-private-field compiler warnings.
protected:
@ -1456,6 +1470,14 @@ class JSScript : public js::gc::TenuredCell
generatorKindBits_ = GeneratorKindAsBits(kind);
}
js::FunctionAsyncKind asyncKind() const {
return isAsync_ ? js::AsyncFunction : js::SyncFunction;
}
void setAsyncKind(js::FunctionAsyncKind kind) {
isAsync_ = kind == js::AsyncFunction;
}
void setNeedsHomeObject() {
needsHomeObject_ = true;
}
@ -2136,7 +2158,8 @@ class LazyScript : public gc::TenuredCell
// Assorted bits that should really be in ScriptSourceObject.
uint32_t version : 8;
uint32_t numFreeVariables : 24;
uint32_t numFreeVariables : 23;
uint32_t isAsync: 1;
uint32_t numInnerFunctions : 20;
uint32_t generatorKindBits : 2;
@ -2274,6 +2297,14 @@ class LazyScript : public gc::TenuredCell
p_.generatorKindBits = GeneratorKindAsBits(kind);
}
FunctionAsyncKind asyncKind() const {
return p_.isAsync ? AsyncFunction : SyncFunction;
}
void setAsyncKind(FunctionAsyncKind kind) {
p_.isAsync = kind == AsyncFunction;
}
bool strict() const {
return p_.strict;
}

View File

@ -1128,12 +1128,9 @@ const char*
ScriptedDirectProxyHandler::className(JSContext* cx, HandleObject proxy) const
{
// Right now the caller is not prepared to handle failures.
RootedObject target(cx, proxy->as<ProxyObject>().target());
if (!target)
return BaseProxyHandler::className(cx, proxy);
return GetObjectClassName(cx, target);
return BaseProxyHandler::className(cx, proxy);
}
JSString*
ScriptedDirectProxyHandler::fun_toString(JSContext* cx, HandleObject proxy,
unsigned indent) const

View File

@ -74,9 +74,7 @@ function TestGeneratorObjectPrototype() {
found_property_names.sort();
assertDeepEq(found_property_names, expected_property_names);
// No symbol properties, at least until we have @@toStringTag.
assertEq(Object.getOwnPropertySymbols(GeneratorObjectPrototype).length, 0);
assertDeepEq(Object.getOwnPropertySymbols(GeneratorObjectPrototype), [Symbol.toStringTag]);
}
TestGeneratorObjectPrototype();

View File

@ -0,0 +1,158 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/ */
// ES6 19.1.3.6 Object.prototype.toString ( )
function testToString() {
var tests = [
[undefined, "[object Undefined]"],
[null, "[object Null]"],
[[], "[object Array]"],
[new String("abc"), "[object String]"],
[(function () {return arguments;})(), "[object Arguments]"],
[(function () {"use strict"; return arguments;})(), "[object Arguments]"],
[function() {}, "[object Function]"],
[new Error("abc"), "[object Error]"],
[true, "[object Boolean]"],
[5, "[object Number]"],
[new Date(), "[object Date]"],
[/regexp/, "[object RegExp]"],
[{[Symbol.toStringTag]: "abc"}, "[object abc]"],
[Object.create(JSON), "[object JSON]"],
[Object.create(new Number), "[object Object]"],
[Object.create(new Number, {[Symbol.toStringTag]: {value: "abc"}}), "[object abc]"],
[(function() { var x = new Number(); x[Symbol.toStringTag] = "abc"; return x; })(), "[object abc]"],
[[], "[object Array]"]
];
// Testing if the values are obtained the right way.
for (let [value, expected] of tests) {
let result = Object.prototype.toString.call(value);
assertEq(result, expected);
}
}
testToString();
function testProxy() {
var count = 0;
var metaHandler = new Proxy({}, {
get(target, property, receiver) {
assertEq(property, "get");
return function(target, property, receiver) {
assertEq(property, Symbol.toStringTag);
count++;
return undefined;
}
}
});
assertEq(Object.prototype.toString.call(new Proxy({}, metaHandler)), "[object Object]")
assertEq(Object.prototype.toString.call(new Proxy(new Date, metaHandler)), "[object Object]")
assertEq(Object.prototype.toString.call(new Proxy([], metaHandler)), "[object Array]")
assertEq(Object.prototype.toString.call(new Proxy(function() {}, metaHandler)), "[object Function]")
var {proxy, revoke} = Proxy.revocable({}, metaHandler);
revoke();
assertThrowsInstanceOf(() => Object.prototype.toString.call(proxy), TypeError);
assertEq(count, 4);
}
testProxy();
// Tests the passed objects toStringTag values and ensures it's
// desc is writable: false, enumerable: false, configurable: true
function testDefault(object, expected) {
let desc = Object.getOwnPropertyDescriptor(object, Symbol.toStringTag);
assertEq(desc.value, expected);
assertEq(desc.writable, false);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, true);
}
// ES6 19.4.3.5 Symbol.prototype [ @@toStringTag ]
testDefault(Symbol.prototype, "Symbol");
// ES6 20.2.1.9 Math [ @@toStringTag ]
testDefault(Math, "Math");
// ES6 21.1.5.2.2 %StringIteratorPrototype% [ @@toStringTag ]
testDefault(""[Symbol.iterator]().__proto__, "String Iterator")
// ES6 22.1.5.2.2 %ArrayIteratorPrototype% [ @@toStringTag ]
testDefault([][Symbol.iterator]().__proto__, "Array Iterator")
// ES6 22.2.3.31 get %TypedArray%.prototype [ @@toStringTag ]
function testTypedArray() {
let ta = (new Uint8Array(0)).__proto__.__proto__;
let desc = Object.getOwnPropertyDescriptor(ta, Symbol.toStringTag);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, true);
assertEq(desc.set, undefined);
let get = desc.get;
assertEq(get.name, "get [Symbol.toStringTag]");
assertEq(get.call(3.14), undefined);
assertEq(get.call({}), undefined);
assertEq(get.call(ta), undefined);
let types = [
Int8Array,
Uint8Array,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array
];
for (let type of types) {
let array = new type(0);
assertEq(get.call(array), type.name);
assertEq(Object.prototype.toString.call(array), `[object ${type.name}]`);
}
}
testTypedArray();
// ES6 23.1.3.13 Map.prototype [ @@toStringTag ]
testDefault(Map.prototype, "Map");
// ES6 23.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ]
testDefault(new Map()[Symbol.iterator]().__proto__, "Map Iterator")
// ES6 23.2.3.12 Set.prototype [ @@toStringTag ]
testDefault(Set.prototype, "Set");
// ES6 23.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ]
testDefault(new Set()[Symbol.iterator]().__proto__, "Set Iterator")
// ES6 23.3.3.6 WeakMap.prototype [ @@toStringTag ]
testDefault(WeakMap.prototype, "WeakMap");
// ES6 23.4.3.5 WeakSet.prototype [ @@toStringTag ]
testDefault(WeakSet.prototype, "WeakSet");
// ES6 24.1.4.4 ArrayBuffer.prototype [ @@toStringTag ]
testDefault(ArrayBuffer.prototype, "ArrayBuffer");
// ES6 24.2.4.21 DataView.prototype[ @@toStringTag ]
testDefault(DataView.prototype, "DataView");
// ES6 24.3.3 JSON [ @@toStringTag ]
testDefault(JSON, "JSON");
// ES6 25.2.3.3 GeneratorFunction.prototype [ @@toStringTag ]
testDefault(function* () {}.constructor.prototype, "GeneratorFunction");
// ES6 25.3.1.5 Generator.prototype [ @@toStringTag ]
testDefault(function* () {}().__proto__.__proto__, "Generator");
// ES6 25.4.5.4 Promise.prototype [ @@toStringTag ]
// Not yet implemented!
if (typeof Promise !== "undefined")
testDefault(Promise.prototype, "Promise");
// AsyncFunction.prototype [ @@toStringTag ]
// Not yet implemented!
// testDefault(async function() {}.constructor.prototype, "AsyncFunction");
reportCompare(true, true);

View File

@ -82,7 +82,8 @@ if (typeof assertDeepEq === 'undefined') {
assertSameValue(ac, bc, msg);
switch (ac) {
case "[object Function]":
assertSameValue(Function_toString(a), Function_toString(b), msg);
if (typeof isProxy !== "undefined" && !isProxy(a) && !isProxy(b))
assertSameValue(Function_toString(a), Function_toString(b), msg);
}
}

View File

@ -1562,7 +1562,7 @@ function test() {
assertEq(Object.prototype.toString.apply(new Float32Array(0)), "[object Float32Array]");
assertEq(Object.prototype.toString.apply(new ArrayBuffer()), "[object ArrayBuffer]");
assertEq(Object.prototype.toString.apply(new DataView(view.buffer)), "[object DataView]");
assertEq(Object.prototype.toString.apply(DataView.prototype), "[object DataViewPrototype]");
assertEq(Object.prototype.toString.apply(DataView.prototype), "[object DataView]");
// Technically the spec requires these throw a TypeError -- right now. It's
// not clear this is desirable. Once we implement @@toStringTag we can see

View File

@ -1650,6 +1650,9 @@ js::InitArrayBufferClass(JSContext* cx, HandleObject obj)
if (!JS_DefineFunctions(cx, arrayBufferProto, ArrayBufferObject::jsfuncs))
return nullptr;
if (!DefineToStringTag(cx, arrayBufferProto, cx->names().ArrayBuffer))
return nullptr;
return arrayBufferProto;
}

View File

@ -18,11 +18,13 @@
macro(apply, apply, "apply") \
macro(arguments, arguments, "arguments") \
macro(as, as, "as") \
macro(ArrayIterator, ArrayIterator, "Array Iterator") \
macro(ArrayIteratorNext, ArrayIteratorNext, "ArrayIteratorNext") \
macro(ArrayType, ArrayType, "ArrayType") \
macro(ArrayValues, ArrayValues, "ArrayValues") \
macro(ArrayValuesAt, ArrayValuesAt, "ArrayValuesAt") \
macro(Async, Async, "Async") \
macro(await, await, "await") \
macro(breakdown, breakdown, "breakdown") \
macro(buffer, buffer, "buffer") \
macro(builder, builder, "builder") \
@ -98,6 +100,7 @@
macro(frame, frame, "frame") \
macro(from, from, "from") \
macro(gcCycleNumber, gcCycleNumber, "gcCycleNumber") \
macro(Generator, Generator, "Generator") \
macro(GeneratorFunction, GeneratorFunction, "GeneratorFunction") \
macro(get, get, "get") \
macro(getInternals, getInternals, "getInternals") \
@ -138,6 +141,7 @@
macro(keys, keys, "keys") \
macro(label, label, "label") \
macro(lastIndex, lastIndex, "lastIndex") \
macro(LegacyGenerator, LegacyGenerator, "LegacyGenerator") \
macro(LegacyGeneratorCloseInternal, LegacyGeneratorCloseInternal, "LegacyGeneratorCloseInternal") \
macro(length, length, "length") \
macro(let, let, "let") \
@ -147,6 +151,7 @@
macro(locale, locale, "locale") \
macro(lookupGetter, lookupGetter, "__lookupGetter__") \
macro(lookupSetter, lookupSetter, "__lookupSetter__") \
macro(MapIterator, MapIterator, "Map Iterator") \
macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
macro(message, message, "message") \
@ -170,15 +175,18 @@
macro(NumberFormat, NumberFormat, "NumberFormat") \
macro(NumberFormatFormatGet, NumberFormatFormatGet, "Intl_NumberFormat_format_get") \
macro(numeric, numeric, "numeric") \
macro(objectArray, objectArray, "[object Array]") \
macro(objectFunction, objectFunction, "[object Function]") \
macro(objectNull, objectNull, "[object Null]") \
macro(objectNumber, objectNumber, "[object Number]") \
macro(objectObject, objectObject, "[object Object]") \
macro(objects, objects, "objects") \
macro(objectString, objectString, "[object String]") \
macro(objectUndefined, objectUndefined, "[object Undefined]") \
macro(objectWindow, objectWindow, "[object Window]") \
macro(objectNull, objectNull, "[object Null]") \
macro(objectArray, objectArray, "[object Array]") \
macro(objectString, objectString, "[object String]") \
macro(objectArguments, objectArguments, "[object Arguments]") \
macro(objectFunction, objectFunction, "[object Function]") \
macro(objectError, objectError, "[object Error]") \
macro(objectBoolean, objectBoolean, "[object Boolean]") \
macro(objectNumber, objectNumber, "[object Number]") \
macro(objectDate, objectDate, "[object Date]") \
macro(objectRegExp, objectRegExp, "[object RegExp]") \
macro(objects, objects, "objects") \
macro(of, of, "of") \
macro(offset, offset, "offset") \
macro(optimizedOut, optimizedOut, "optimizedOut") \
@ -203,6 +211,7 @@
macro(scripts, scripts, "scripts") \
macro(sensitivity, sensitivity, "sensitivity") \
macro(set, set, "set") \
macro(SetIterator, SetIterator, "Set Iterator") \
macro(shape, shape, "shape") \
macro(signMask, signMask, "signMask") \
macro(size, size, "size") \
@ -214,6 +223,7 @@
macro(static, static_, "static") \
macro(sticky, sticky, "sticky") \
macro(strings, strings, "strings") \
macro(StringIterator, StringIterator, "String Iterator") \
macro(StructType, StructType, "StructType") \
macro(style, style, "style") \
macro(super, super, "super") \
@ -276,6 +286,7 @@
macro(match, match, "match") \
macro(species, species, "species") \
macro(toPrimitive, toPrimitive, "toPrimitive") \
macro(toStringTag, toStringTag, "toStringTag") \
macro(unscopables, unscopables, "unscopables") \
/* Same goes for the descriptions of the well-known symbols. */ \
macro(Symbol_hasInstance, Symbol_hasInstance, "Symbol.hasInstance") \
@ -284,6 +295,7 @@
macro(Symbol_match, Symbol_match, "Symbol.match") \
macro(Symbol_species, Symbol_species, "Symbol.species") \
macro(Symbol_toPrimitive, Symbol_toPrimitive, "Symbol.toPrimitive") \
macro(Symbol_toStringTag, Symbol_toStringTag, "Symbol.toStringTag") \
macro(Symbol_unscopables, Symbol_unscopables, "Symbol.unscopables") \
/* Function names for properties named by symbols. */ \
macro(Symbol_iterator_fun, Symbol_iterator_fun, "[Symbol.iterator]") \

View File

@ -282,7 +282,14 @@ GlobalObject::initLegacyGeneratorProto(JSContext* cx, Handle<GlobalObject*> glob
RootedObject proto(cx, NewSingletonObjectWithObjectPrototype(cx, global));
if (!proto || !proto->setDelegate(cx))
return false;
#if(0)
/* XXX: Stub @@toStringTag for legacy generators.
TenFourFox issue 392 */
if (!DefinePropertiesAndFunctions(cx, proto, nullptr, legacy_generator_methods) ||
!DefineToStringTag(cx, proto, cx->names().LegacyGenerator))
#else
if (!DefinePropertiesAndFunctions(cx, proto, nullptr, legacy_generator_methods))
#endif
return false;
global->setReservedSlot(LEGACY_GENERATOR_OBJECT_PROTO, ObjectValue(*proto));
@ -304,13 +311,15 @@ GlobalObject::initStarGenerators(JSContext* cx, Handle<GlobalObject*> global)
iteratorProto));
if (!genObjectProto)
return false;
if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr, star_generator_methods))
if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr, star_generator_methods) ||
!DefineToStringTag(cx, genObjectProto, cx->names().Generator))
return false;
RootedObject genFunctionProto(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
if (!genFunctionProto || !genFunctionProto->setDelegate(cx))
return false;
if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto))
if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto) ||
!DefineToStringTag(cx, genFunctionProto, cx->names().GeneratorFunction))
return false;
RootedValue function(cx, global->getConstructor(JSProto_Function));

View File

@ -529,6 +529,14 @@ js::DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
return true;
}
bool
js::DefineToStringTag(JSContext *cx, HandleObject obj, JSAtom* tag)
{
RootedId toStringTagId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag));
RootedValue tagString(cx, StringValue(tag));
return DefineProperty(cx, obj, toStringTagId, tagString, nullptr, nullptr, JSPROP_READONLY);
}
static void
GlobalDebuggees_finalize(FreeOp* fop, JSObject* obj)
{
@ -658,16 +666,37 @@ GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
HandlePropertyName selfHostedName, HandleAtom name,
unsigned nargs, MutableHandleValue funVal)
{
if (GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal))
return true;
if (GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal)) {
RootedFunction fun(cx, &funVal.toObject().as<JSFunction>());
if (fun->atom() == name)
return true;
JSFunction* fun =
NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
name, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
if (!fun)
if (fun->atom() == selfHostedName) {
// This function was initially cloned because it was called by
// other self-hosted code, so the clone kept its self-hosted name,
// instead of getting the name it's intended to have in content
// compartments. This can happen when a lazy builtin is initialized
// after self-hosted code for another builtin used the same
// function. In that case, we need to change the function's name,
// which is ok because it can't have been exposed to content
// before.
fun->initAtom(name);
return true;
}
// The function might be installed multiple times on the same or
// different builtins, under different property names, so its name
// might be neither "selfHostedName" nor "name". In that case, its
// canonical name must've been set using the `_SetCanonicalName`
// intrinsic.
cx->runtime()->assertSelfHostedFunctionHasCanonicalName(cx, selfHostedName);
return true;
}
RootedFunction fun(cx);
if (!cx->runtime()->createLazySelfHostedFunctionClone(cx, selfHostedName, name, nargs, &fun))
return false;
fun->setIsSelfHostedBuiltin();
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
funVal.setObject(*fun);
return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);

View File

@ -905,6 +905,9 @@ DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
typedef HashSet<GlobalObject*, DefaultHasher<GlobalObject*>, SystemAllocPolicy> GlobalObjectSet;
extern bool
DefineToStringTag(JSContext *cx, HandleObject obj, JSAtom* tag);
/*
* Convenience templates to generic constructor and prototype creation functions
* for ClassSpecs.

View File

@ -3277,9 +3277,10 @@ CASE(JSOP_DEFFUN)
* a compound statement (not at the top statement level of global code, or
* at the top level of a function body).
*/
ReservedRooted<JSFunction*> fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc)));
ReservedRooted<JSFunction*> fun(&rootFunction0, &REGS.sp[-1].toObject().as<JSFunction>());
if (!DefFunOperation(cx, script, REGS.fp()->scopeChain(), fun))
goto error;
REGS.sp--;
}
END_CASE(JSOP_DEFFUN)
@ -4095,27 +4096,8 @@ js::LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleVa
bool
js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject scopeChain,
HandleFunction funArg)
HandleFunction fun)
{
/*
* If static link is not current scope, clone fun's object to link to the
* current scope via parent. We do this to enable sharing of compiled
* functions among multiple equivalent scopes, amortizing the cost of
* compilation over a number of executions. Examples include XUL scripts
* and event handlers shared among Firefox or other Mozilla app chrome
* windows, and user-defined JS functions precompiled and then shared among
* requests in server-side JS.
*/
RootedFunction fun(cx, funArg);
if (fun->isNative() || fun->environment() != scopeChain) {
fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain, nullptr, TenuredObject);
if (!fun)
return false;
} else {
MOZ_ASSERT(script->treatAsRunOnce());
MOZ_ASSERT(!script->functionNonDelazifying());
}
/*
* We define the function as a property of the variable object and not the
* current scope chain even for the case of function expression statements

View File

@ -56,6 +56,7 @@
macro(protected, protected_, TOK_STRICT_RESERVED) \
macro(public, public_, TOK_STRICT_RESERVED) \
macro(static, static_, TOK_STRICT_RESERVED) \
macro(await, await, TOK_AWAIT) \
/* \
* Yield is a token inside function*. Outside of a function*, it is a \
* future reserved keyword in strict mode, but a keyword in JS1.7 even \

View File

@ -1286,10 +1286,10 @@
* scripts where use of dynamic scoping inhibits optimization.
* Category: Variables and Scopes
* Type: Variables
* Operands: uint32_t funcIndex
* Stack: =>
* Operands:
* Stack: fun =>
*/ \
macro(JSOP_DEFFUN, 127,"deffun", NULL, 5, 0, 0, JOF_OBJECT) \
macro(JSOP_DEFFUN, 127,"deffun", NULL, 1, 1, 0, JOF_BYTE) \
/* Defines the new constant binding on global lexical scope.
*
* Throws if a binding with the same name already exists on the scope, or

View File

@ -934,6 +934,10 @@ struct JSRuntime : public JS::shadow::Runtime,
static js::GlobalObject*
createSelfHostingGlobal(JSContext* cx);
bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
js::MutableHandleValue vp);
JSFunction* getUnclonedSelfHostedFunction(JSContext* cx, js::HandlePropertyName name);
/* Space for interpreter frames. */
js::InterpreterStack interpreterStack_;
@ -974,10 +978,14 @@ struct JSRuntime : public JS::shadow::Runtime,
}
bool isSelfHostingCompartment(JSCompartment* comp) const;
bool isSelfHostingZone(const JS::Zone* zone) const;
bool createLazySelfHostedFunctionClone(JSContext* cx, js::HandlePropertyName selfHostedName,
js::HandleAtom name, unsigned nargs,
js::MutableHandleFunction fun);
bool cloneSelfHostedFunctionScript(JSContext* cx, js::Handle<js::PropertyName*> name,
js::Handle<JSFunction*> targetFun);
bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
js::MutableHandleValue vp);
void assertSelfHostedFunctionHasCanonicalName(JSContext* cx, js::HandlePropertyName name);
//-------------------------------------------------------------------------
// Locale information

View File

@ -15,6 +15,7 @@
#include "jscompartment.h"
#include "jsdate.h"
#include "jsfriendapi.h"
#include "jsfun.h"
#include "jshashutil.h"
#include "jsweakmap.h"
#include "jswrapper.h"
@ -39,6 +40,7 @@
#include "vm/String.h"
#include "vm/TypedArrayCommon.h"
#include "jsatominlines.h"
#include "jsfuninlines.h"
#include "jsscriptinlines.h"
@ -148,6 +150,41 @@ intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc, Value* vp)
return true;
}
/**
* Self-hosting intrinsic returning the original constructor for a builtin
* the name of which is the first and only argument.
*
* The return value is guaranteed to be the original constructor even if
* content code changed the named binding on the global object.
*
* This intrinsic shouldn't be called directly. Instead, the
* `GetBuiltinConstructor` and `GetBuiltinPrototype` helper functions in
* Utilities.js should be used, as they cache results, improving performance.
*/
static bool
intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
RootedString str(cx, args[0].toString());
JSAtom* atom;
if (str->isAtom()) {
atom = &str->asAtom();
} else {
atom = AtomizeString(cx, str);
if (!atom)
return false;
}
RootedId id(cx, AtomToId(atom));
JSProtoKey key = JS_IdToProtoKey(cx, id);
MOZ_ASSERT(key != JSProto_Null);
RootedObject ctor(cx);
if (!GetBuiltinConstructor(cx, key, &ctor))
return false;
args.rval().setObject(*ctor);
return true;
}
static bool
intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
{
@ -538,6 +575,26 @@ intrinsic_ActiveFunction(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
MOZ_ASSERT(fun->isSelfHostedBuiltin());
RootedAtom atom(cx, AtomizeString(cx, args[1].toString()));
if (!atom)
return false;
fun->setAtom(atom);
#ifdef DEBUG
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(true));
#endif
args.rval().setUndefined();
return true;
}
static bool
intrinsic_StarGeneratorObjectIsClosed(JSContext* cx, unsigned argc, Value* vp)
{
@ -1225,6 +1282,23 @@ intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_NameForTypedArray(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isObject());
RootedObject object(cx, &args[0].toObject());
MOZ_ASSERT(object->is<TypedArrayObject>());
JSProtoKey protoKey = StandardProtoKeyOrNull(object);
MOZ_ASSERT(protoKey);
args.rval().setString(ClassName(protoKey, cx));
return true;
}
static bool
intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
{
@ -1467,6 +1541,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("ToPropertyKey", intrinsic_ToPropertyKey, 1,0),
JS_INLINABLE_FN("IsCallable", intrinsic_IsCallable, 1,0, IntrinsicIsCallable),
JS_FN("IsConstructor", intrinsic_IsConstructor, 1,0),
JS_FN("GetBuiltinConstructorImpl", intrinsic_GetBuiltinConstructor, 1,0),
JS_FN("OwnPropertyKeys", intrinsic_OwnPropertyKeys, 1,0),
JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4,0),
JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4,0),
@ -1474,6 +1549,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0),
JS_FN("MakeConstructible", intrinsic_MakeConstructible, 2,0),
JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
JS_FN("_NameForTypedArray", intrinsic_NameForTypedArray, 1,0),
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0),
@ -1510,6 +1586,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
CallNonGenericSelfhostedMethod<Is<ListIteratorObject>>, 2,0),
JS_FN("ActiveFunction", intrinsic_ActiveFunction, 0,0),
JS_FN("_SetCanonicalName", intrinsic_SetCanonicalName, 2,0),
JS_INLINABLE_FN("IsArrayIterator",
intrinsic_IsInstanceOfBuiltin<ArrayIteratorObject>, 1,0,
IntrinsicIsArrayIterator),
@ -1969,8 +2047,10 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
staticGlobalLexical, kind);
// To be able to re-lazify the cloned function, its name in the
// self-hosting compartment has to be stored on the clone.
if (clone && hasName)
clone->as<JSFunction>().setExtendedSlot(0, StringValue(selfHostedFunction->atom()));
if (clone && hasName) {
clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT,
StringValue(selfHostedFunction->atom()));
}
} else if (selfHostedObject->is<RegExpObject>()) {
RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
RootedAtom source(cx, reobj.getSource());
@ -2037,16 +2117,37 @@ CloneValue(JSContext* cx, HandleValue selfHostedValue, MutableHandleValue vp)
return true;
}
bool
JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName selfHostedName,
HandleAtom name, unsigned nargs,
MutableHandleFunction fun)
{
RootedAtom funName(cx, name);
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, selfHostedName);
if (!selfHostedFun)
return false;
if (selfHostedFun->atom() != selfHostedName) {
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
funName = selfHostedFun->atom();
}
fun.set(NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
funName, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject));
if (!fun)
return false;
fun->setIsSelfHostedBuiltin();
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
return true;
}
bool
JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
HandleFunction targetFun)
{
RootedId id(cx, NameToId(name));
RootedValue funVal(cx);
if (!GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, &funVal))
RootedFunction sourceFun(cx, getUnclonedSelfHostedFunction(cx, name));
if (!sourceFun)
return false;
RootedFunction sourceFun(cx, &funVal.toObject().as<JSFunction>());
// JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
// aren't any.
MOZ_ASSERT(!sourceFun->isGenerator());
@ -2076,11 +2177,28 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
}
bool
JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableHandleValue vp)
JSRuntime::getUnclonedSelfHostedValue(JSContext* cx, HandlePropertyName name,
MutableHandleValue vp)
{
RootedId id(cx, NameToId(name));
return GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, vp);
}
JSFunction*
JSRuntime::getUnclonedSelfHostedFunction(JSContext* cx, HandlePropertyName name)
{
RootedValue selfHostedValue(cx);
if (!GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, &selfHostedValue))
if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
return nullptr;
return &selfHostedValue.toObject().as<JSFunction>();
}
bool
JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableHandleValue vp)
{
RootedValue selfHostedValue(cx);
if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
return false;
/*
@ -2096,6 +2214,16 @@ JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableH
return CloneValue(cx, selfHostedValue, vp);
}
void
JSRuntime::assertSelfHostedFunctionHasCanonicalName(JSContext* cx, HandlePropertyName name)
{
#ifdef DEBUG
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name);
MOZ_ASSERT(selfHostedFun);
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
#endif
}
JSFunction*
js::SelfHostedFunction(JSContext* cx, HandlePropertyName propName)
{

View File

@ -832,6 +832,7 @@ TypedArrayObject::protoAccessors[] = {
JS_PSG("buffer", TypedArray_bufferGetter, 0),
JS_PSG("byteLength", TypedArray_byteLengthGetter, 0),
JS_PSG("byteOffset", TypedArray_byteOffsetGetter, 0),
JS_SELF_HOSTED_SYM_GET(toStringTag, "TypedArrayToStringTag", 0),
JS_PS_END
};
@ -2148,6 +2149,9 @@ DataViewObject::initClass(JSContext* cx)
if (!JS_DefineFunctions(cx, proto, DataViewObject::jsfuncs))
return false;
if (!DefineToStringTag(cx, proto, cx->names().DataView))
return false;
/*
* Create a helper function to implement the craziness of
* |new DataView(new otherWindow.ArrayBuffer())|, and install it in the

View File

@ -144,10 +144,10 @@ class AsyncFreeSnowWhite : public nsRunnable
public:
NS_IMETHOD Run()
{
TimeStamp start = TimeStamp::Now();
//TimeStamp start = TimeStamp::Now();
bool hadSnowWhiteObjects = nsCycleCollector_doDeferredDeletion();
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING,
uint32_t((TimeStamp::Now() - start).ToMilliseconds()));
//Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING,
// uint32_t((TimeStamp::Now() - start).ToMilliseconds()));
if (hadSnowWhiteObjects && !mContinuation) {
mContinuation = true;
if (NS_FAILED(NS_DispatchToCurrentThread(this))) {
@ -3096,6 +3096,7 @@ JSSizeOfTab(JSObject* objArg, size_t* jsObjectsSize, size_t* jsStringsSize,
static void
AccumulateTelemetryCallback(int id, uint32_t sample, const char* key)
{
#if(0)
switch (id) {
case JS_TELEMETRY_GC_REASON:
Telemetry::Accumulate(Telemetry::GC_REASON_2, sample);
@ -3172,6 +3173,7 @@ AccumulateTelemetryCallback(int id, uint32_t sample, const char* key)
default:
MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
}
#endif
}
static void
@ -3491,7 +3493,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
if (PseudoStack* stack = mozilla_get_pseudo_stack())
stack->sampleRuntime(runtime);
#endif
JS_SetAccumulateTelemetryCallback(runtime, AccumulateTelemetryCallback);
//JS_SetAccumulateTelemetryCallback(runtime, AccumulateTelemetryCallback);
js::SetScriptEnvironmentPreparer(runtime, &mEnvironmentPreparer);
js::SetActivityCallback(runtime, ActivityCallback, this);
JS_SetInterruptCallback(runtime, InterruptCallback);

View File

@ -2220,6 +2220,13 @@ XrayWrapper<Base, Traits>::construct(JSContext* cx, HandleObject wrapper, const
return Traits::construct(cx, wrapper, args, Base::singleton);
}
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, js::ESClassValue* cls) const
{
return Traits::getBuiltinClass(cx, wrapper, Base::singleton, cls);
}
template <typename Base, typename Traits>
const char*
XrayWrapper<Base, Traits>::className(JSContext* cx, HandleObject wrapper) const

View File

@ -83,6 +83,11 @@ public:
return result.succeed();
}
static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
js::ESClassValue* cls) {
return baseInstance.getBuiltinClass(cx, wrapper, cls);
}
static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
return baseInstance.className(cx, wrapper);
}
@ -407,6 +412,12 @@ public:
return JS_WrapObject(cx, protop);
}
static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
js::ESClassValue* cls) {
*cls = js::ESClass_Other;
return true;
}
static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
return "Opaque";
}
@ -473,6 +484,7 @@ class XrayWrapper : public Base {
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool getBuiltinClass(JSContext* cx, JS::HandleObject wapper, js::ESClassValue* cls) const override;
virtual const char* className(JSContext* cx, JS::HandleObject proxy) const override;
static const XrayWrapper singleton;

View File

@ -493,11 +493,10 @@ pref("media.webvtt.regions.enabled", false);
pref("media.track.enabled", false);
// Whether to enable MediaSource support.
// MediaSource is pretty much hosed on PowerPC OS X, so ... no.
pref("media.mediasource.enabled", false);
pref("media.mediasource.enabled", true);
pref("media.mediasource.mp4.enabled", false);
pref("media.mediasource.webm.enabled", false);
pref("media.mediasource.webm.audio.enabled", false);
pref("media.mediasource.webm.enabled", true);
pref("media.mediasource.webm.audio.enabled", true);
// Enable new MediaFormatReader architecture for plain webm.
pref("media.format-reader.webm", true);
@ -2004,6 +2003,14 @@ pref("security.cert_pinning.enforcement_level", 0);
// for tests.
pref("security.cert_pinning.process_headers_from_non_builtin_roots", false);
// Bug 1324406: Treat 'data:' documents as unique, opaque origins
// If true, data: URIs will be treated as unique opaque origins, hence will use
// a NullPrincipal as the security context.
// Otherwise it will inherit the origin from parent node, this is the legacy
// behavior of Firefox.
// TenFourFox issue 525 -- hold until better chrome detection is working
pref("security.data_uri.unique_opaque_origin", false);
// Modifier key prefs: default to Windows settings,
// menu access key = alt, accelerator key = control.
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 91 for Win, 0 for none. Mac settings in macprefs.js

View File

@ -166,7 +166,9 @@ static const char kNetworkActiveChanged[] = "network-active-changed";
uint32_t nsIOService::gDefaultSegmentSize = 4096;
uint32_t nsIOService::gDefaultSegmentCount = 24;
bool nsIOService::sTelemetryEnabled = false;
bool nsIOService::sIsDataURIUniqueOpaqueOrigin = false;
//bool nsIOService::sTelemetryEnabled = false;
NS_IMPL_ISUPPORTS(nsAppOfflineInfo, nsIAppOfflineInfo)
@ -250,7 +252,8 @@ nsIOService::Init()
else
NS_WARNING("failed to get observer service");
Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false);
//Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false);
Preferences::AddBoolVarCache(&sIsDataURIUniqueOpaqueOrigin, "security.data_uri.unique_opaque_origin", true);
Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true);
gIOService = this;
@ -715,6 +718,7 @@ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
if (NS_FAILED(rv))
return rv;
#if(0)
if (sTelemetryEnabled) {
nsAutoCString path;
aURI->GetPath(path);
@ -736,6 +740,7 @@ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
Telemetry::Accumulate(Telemetry::URL_PATH_CONTAINS_EXCLAMATION_DOUBLE_SLASH,
hasBangDoubleSlash);
}
#endif
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
@ -2066,3 +2071,9 @@ nsIOService::IsAppOffline(uint32_t aAppId, bool* aResult)
return NS_OK;
}
/*static*/ bool
nsIOService::IsDataURIUniqueOpaqueOrigin()
{
return sIsDataURIUniqueOpaqueOrigin;
}

View File

@ -87,6 +87,8 @@ public:
bool IsShutdown() { return mShutdown; }
bool IsLinkUp();
static bool IsDataURIUniqueOpaqueOrigin();
// Should only be called from NeckoChild. Use SetAppOffline instead.
void SetAppOfflineInternal(uint32_t appId, int32_t status);
@ -174,7 +176,8 @@ private:
// that is used especially in IsAppOffline
nsDataHashtable<nsUint32HashKey, int32_t> mAppsOfflineStatus;
static bool sTelemetryEnabled;
//static bool sTelemetryEnabled;
static bool sIsDataURIUniqueOpaqueOrigin;
// These timestamps are needed for collecting telemetry on PR_Connect,
// PR_ConnectContinue and PR_Close blocking time. If we spend very long

View File

@ -55,9 +55,16 @@ nsDataHandler::GetDefaultPort(int32_t *result) {
NS_IMETHODIMP
nsDataHandler::GetProtocolFlags(uint32_t *result) {
*result = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT |
*result = URI_NORELATIVE | URI_NOAUTH |
URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE | URI_IS_LOCAL_RESOURCE |
URI_SYNC_LOAD_IS_OK;
// From bug 1324406:
// data: URIs inherit the security context.
if (!nsIOService::IsDataURIUniqueOpaqueOrigin()) {
*result |= URI_INHERITS_SECURITY_CONTEXT;
}
return NS_OK;
}

View File

@ -359,7 +359,7 @@ Http2Decompressor::DecodeHeaderBlock(const uint8_t *data, uint32_t datalen,
nsresult rv = NS_OK;
nsresult softfail_rv = NS_OK;
while (NS_SUCCEEDED(rv) && (mOffset < datalen)) {
while (NS_SUCCEEDED(rv) && (mOffset < mDataLen)) {
bool modifiesTable = true;
if (mData[mOffset] & 0x80) {
rv = DoIndexed();
@ -603,6 +603,11 @@ nsresult
Http2Decompressor::DecodeFinalHuffmanCharacter(HuffmanIncomingTable *table,
uint8_t &c, uint8_t &bitsLeft)
{
MOZ_ASSERT(mOffset <= mDataLen);
if (MOZ_UNLIKELY(mOffset > mDataLen)) {
NS_WARNING("DecodeFinalHuffmanCharacter would read beyond end of buffer");
return NS_ERROR_FAILURE;
}
uint8_t mask = (1 << bitsLeft) - 1;
uint8_t idx = mData[mOffset - 1] & mask;
idx <<= (8 - bitsLeft);
@ -640,6 +645,7 @@ Http2Decompressor::DecodeFinalHuffmanCharacter(HuffmanIncomingTable *table,
uint8_t
Http2Decompressor::ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed)
{
MOZ_DIAGNOSTIC_ASSERT(mOffset < mDataLen);
uint8_t rv;
if (bitsLeft) {
@ -670,8 +676,8 @@ Http2Decompressor::DecodeHuffmanCharacter(HuffmanIncomingTable *table,
HuffmanIncomingEntry *entry = &(table->mEntries[idx]);
if (entry->mPtr) {
if (bytesConsumed >= mDataLen) {
if (!bitsLeft || (bytesConsumed > mDataLen)) {
if (mOffset >= mDataLen) {
if (MOZ_UNLIKELY(!bitsLeft || (mOffset > mDataLen))) {
// TODO - does this get me into trouble in the new world?
// No info left in input to try to consume, we're done
LOG(("DecodeHuffmanCharacter all out of bits to consume, can't chain"));
@ -811,6 +817,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value,
return rv;
}
// sanity check
if (MOZ_UNLIKELY(mOffset >= mDataLen)) {
NS_WARNING("Http2 Decompressor ran out of data");
// This is session-fatal
return NS_ERROR_FAILURE;
}
bool isHuffmanEncoded;
if (!index) {
@ -838,6 +851,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value,
return rv;
}
// sanity check
if (MOZ_UNLIKELY(mOffset >= mDataLen)) {
NS_WARNING("Http2 Decompressor ran out of data");
// This is session-fatal
return NS_ERROR_FAILURE;
}
// now the value
uint32_t valueLen;
isHuffmanEncoded = mData[mOffset] & (1 << 7);

View File

@ -439,13 +439,11 @@ nsHttpChannelAuthProvider::PrepareForAuthentication(bool proxyAuth)
// We need to remove any Proxy_Authorization header left over from a
// non-request based authentication handshake (e.g., for NTLM auth).
nsAutoCString contractId;
contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
contractId.Append(mProxyAuthType);
nsresult rv;
nsCOMPtr<nsIHttpAuthenticator> precedingAuth =
do_GetService(contractId.get(), &rv);
nsCOMPtr<nsIHttpAuthenticator> precedingAuth;
nsCString proxyAuthType;
rv = GetAuthenticator(mProxyAuthType.get(), proxyAuthType,
getter_AddRefs(precedingAuth));
if (NS_FAILED(rv))
return rv;

View File

@ -437,6 +437,7 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
!hostLine.EqualsLiteral("i.imgur.com") &&
!hostLine.EqualsLiteral("imgur.com") &&
!hostLine.EqualsLiteral("github.com") &&
!hostLine.EqualsLiteral("gist.github.com") &&
1)) {
rv = request->SetHeader(nsHttp::User_Agent, UserAgent(),
false, nsHttpHeaderArray::eVarietyDefault);

View File

@ -232,6 +232,7 @@ DataChannelConnection::Destroy()
MOZ_ASSERT(mSTS);
ASSERT_WEBRTC(NS_IsMainThread());
mListener = nullptr;
// Must do this in Destroy() since we may then delete this object.
// Do this before dispatching to create a consistent ordering of calls to
// the SCTP stack.

View File

@ -610,17 +610,13 @@ static const StaticFingerprints kPinset_spideroak = {
static const char* const kPinset_yahoo_Data[] = {
kYahooBackup1Fingerprint,
kGOOGLE_PIN_VeriSignClass2_G2Fingerprint,
kDigiCert_Assured_ID_Root_CAFingerprint,
kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
kGlobalSign_Root_CAFingerprint,
kDigiCert_Trusted_Root_G4Fingerprint,
kDigiCert_High_Assurance_EV_Root_CAFingerprint,
kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
kGlobalSign_Root_CA___R3Fingerprint,
kYahooBackup2Fingerprint,
kDigiCert_Global_Root_G2Fingerprint,
kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
kDigiCert_Global_Root_CAFingerprint,
kDigiCert_Global_Root_G3Fingerprint,
};
@ -1174,4 +1170,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1544124515242000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1548072521544000);

View File

@ -1544,6 +1544,10 @@ void nsNSSCertList::destructorSafeDestroyNSSReference()
NS_IMETHODIMP
nsNSSCertList::AddCert(nsIX509Cert* aCert)
{
if (!aCert) {
return NS_ERROR_INVALID_ARG;
}
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
@ -1698,17 +1702,19 @@ nsNSSCertList::Read(nsIObjectInputStream* aStream)
nsCOMPtr<nsISupports> certSupports;
rv = aStream->ReadObject(true, getter_AddRefs(certSupports));
if (NS_FAILED(rv)) {
break;
return rv;
}
nsCOMPtr<nsIX509Cert> cert = do_QueryInterface(certSupports);
if (!cert) {
return NS_ERROR_UNEXPECTED;
}
rv = AddCert(cert);
if (NS_FAILED(rv)) {
break;
return rv;
}
}
return rv;
return NS_OK;
}
NS_IMETHODIMP

File diff suppressed because it is too large Load Diff

View File

@ -35,14 +35,6 @@ function do_check_throws(f, type, stack)
do_throw("expected " + type.name + " exception, none thrown", stack);
}
function do_check_class(obj, classname, stack)
{
if (!stack)
stack = Components.stack.caller;
do_check_eq(Object.prototype.toString.call(obj), "[object " + classname + "]", stack);
}
function run_test()
{
// Test ctypes.CType and ctypes.CData are set up correctly.
@ -231,10 +223,6 @@ function run_abstract_class_tests()
do_check_throws(function() { ctypes.CType(); }, Error);
do_check_throws(function() { new ctypes.CType() }, Error);
// Test that classes and prototypes are set up correctly.
do_check_class(ctypes.CType, "Function");
do_check_class(ctypes.CType.prototype, "CType");
do_check_true(ctypes.CType.hasOwnProperty("prototype"));
do_check_throws(function() { ctypes.CType.prototype(); }, Error);
do_check_throws(function() { new ctypes.CType.prototype() }, Error);
@ -269,10 +257,6 @@ function run_abstract_class_tests()
do_check_throws(function() { ctypes.CData(); }, Error);
do_check_throws(function() { new ctypes.CData() }, Error);
// Test that classes and prototypes are set up correctly.
do_check_class(ctypes.CData, "Function");
do_check_class(ctypes.CData.prototype, "CData");
do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype);
do_check_true(ctypes.CData instanceof ctypes.CType);
@ -302,10 +286,6 @@ function run_abstract_class_tests()
function run_Int64_tests() {
do_check_throws(function() { ctypes.Int64(); }, TypeError);
// Test that classes and prototypes are set up correctly.
do_check_class(ctypes.Int64, "Function");
do_check_class(ctypes.Int64.prototype, "Int64");
do_check_true(ctypes.Int64.hasOwnProperty("prototype"));
do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64);
@ -473,10 +453,6 @@ function run_Int64_tests() {
function run_UInt64_tests() {
do_check_throws(function() { ctypes.UInt64(); }, TypeError);
// Test that classes and prototypes are set up correctly.
do_check_class(ctypes.UInt64, "Function");
do_check_class(ctypes.UInt64.prototype, "UInt64");
do_check_true(ctypes.UInt64.hasOwnProperty("prototype"));
do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64);
@ -738,10 +714,6 @@ function offsetof(struct, member) {
// Test the class and prototype hierarchy for a given basic type 't'.
function run_basic_class_tests(t)
{
// Test that classes and prototypes are set up correctly.
do_check_class(t, "CType");
do_check_class(t.prototype, "CData");
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t instanceof ctypes.CType);
@ -762,7 +734,6 @@ function run_basic_class_tests(t)
// Test that an instance 'd' of 't' is a CData.
let d = t();
do_check_class(d, "CData");
do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t);
do_check_true(d.constructor === t);
@ -1283,10 +1254,6 @@ function run_char16_tests(library, t, name, limits) {
// Test the class and prototype hierarchy for a given type constructor 'c'.
function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[], instanceFns=[], specialProps=[])
{
// Test that classes and prototypes are set up correctly on the type ctor 'c'.
do_check_class(c, "Function");
do_check_class(c.prototype, "CType");
do_check_true(c.prototype.__proto__ === ctypes.CType.prototype);
do_check_true(c.prototype instanceof ctypes.CType);
do_check_true(c.prototype.constructor === c);
@ -1303,15 +1270,9 @@ function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[],
for (let f of fns)
do_check_throws(function() { c.prototype[f](); }, Error);
// Test that classes and prototypes are set up correctly on a constructed
// type 't'.
do_check_class(t, "CType");
do_check_class(t.prototype, "CData");
do_check_true(t.__proto__ === c.prototype);
do_check_true(t instanceof c);
do_check_class(t.prototype.__proto__, "CData");
// 't.prototype.__proto__' is the common ancestor of all types constructed
// from 'c'; while not available from 'c' directly, it should be identically
// equal to 't2.prototype.__proto__' where 't2' is a different CType
@ -1359,7 +1320,6 @@ function run_type_ctor_class_tests(c, t, t2, props=[], fns=[], instanceProps=[],
// Test that an instance 'd' of 't' is a CData.
if (t.__proto__ != ctypes.FunctionType.prototype) {
let d = t();
do_check_class(d, "CData");
do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t);
do_check_true(d.constructor === t);

View File

@ -108,6 +108,23 @@ nsTArray_base<Alloc, Copy>::UsesAutoArrayBuffer() const
bool IsTwiceTheRequiredBytesRepresentableAsUint32(size_t aCapacity,
size_t aElemSize);
template<class Alloc, class Copy>
template<typename ActualAlloc>
typename ActualAlloc::ResultTypeProxy
nsTArray_base<Alloc, Copy>::ExtendCapacity(size_type aLength,
size_type aCount,
size_type aElemSize)
{
mozilla::CheckedInt<size_type> newLength = aLength;
newLength += aCount;
if (!newLength.isValid()) {
return ActualAlloc::FailureResult();
}
return this->EnsureCapacity<ActualAlloc>(newLength.value(), aElemSize);
}
template<class Alloc, class Copy>
template<typename ActualAlloc>
typename ActualAlloc::ResultTypeProxy
@ -275,26 +292,22 @@ nsTArray_base<Alloc, Copy>::ShiftData(index_type aStart,
template<class Alloc, class Copy>
template<typename ActualAlloc>
bool
typename ActualAlloc::ResultTypeProxy
nsTArray_base<Alloc, Copy>::InsertSlotsAt(index_type aIndex, size_type aCount,
size_type aElemSize,
size_t aElemAlign)
{
MOZ_ASSERT(aIndex <= Length(), "Bogus insertion index");
size_type newLen = Length() + aCount;
EnsureCapacity<ActualAlloc>(newLen, aElemSize);
// Check for out of memory conditions
if (Capacity() < newLen) {
return false;
if (!ActualAlloc::Successful(this->ExtendCapacity<ActualAlloc>(Length(), aCount, aElemSize))) {
return ActualAlloc::FailureResult();
}
// Move the existing elements as needed. Note that this will
// change our mLength, so no need to call IncrementLength.
ShiftData<ActualAlloc>(aIndex, 0, aCount, aElemSize, aElemAlign);
return true;
return ActualAlloc::SuccessResult();
}
// nsTArray_base::IsAutoArrayRestorer is an RAII class which takes

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