mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-10 18:29:43 +00:00
commit
06ee05da83
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -2932,6 +2932,7 @@ var SessionStoreInternal = {
|
|||
tabbrowser.addTab("about:blank", {
|
||||
skipAnimation: true,
|
||||
forceNotRemote: true,
|
||||
skipBackgroundNotify: true,
|
||||
}));
|
||||
|
||||
if (winData.tabs[t].pinned)
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,7 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
|||
// static
|
||||
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
|
||||
"noreferrer",
|
||||
"noopener",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -88,6 +88,7 @@ function LegacyGeneratorNext(val) {
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
_SetCanonicalName(LegacyGeneratorNext, "next");
|
||||
|
||||
function LegacyGeneratorThrow(val) {
|
||||
if (!IsObject(this) || !IsLegacyGeneratorObject(this))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -38,3 +38,4 @@ function SetSpecies() {
|
|||
// Step 1.
|
||||
return this;
|
||||
}
|
||||
_SetCanonicalName(SetSpecies, "get [Symbol.species]");
|
||||
|
|
|
@ -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) + '"';
|
||||
outputStr += callFunction(String_substring, inputStr, chunkStart, i) + '"';
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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]");
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'") \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
13
js/src/jit-test/tests/self-hosting/getbuiltinconstructor.js
Normal file
13
js/src/jit-test/tests/self-hosting/getbuiltinconstructor.js
Normal 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);
|
|
@ -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);
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4561,6 +4561,7 @@ GetSymbolDescription(HandleSymbol symbol);
|
|||
macro(match) \
|
||||
macro(species) \
|
||||
macro(toPrimitive) \
|
||||
macro(toStringTag) \
|
||||
macro(unscopables)
|
||||
|
||||
enum class SymbolCode : uint32_t {
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
158
js/src/tests/ecma_6/Symbol/toStringTag.js
Normal file
158
js/src/tests/ecma_6/Symbol/toStringTag.js
Normal 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);
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]") \
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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, ®S.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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue
Block a user