diff --git a/CLOBBER b/CLOBBER index 864c1c575427..eec9e5c31b8a 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 1178850 requires clobber for Android JNI header changes +Bug 1123386 requires clobber for switching to use a new compiler diff --git a/browser/config/tooltool-manifests/linux32/clang.manifest b/browser/config/tooltool-manifests/linux32/clang.manifest index 6d75f637c117..2da4b025644e 100644 --- a/browser/config/tooltool-manifests/linux32/clang.manifest +++ b/browser/config/tooltool-manifests/linux32/clang.manifest @@ -1,10 +1,10 @@ [ { -"clang_version": "r183744" +"clang_version": "r241406" }, { -"size": 70206124, -"digest": "a6b8046bd9485f9387dcb1c14b8d442822f02b1caa61b653e8b6cfd96906deadfb4b29809f2cd2b71f919b321d97dd2ebec6020c15f6d485f1641c0f710a762f", +"size": 100307285, +"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30", "algorithm": "sha512", "filename": "clang.tar.bz2", "unpack": true, diff --git a/browser/config/tooltool-manifests/linux64/clang.manifest b/browser/config/tooltool-manifests/linux64/clang.manifest index 2bad4b994b96..216b4eae7037 100644 --- a/browser/config/tooltool-manifests/linux64/clang.manifest +++ b/browser/config/tooltool-manifests/linux64/clang.manifest @@ -1,10 +1,10 @@ [ { -"clang_version": "r183744" +"clang_version": "r241406" }, { -"size": 70350828, -"digest": "6cd04e8ec44c6fef159349c22bd0476891e4a2d46479f9586283eaf3305e42f79c720d40dfec0e78d8899c1651189b12e285de60862ffd0612b0dac7a0c336c6", +"size": 100307285, +"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30", "algorithm": "sha512", "filename": "clang.tar.bz2", "unpack": true diff --git a/browser/config/tooltool-manifests/macosx64/clang.manifest b/browser/config/tooltool-manifests/macosx64/clang.manifest index aa1ef98af6c3..c84370fc6b19 100644 --- a/browser/config/tooltool-manifests/macosx64/clang.manifest +++ b/browser/config/tooltool-manifests/macosx64/clang.manifest @@ -1,10 +1,10 @@ [ { -"clang_version": "r183744" +"clang_version": "r241406" }, { -"size": 59602619, -"digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", +"size": 86465808, +"digest": "947eaaf11ac8cbe12e11b48c8b052721e018d31fb8ce20f8bf14b117b6623c56513b1422d8d9c8011bc0b0b985ef74d8f181e7200c6d7a05d79a1bce0d75ddee", "algorithm": "sha512", "filename": "clang.tar.bz2", "unpack": true diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index 11382b4e2231..55d555bbb575 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -336,6 +336,26 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel, NS_ADDREF(*aPrincipal = loadInfo->TriggeringPrincipal()); return NS_OK; } + + nsSecurityFlags securityFlags = loadInfo->GetSecurityMode(); + if (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS || + securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS || + securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { + + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr triggeringPrincipal = loadInfo->TriggeringPrincipal(); + bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits(); + + if (nsContentUtils::ChannelShouldInheritPrincipal(triggeringPrincipal, + uri, + inheritForAboutBlank, + false)) { + triggeringPrincipal.forget(aPrincipal); + return NS_OK; + } + } } return GetChannelURIPrincipal(aChannel, aPrincipal); } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 6ded2df52eb7..46ed81514252 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9715,7 +9715,8 @@ nsDocShell::InternalLoad(nsIURI* aURI, } if (IsFrame() && !isNewDocShell && !isTargetTopLevelDocShell) { NS_ASSERTION(requestingElement, "A frame but no DOM element!?"); - contentType = nsIContentPolicy::TYPE_SUBDOCUMENT; + contentType = requestingElement->IsHTMLElement(nsGkAtoms::iframe) ? + nsIContentPolicy::TYPE_INTERNAL_IFRAME : nsIContentPolicy::TYPE_INTERNAL_FRAME; } else { contentType = nsIContentPolicy::TYPE_DOCUMENT; } @@ -9836,13 +9837,9 @@ nsDocShell::InternalLoad(nsIURI* aURI, if (aURI) { aURI->GetSpec(spec); } - nsAutoString features; - if (mInPrivateBrowsing) { - features.AssignLiteral("private"); - } rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec), name, // window name - features, + EmptyString(), // Features getter_AddRefs(newWin)); // In some cases the Open call doesn't actually result in a new diff --git a/docshell/test/navigation/browser.ini b/docshell/test/navigation/browser.ini index b6c882164ef7..39e4b503c0d0 100644 --- a/docshell/test/navigation/browser.ini +++ b/docshell/test/navigation/browser.ini @@ -9,3 +9,4 @@ support-files = [browser_bug343515.js] skip-if = e10s # Bug ?????? - test directly touches content (tries to QI the content window) +[browser_test-content-chromeflags.js] diff --git a/docshell/test/navigation/browser_test-content-chromeflags.js b/docshell/test/navigation/browser_test-content-chromeflags.js new file mode 100644 index 000000000000..64559897cd4e --- /dev/null +++ b/docshell/test/navigation/browser_test-content-chromeflags.js @@ -0,0 +1,45 @@ +const TEST_PAGE = `data:text/html,Test`; +const CHROME_ALL = Ci.nsIWebBrowserChrome.CHROME_ALL; +const CHROME_REMOTE_WINDOW = Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW; + +/** + * Tests that when we open new browser windows from content they + * get the full browser chrome. + */ +add_task(function* () { + // Make sure that the window.open call will open a new + // window instead of a new tab. + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({ + "set": [ + ["browser.link.open_newwindow", 2], + ] + }, resolve); + }); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: TEST_PAGE + }, function*(browser) { + let openedPromise = BrowserTestUtils.waitForNewWindow(); + BrowserTestUtils.synthesizeMouse("a", 0, 0, {}, browser); + let win = yield openedPromise; + + let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .treeOwner + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIXULWindow) + .chromeFlags; + + // In the multi-process case, the new window will have the + // CHROME_REMOTE_WINDOW flag set. + const EXPECTED = gMultiProcessBrowser ? CHROME_ALL | CHROME_REMOTE_WINDOW + : CHROME_ALL; + + is(chromeFlags, EXPECTED, "Window should have opened with all chrome"); + + BrowserTestUtils.closeWindow(win); + }); +}); diff --git a/dom/audiochannel/AudioChannelService.cpp b/dom/audiochannel/AudioChannelService.cpp index 60a7afb45aa0..c3b858ab7761 100644 --- a/dom/audiochannel/AudioChannelService.cpp +++ b/dom/audiochannel/AudioChannelService.cpp @@ -521,23 +521,20 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } -struct RefreshAgentsVolumeData -{ - explicit RefreshAgentsVolumeData(nsPIDOMWindow* aWindow) - : mWindow(aWindow) - {} - - nsPIDOMWindow* mWindow; - nsTArray> mAgents; -}; - void AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow) { MOZ_ASSERT(aWindow); MOZ_ASSERT(aWindow->IsOuterWindow()); - AudioChannelWindow* winData = GetWindowData(aWindow->WindowID()); + nsCOMPtr topWindow; + aWindow->GetScriptableTop(getter_AddRefs(topWindow)); + nsCOMPtr pTopWindow = do_QueryInterface(topWindow); + if (!pTopWindow) { + return; + } + + AudioChannelWindow* winData = GetWindowData(pTopWindow->WindowID()); if (!winData) { return; } diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 6b665e152467..9f33d232b6e5 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/Exceptions.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/StructuredCloneHelper.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/Maybe.h" #include "nsCycleCollectionParticipant.h" @@ -74,87 +75,6 @@ ConsoleStructuredCloneData * It's not the best, but at least we are able to show something. */ -// This method is called by the Structured Clone Algorithm when some data has -// to be read. -static JSObject* -ConsoleStructuredCloneCallbacksRead(JSContext* aCx, - JSStructuredCloneReader* /* unused */, - uint32_t aTag, uint32_t aIndex, - void* aClosure) -{ - AssertIsOnMainThread(); - ConsoleStructuredCloneData* data = - static_cast(aClosure); - MOZ_ASSERT(data); - - if (aTag == CONSOLE_TAG_BLOB) { - MOZ_ASSERT(data->mBlobs.Length() > aIndex); - - JS::Rooted val(aCx); - { - nsRefPtr blob = - Blob::Create(data->mParent, data->mBlobs.ElementAt(aIndex)); - if (!ToJSValue(aCx, blob, &val)) { - return nullptr; - } - } - - return &val.toObject(); - } - - MOZ_CRASH("No other tags are supported."); - return nullptr; -} - -// This method is called by the Structured Clone Algorithm when some data has -// to be written. -static bool -ConsoleStructuredCloneCallbacksWrite(JSContext* aCx, - JSStructuredCloneWriter* aWriter, - JS::Handle aObj, - void* aClosure) -{ - ConsoleStructuredCloneData* data = - static_cast(aClosure); - MOZ_ASSERT(data); - - nsRefPtr blob; - if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) && - blob->Impl()->MayBeClonedToOtherThreads()) { - if (!JS_WriteUint32Pair(aWriter, CONSOLE_TAG_BLOB, data->mBlobs.Length())) { - return false; - } - - data->mBlobs.AppendElement(blob->Impl()); - return true; - } - - JS::Rooted value(aCx, JS::ObjectOrNullValue(aObj)); - JS::Rooted jsString(aCx, JS::ToString(aCx, value)); - if (!jsString) { - return false; - } - - if (!JS_WriteString(aWriter, jsString)) { - return false; - } - - return true; -} - -static void -ConsoleStructuredCloneCallbacksError(JSContext* /* aCx */, - uint32_t /* aErrorId */) -{ - NS_WARNING("Failed to clone data for the Console API in workers."); -} - -static const JSStructuredCloneCallbacks gConsoleCallbacks = { - ConsoleStructuredCloneCallbacksRead, - ConsoleStructuredCloneCallbacksWrite, - ConsoleStructuredCloneCallbacksError -}; - class ConsoleCallData final { public: @@ -274,6 +194,7 @@ private: class ConsoleRunnable : public nsRunnable , public WorkerFeature + , public StructuredCloneHelperInternal { public: explicit ConsoleRunnable(Console* aConsole) @@ -431,10 +352,67 @@ protected: RunConsole(JSContext* aCx, nsPIDOMWindow* aOuterWindow, nsPIDOMWindow* aInnerWindow) = 0; + virtual JSObject* ReadCallback(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + uint32_t aIndex) override + { + AssertIsOnMainThread(); + + if (aTag == CONSOLE_TAG_BLOB) { + MOZ_ASSERT(mClonedData.mBlobs.Length() > aIndex); + + JS::Rooted val(aCx); + { + nsRefPtr blob = + Blob::Create(mClonedData.mParent, mClonedData.mBlobs.ElementAt(aIndex)); + if (!ToJSValue(aCx, blob, &val)) { + return nullptr; + } + } + + return &val.toObject(); + } + + MOZ_CRASH("No other tags are supported."); + return nullptr; + } + + virtual bool WriteCallback(JSContext* aCx, + JSStructuredCloneWriter* aWriter, + JS::Handle aObj) override + { + nsRefPtr blob; + if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) && + blob->Impl()->MayBeClonedToOtherThreads()) { + if (!JS_WriteUint32Pair(aWriter, CONSOLE_TAG_BLOB, + mClonedData.mBlobs.Length())) { + return false; + } + + mClonedData.mBlobs.AppendElement(blob->Impl()); + return true; + } + + JS::Rooted value(aCx, JS::ObjectOrNullValue(aObj)); + JS::Rooted jsString(aCx, JS::ToString(aCx, value)); + if (!jsString) { + return false; + } + + if (!JS_WriteString(aWriter, jsString)) { + return false; + } + + return true; + } + WorkerPrivate* mWorkerPrivate; // This must be released on the worker thread. nsRefPtr mConsole; + + ConsoleStructuredCloneData mClonedData; }; // This runnable appends a CallData object into the Console queue running on @@ -499,7 +477,7 @@ private: JS::Rooted value(aCx, JS::ObjectValue(*arguments)); - if (!mArguments.write(aCx, value, &gConsoleCallbacks, &mData)) { + if (!Write(aCx, value)) { return false; } @@ -537,12 +515,12 @@ private: } // Now we could have the correct window (if we are not window-less). - mData.mParent = aInnerWindow; + mClonedData.mParent = aInnerWindow; ProcessCallData(aCx); mCallData->CleanupJSObjects(); - mData.mParent = nullptr; + mClonedData.mParent = nullptr; } private: @@ -552,7 +530,7 @@ private: ClearException ce(aCx); JS::Rooted argumentsValue(aCx); - if (!mArguments.read(aCx, &argumentsValue, &gConsoleCallbacks, &mData)) { + if (!Read(aCx, &argumentsValue)) { return; } @@ -582,9 +560,6 @@ private: } nsRefPtr mCallData; - - JSAutoStructuredCloneBuffer mArguments; - ConsoleStructuredCloneData mData; }; // This runnable calls ProfileMethod() on the console on the main-thread. @@ -629,7 +604,7 @@ private: JS::Rooted value(aCx, JS::ObjectValue(*arguments)); - if (!mBuffer.write(aCx, value, &gConsoleCallbacks, &mData)) { + if (!Write(aCx, value)) { return false; } @@ -644,11 +619,11 @@ private: ClearException ce(aCx); // Now we could have the correct window (if we are not window-less). - mData.mParent = aInnerWindow; + mClonedData.mParent = aInnerWindow; JS::Rooted argumentsValue(aCx); - bool ok = mBuffer.read(aCx, &argumentsValue, &gConsoleCallbacks, &mData); - mData.mParent = nullptr; + bool ok = Read(aCx, &argumentsValue); + mClonedData.mParent = nullptr; if (!ok) { return; @@ -682,9 +657,6 @@ private: nsString mAction; Sequence mArguments; - - JSAutoStructuredCloneBuffer mBuffer; - ConsoleStructuredCloneData mData; }; NS_IMPL_CYCLE_COLLECTION_CLASS(Console) diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 62f29573fc3c..fe4c81ab0c28 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1059,10 +1059,12 @@ Element::CreateShadowRoot(ErrorResult& aError) return shadowRoot.forget(); } -NS_IMPL_CYCLE_COLLECTION(DestinationInsertionPointList, mParent, mDestinationPoints) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DestinationInsertionPointList, mParent, + mDestinationPoints) NS_INTERFACE_TABLE_HEAD(DestinationInsertionPointList) - NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList) + NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY + NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList, nsIDOMNodeList) NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DestinationInsertionPointList) NS_INTERFACE_MAP_END @@ -1678,7 +1680,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) nsContentUtils::eDOM_PROPERTIES, "RemovedFullScreenElement"); // Fully exit full-screen. - nsIDocument::ExitFullscreen(OwnerDoc(), /* async */ false); + nsIDocument::ExitFullscreenInDocTree(OwnerDoc()); } if (HasPointerLock()) { nsIDocument::UnlockPointer(); diff --git a/dom/base/Element.h b/dom/base/Element.h index fc9cf1773239..0f501d922f07 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -1301,7 +1301,7 @@ public: explicit DestinationInsertionPointList(Element* aElement); NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(DestinationInsertionPointList) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DestinationInsertionPointList) // nsIDOMNodeList NS_DECL_NSIDOMNODELIST diff --git a/dom/base/StructuredCloneHelper.cpp b/dom/base/StructuredCloneHelper.cpp new file mode 100644 index 000000000000..be8306b672c5 --- /dev/null +++ b/dom/base/StructuredCloneHelper.cpp @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "StructuredCloneHelper.h" + +namespace mozilla { +namespace dom { + +namespace { + +JSObject* +StructuredCloneCallbacksRead(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, uint32_t aIndex, + void* aClosure) +{ + StructuredCloneHelperInternal* helper = + static_cast(aClosure); + MOZ_ASSERT(helper); + return helper->ReadCallback(aCx, aReader, aTag, aIndex); +} + +bool +StructuredCloneCallbacksWrite(JSContext* aCx, + JSStructuredCloneWriter* aWriter, + JS::Handle aObj, + void* aClosure) +{ + StructuredCloneHelperInternal* helper = + static_cast(aClosure); + MOZ_ASSERT(helper); + return helper->WriteCallback(aCx, aWriter, aObj); +} + +bool +StructuredCloneCallbacksReadTransfer(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + void* aContent, + uint64_t aExtraData, + void* aClosure, + JS::MutableHandleObject aReturnObject) +{ + StructuredCloneHelperInternal* helper = + static_cast(aClosure); + MOZ_ASSERT(helper); + return helper->ReadTransferCallback(aCx, aReader, aTag, aContent, + aExtraData, aReturnObject); +} + +bool +StructuredCloneCallbacksWriteTransfer(JSContext* aCx, + JS::Handle aObj, + void* aClosure, + // Output: + uint32_t* aTag, + JS::TransferableOwnership* aOwnership, + void** aContent, + uint64_t* aExtraData) +{ + StructuredCloneHelperInternal* helper = + static_cast(aClosure); + MOZ_ASSERT(helper); + return helper->WriteTransferCallback(aCx, aObj, aTag, aOwnership, aContent, + aExtraData); +} + +void +StructuredCloneCallbacksFreeTransfer(uint32_t aTag, + JS::TransferableOwnership aOwnership, + void* aContent, + uint64_t aExtraData, + void* aClosure) +{ + StructuredCloneHelperInternal* helper = + static_cast(aClosure); + MOZ_ASSERT(helper); + return helper->FreeTransferCallback(aTag, aOwnership, aContent, aExtraData); +} + +void +StructuredCloneCallbacksError(JSContext* aCx, + uint32_t aErrorId) +{ + NS_WARNING("Failed to clone data for the Console API in workers."); +} + +const JSStructuredCloneCallbacks gCallbacks = { + StructuredCloneCallbacksRead, + StructuredCloneCallbacksWrite, + StructuredCloneCallbacksError, + StructuredCloneCallbacksReadTransfer, + StructuredCloneCallbacksWriteTransfer, + StructuredCloneCallbacksFreeTransfer +}; + +} // anonymous namespace + +bool +StructuredCloneHelperInternal::Write(JSContext* aCx, + JS::Handle aValue) +{ + MOZ_ASSERT(!mBuffer, "Double Write is not allowed"); + + mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this); + return mBuffer->write(aCx, aValue, &gCallbacks, this); +} + +bool +StructuredCloneHelperInternal::Read(JSContext* aCx, + JS::MutableHandle aValue) +{ + MOZ_ASSERT(mBuffer, "Read() without Write() is not allowed."); + + bool ok = mBuffer->read(aCx, aValue, &gCallbacks, this); + mBuffer = nullptr; + return ok; +} + +bool +StructuredCloneHelperInternal::ReadTransferCallback(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + void* aContent, + uint64_t aExtraData, + JS::MutableHandleObject aReturnObject) +{ + MOZ_CRASH("Nothing to read."); + return false; +} + + +bool +StructuredCloneHelperInternal::WriteTransferCallback(JSContext* aCx, + JS::Handle aObj, + uint32_t* aTag, + JS::TransferableOwnership* aOwnership, + void** aContent, + uint64_t* aExtraData) +{ + // No transfers are supported by default. + return false; +} + +void +StructuredCloneHelperInternal::FreeTransferCallback(uint32_t aTag, + JS::TransferableOwnership aOwnership, + void* aContent, + uint64_t aExtraData) +{ + MOZ_CRASH("Nothing to free."); +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/base/StructuredCloneHelper.h b/dom/base/StructuredCloneHelper.h new file mode 100644 index 000000000000..1a508d175de5 --- /dev/null +++ b/dom/base/StructuredCloneHelper.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_StructuredCloneHelper_h +#define mozilla_dom_StructuredCloneHelper_h + +#include "js/StructuredClone.h" +#include "nsAutoPtr.h" + +namespace mozilla { +namespace dom { + +class StructuredCloneHelperInternal +{ +public: + // These methods should be implemented in order to clone data. + // Read more documentation in js/public/StructuredClone.h. + + virtual JSObject* ReadCallback(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + uint32_t aIndex) = 0; + + virtual bool WriteCallback(JSContext* aCx, + JSStructuredCloneWriter* aWriter, + JS::Handle aObj) = 0; + + // If these 3 methods are not implement, transfering objects will not be + // allowed. + + virtual bool + ReadTransferCallback(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + void* aContent, + uint64_t aExtraData, + JS::MutableHandleObject aReturnObject); + + virtual bool + WriteTransferCallback(JSContext* aCx, + JS::Handle aObj, + // Output: + uint32_t* aTag, + JS::TransferableOwnership* aOwnership, + void** aContent, + uint64_t* aExtraData); + + virtual void + FreeTransferCallback(uint32_t aTag, + JS::TransferableOwnership aOwnership, + void* aContent, + uint64_t aExtraData); + + // These methods are what you should use. + + bool Write(JSContext* aCx, + JS::Handle aValue); + + bool Write(JSContext* aCx, + JS::Handle aValue, + JS::Handle aTransfer); + + bool Read(JSContext* aCx, + JS::MutableHandle aValue); + +protected: + nsAutoPtr mBuffer; +}; + +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_StructuredCloneHelper_h diff --git a/dom/base/moz.build b/dom/base/moz.build index 92fb71bd3972..d4e4499bdfe5 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -195,6 +195,7 @@ EXPORTS.mozilla.dom += [ 'ScreenOrientation.h', 'ScriptSettings.h', 'ShadowRoot.h', + 'StructuredCloneHelper.h', 'StructuredCloneTags.h', 'StyleSheetList.h', 'SubtleCrypto.h', @@ -332,6 +333,7 @@ UNIFIED_SOURCES += [ 'SameProcessMessageQueue.cpp', 'ScriptSettings.cpp', 'ShadowRoot.cpp', + 'StructuredCloneHelper.cpp', 'StyleSheetList.cpp', 'SubtleCrypto.cpp', 'Text.cpp', diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 210c00970ac2..c2c05e6466d9 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -902,7 +902,7 @@ nsDOMClassInfo::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHODIMP nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, - JSObject *obj, jsid id, jsval *vp, + JSObject *obj, jsid id, JS::Value *vp, bool *_retval) { NS_WARNING("nsDOMClassInfo::GetProperty Don't call me!"); @@ -912,7 +912,7 @@ nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHODIMP nsDOMClassInfo::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, - JSObject *obj, jsid id, jsval *vp, + JSObject *obj, jsid id, JS::Value *vp, bool *_retval) { NS_WARNING("nsDOMClassInfo::SetProperty Don't call me!"); @@ -1339,7 +1339,7 @@ public: bool *_retval); nsresult HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx, - JS::Handle obj, const jsval &val, bool *bp, + JS::Handle obj, const JS::Value &val, bool *bp, bool *_retval); nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle obj); @@ -1499,7 +1499,7 @@ nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, nsresult nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JS::Handle obj, - const jsval &v, bool *bp, bool *_retval) + const JS::Value &v, bool *bp, bool *_retval) { // No need to look these up in the hash. diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 7c68528e47d9..7eb4a6867f5a 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -3212,7 +3212,7 @@ nsDOMWindowUtils::ExitFullscreen() nsCOMPtr doc = GetDocument(); NS_ENSURE_STATE(doc); - nsIDocument::ExitFullscreen(doc, /* async */ false); + nsIDocument::ExitFullscreenInDocTree(doc); return NS_OK; } diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 5f79863ac5ed..a0a2f895b8d7 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9358,7 +9358,7 @@ nsDocument::OnPageHide(bool aPersisted, // doctree by the time OnPageHide() is called, so we must store a // reference to the root (in nsDocument::mFullscreenRoot) since we can't // just traverse the doctree to get the root. - nsIDocument::ExitFullscreen(this, /* async */ false); + nsIDocument::ExitFullscreenInDocTree(this); // Since the document is removed from the doctree before OnPageHide() is // called, ExitFullscreen() can't traverse from the root down to *this* @@ -11122,31 +11122,43 @@ SetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo *aVRHMD = nul nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue, aVRHMD)); } -class nsCallExitFullscreen : public nsRunnable { +static void +AskWindowToExitFullscreen(nsIDocument* aDoc) +{ + if (XRE_GetProcessType() == GeckoProcessType_Content) { + nsContentUtils::DispatchEventOnlyToChrome( + aDoc, ToSupports(aDoc), NS_LITERAL_STRING("MozDOMFullscreen:Exit"), + /* Bubbles */ true, /* Cancelable */ false, + /* DefaultAction */ nullptr); + } else { + SetWindowFullScreen(aDoc, false); + } +} + +class nsCallExitFullscreen : public nsRunnable +{ public: explicit nsCallExitFullscreen(nsIDocument* aDoc) : mDoc(aDoc) {} - NS_IMETHOD Run() + + NS_IMETHOD Run() override final { - nsDocument::ExitFullscreen(mDoc); + if (!mDoc) { + FullscreenRoots::ForEach(&AskWindowToExitFullscreen); + } else { + AskWindowToExitFullscreen(mDoc); + } return NS_OK; } + private: nsCOMPtr mDoc; }; -/* static */ -void -nsIDocument::ExitFullscreen(nsIDocument* aDoc, bool aRunAsync) +/* static */ void +nsIDocument::AsyncExitFullscreen(nsIDocument* aDoc) { - if (aDoc && !aDoc->IsFullScreenDoc()) { - return; - } - if (aRunAsync) { - NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc)); - return; - } - nsDocument::ExitFullscreen(aDoc); + NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc)); } static bool @@ -11193,16 +11205,16 @@ ResetFullScreen(nsIDocument* aDocument, void* aData) return true; } -static void -ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) +/* static */ void +nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) { MOZ_ASSERT(aMaybeNotARootDoc); + + // Unlock the pointer + UnlockPointer(); + nsCOMPtr root = aMaybeNotARootDoc->GetFullscreenRoot(); - NS_ASSERTION(root, "Should have root when in fullscreen!"); - if (!root) { - return; - } - if (!root->IsFullScreenDoc()) { + if (!root || !root->IsFullScreenDoc()) { // If a document was detached before exiting from fullscreen, it is // possible that the root had left fullscreen state. In this case, // we would not get anything from the ResetFullScreen() call. Root's @@ -11246,24 +11258,6 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) SetWindowFullScreen(root, false); } -/* static */ -void -nsDocument::ExitFullscreen(nsIDocument* aDoc) -{ - // Unlock the pointer - UnlockPointer(); - - if (aDoc) { - ExitFullscreenInDocTree(aDoc); - return; - } - - // Clear fullscreen stacks in all fullscreen roots' descendant documents. - FullscreenRoots::ForEach(&ExitFullscreenInDocTree); - NS_ASSERTION(FullscreenRoots::IsEmpty(), - "Should have exited all fullscreen roots from fullscreen"); -} - bool GetFullscreenLeaf(nsIDocument* aDoc, void* aData) { @@ -11318,14 +11312,7 @@ nsDocument::RestorePreviousFullScreenState() if (exitingFullscreen) { // If we are fully exiting fullscreen, don't touch anything here, // just wait for the window to get out from fullscreen first. - if (XRE_GetProcessType() == GeckoProcessType_Content) { - nsContentUtils::DispatchEventOnlyToChrome( - this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"), - /* Bubbles */ true, /* Cancelable */ false, - /* DefaultAction */ nullptr); - } else { - SetWindowFullScreen(this, false); - } + AskWindowToExitFullscreen(this); return; } diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 1fe77e78b35e..07fe43d8809b 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -1242,8 +1242,6 @@ public: // already_AddRefed BlockedTrackingNodes() const; - static void ExitFullscreen(nsIDocument* aDoc); - // Do the "fullscreen element ready check" from the fullscreen spec. // It returns true if the given element is allowed to go into fullscreen. bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome); diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index d9062250da93..aa3a24a6c883 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1249,7 +1249,7 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags, contentToFocus->OwnerDoc(), nsContentUtils::eDOM_PROPERTIES, "FocusedWindowedPluginWhileFullScreen"); - nsIDocument::ExitFullscreen(contentToFocus->OwnerDoc(), /* async */ true); + nsIDocument::AsyncExitFullscreen(contentToFocus->OwnerDoc()); } #endif diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index dd6f00072d68..65b5c79efc2b 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -6308,11 +6308,9 @@ FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen) // Ask the document to handle any pending DOM fullscreen change. nsIDocument::HandlePendingFullscreenRequests(aDoc); } else { - // Force exit from DOM full-screen mode. This is so that if we're in - // DOM full-screen mode and the user exits full-screen mode with - // the browser full-screen mode toggle keyboard-shortcut, we'll detect - // that and leave DOM API full-screen mode too. - nsIDocument::ExitFullscreen(aDoc, /* async */ false); + // If the window is leaving fullscreen state, also ask the document + // to exit from DOM Fullscreen. + nsIDocument::ExitFullscreenInDocTree(aDoc); } } diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 1b519857b544..bca3dbaa62c1 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -1165,24 +1165,29 @@ public: virtual void SetApprovedForFullscreen(bool aIsApproved) = 0; /** - * Exits documents out of DOM fullscreen mode. + * Synchronously cleans up the fullscreen state on the given document. * - * If aDocument is null, all fullscreen documents in all browser windows - * exit fullscreen. + * Calling this without performing fullscreen transition could lead + * to undesired effect (the transition happens after document state + * flips), hence it should only be called either by nsGlobalWindow + * when we have performed the transition, or when it is necessary to + * clean up the state immediately. Otherwise, AsyncExitFullscreen() + * should be called instead. * - * If aDocument is non null, all documents from aDocument's fullscreen root - * to the fullscreen leaf exit fullscreen. - * - * Note that the fullscreen leaf is the bottom-most document which is - * fullscreen, it may have non-fullscreen child documents. The fullscreen - * root is normally the chrome document. - * - * If aRunAsync is true, fullscreen is executed asynchronously. - * - * Note if aDocument is not fullscreen this function has no effect, even if - * aDocument has fullscreen ancestors. + * aDocument must not be null. */ - static void ExitFullscreen(nsIDocument* aDocument, bool aRunAsync); + static void ExitFullscreenInDocTree(nsIDocument* aDocument); + + /** + * Ask the document to exit fullscreen state asynchronously. + * + * Different from ExitFullscreenInDocTree(), this allows the window + * to perform fullscreen transition first if any. + * + * If aDocument is null, it will exit fullscreen from all documents + * in all windows. + */ + static void AsyncExitFullscreen(nsIDocument* aDocument); /** * Handles one single fullscreen request, updates `aHandled` if the request diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 5db21a16237e..39e94d356e5a 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -1512,6 +1512,15 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage) nsIDocument* doc = GetOurCurrentDoc(); if (doc && (mFrameCreateCalled || GetOurPrimaryFrame()) && (mVisibleCount > 0)) { + + if (mVisibleCount == 1) { + // Since we're becoming visible, request a decode. + nsImageFrame* f = do_QueryFrame(GetOurPrimaryFrame()); + if (f) { + f->MaybeDecodeForPredictedSize(); + } + } + if (aImage == mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) { mCurrentRequestFlags |= REQUEST_IS_TRACKED; doc->AddImage(mCurrentRequest); diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 91d042d48840..a369b961baa0 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1485,8 +1485,10 @@ nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy) nsIDocument* doc = thisContent->OwnerDoc(); + nsContentPolicyType contentPolicyType = GetContentPolicyType(); + *aContentPolicy = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT, + nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, mURI, doc->NodePrincipal(), thisContent, @@ -1532,7 +1534,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy) objectType = nsIContentPolicy::TYPE_DOCUMENT; break; case eType_Plugin: - objectType = nsIContentPolicy::TYPE_OBJECT; + objectType = GetContentPolicyType(); break; default: NS_NOTREACHED("Calling checkProcessPolicy with a unloadable type"); @@ -2485,11 +2487,13 @@ nsObjectLoadingContent::OpenChannel() securityFlags |= nsILoadInfo::SEC_SANDBOXED; } + nsContentPolicyType contentPolicyType = GetContentPolicyType(); + rv = NS_NewChannel(getter_AddRefs(chan), mURI, thisContent, securityFlags, - nsIContentPolicy::TYPE_OBJECT, + contentPolicyType, group, // aLoadGroup shim, // aCallbacks nsIChannel::LOAD_CALL_CONTENT_SNIFFERS | diff --git a/dom/base/nsObjectLoadingContent.h b/dom/base/nsObjectLoadingContent.h index 8a9de6380848..d246eac042cb 100644 --- a/dom/base/nsObjectLoadingContent.h +++ b/dom/base/nsObjectLoadingContent.h @@ -17,6 +17,7 @@ #include "nsImageLoadingContent.h" #include "nsIStreamListener.h" #include "nsIChannelEventSink.h" +#include "nsIContentPolicy.h" #include "nsIObjectLoadingContent.h" #include "nsIRunnable.h" #include "nsIThreadInternal.h" @@ -332,6 +333,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent void UnbindFromTree(bool aDeep = true, bool aNullParent = true); + /** + * Return the content policy type used for loading the element. + */ + virtual nsContentPolicyType GetContentPolicyType() const = 0; + private: // Object parameter changes returned by UpdateObjectParameters diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index 53ba875c0a4c..e115338f0cbe 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -36,22 +36,10 @@ function getIntPref(prefName, def) { } } -function visibilityChangeHandler(e) { - // The visibilitychange event's target is the document. - let win = e.target.defaultView; - - if (!win._browserElementParents) { - return; - } - - let beps = Cu.nondeterministicGetWeakMapKeys(win._browserElementParents); - if (beps.length == 0) { - win.removeEventListener('visibilitychange', visibilityChangeHandler); - return; - } - - for (let i = 0; i < beps.length; i++) { - beps[i]._ownerVisibilityChange(); +function handleWindowEvent(e) { + if (this._browserElementParents) { + let beps = Cu.nondeterministicGetWeakMapKeys(this._browserElementParents); + beps.forEach(bep => bep._handleOwnerEvent(e)); } } @@ -119,10 +107,14 @@ BrowserElementParent.prototype = { // BrowserElementParents. if (!this._window._browserElementParents) { this._window._browserElementParents = new WeakMap(); - this._window.addEventListener('visibilitychange', - visibilityChangeHandler, - /* useCapture = */ false, - /* wantsUntrusted = */ false); + let handler = handleWindowEvent.bind(this._window); + let windowEvents = ['visibilitychange', 'mozfullscreenchange']; + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); + for (let event of windowEvents) { + els.addSystemEventListener(this._window, event, handler, + /* useCapture = */ true); + } } this._window._browserElementParents.set(this, null); @@ -131,11 +123,6 @@ BrowserElementParent.prototype = { BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this); this._setupMessageListener(); this._registerAppManifest(); - - let els = Cc["@mozilla.org/eventlistenerservice;1"] - .getService(Ci.nsIEventListenerService); - els.addSystemEventListener(this._window.document, "mozfullscreenchange", - this._fullscreenChange.bind(this), true); }, _runPendingAPICall: function() { @@ -1056,14 +1043,19 @@ BrowserElementParent.prototype = { this._windowUtils.remoteFrameFullscreenReverted(); }, - _fullscreenChange: function(evt) { - if (this._isAlive() && evt.target == this._window.document) { - if (!this._window.document.mozFullScreen) { - this._sendAsyncMsg("exit-fullscreen"); - } else if (this._pendingDOMFullscreen) { - this._pendingDOMFullscreen = false; - this._sendAsyncMsg("entered-fullscreen"); - } + _handleOwnerEvent: function(evt) { + switch (evt.type) { + case 'visibilitychange': + this._ownerVisibilityChange(); + break; + case 'mozfullscreenchange': + if (!this._window.document.mozFullScreen) { + this._sendAsyncMsg('exit-fullscreen'); + } else if (this._pendingDOMFullscreen) { + this._pendingDOMFullscreen = false; + this._sendAsyncMsg('entered-fullscreen'); + } + break; } }, diff --git a/dom/canvas/WebGL2ContextFramebuffers.cpp b/dom/canvas/WebGL2ContextFramebuffers.cpp index eeb7cd5e28ff..47356b4a96b6 100644 --- a/dom/canvas/WebGL2ContextFramebuffers.cpp +++ b/dom/canvas/WebGL2ContextFramebuffers.cpp @@ -498,31 +498,38 @@ WebGL2Context::ReadBuffer(GLenum mode) if (IsContextLost()) return; - MakeContextCurrent(); + const bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 && + mode <= LastColorAttachment()); + + if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK && !isColorAttachment) { + ErrorInvalidEnum("readBuffer: `mode` must be one of NONE, BACK, or " + "COLOR_ATTACHMENTi. Was %s", + EnumName(mode)); + return; + } if (mBoundReadFramebuffer) { - bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 && - mode <= LastColorAttachment()); if (mode != LOCAL_GL_NONE && !isColorAttachment) { - ErrorInvalidEnumInfo("readBuffer: If READ_FRAMEBUFFER is non-null," - " `mode` must be COLOR_ATTACHMENTN or NONE." - " Was:", mode); + ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is non-null, `mode` " + "must be COLOR_ATTACHMENTi or NONE. Was %s", + EnumName(mode)); return; } + MakeContextCurrent(); gl->fReadBuffer(mode); return; } // Operating on the default framebuffer. - if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK) { - ErrorInvalidEnumInfo("readBuffer: If READ_FRAMEBUFFER is null, `mode`" - " must be BACK or NONE. Was:", mode); + ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is null, `mode`" + " must be BACK or NONE. Was %s", + EnumName(mode)); return; } diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index edf469e4890f..ffbe754b8632 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -1403,10 +1403,8 @@ protected: WebGLRefPtr mCurrentProgram; RefPtr mActiveProgramLinkInfo; - uint32_t mMaxFramebufferColorAttachments; - GLenum LastColorAttachment() const { - return LOCAL_GL_COLOR_ATTACHMENT0 + mMaxFramebufferColorAttachments - 1; + return LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments - 1; } bool ValidateFramebufferTarget(GLenum target, const char* const info); diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index 51292042c7c1..bd2a1349df7b 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -401,15 +401,8 @@ WebGLContext::ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum a return true; } - GLenum colorAttachCount = 1; - if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) - colorAttachCount = mGLMaxColorAttachments; - - if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 && - attachment < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + colorAttachCount)) - { + if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 && attachment <= LastColorAttachment()) return true; - } ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment); @@ -1885,9 +1878,6 @@ WebGLContext::InitAndValidateGL() } } - // Always 1 for GLES2 - mMaxFramebufferColorAttachments = 1; - if (gl->IsCompatibilityProfile()) { // gl_PointSize is always available in ES2 GLSL, but has to be // specifically enabled on desktop GLSL. diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 27e7197c6a64..3c4ce1a28b54 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -398,7 +398,8 @@ EventListenerManager::AddEventListenerInternal( } if (mIsMainThreadELM && mTarget) { - EventListenerService::NotifyAboutMainThreadListenerChange(mTarget); + EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, + aTypeAtom); } } @@ -518,7 +519,8 @@ EventListenerManager::RemoveEventListenerInternal( mTarget->EventListenerRemoved(aUserType); } if (mIsMainThreadELM && mTarget) { - EventListenerService::NotifyAboutMainThreadListenerChange(mTarget); + EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, + aUserType); } if (!deviceType @@ -654,7 +656,7 @@ EventListenerManager::SetEventHandlerInternal( mTarget->EventListenerAdded(aName); } if (mIsMainThreadELM && mTarget) { - EventListenerService::NotifyAboutMainThreadListenerChange(mTarget); + EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName); } } @@ -784,7 +786,7 @@ EventListenerManager::RemoveEventHandler(nsIAtom* aName, mTarget->EventListenerRemoved(aName); } if (mIsMainThreadELM && mTarget) { - EventListenerService::NotifyAboutMainThreadListenerChange(mTarget); + EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName); } } } diff --git a/dom/events/EventListenerService.cpp b/dom/events/EventListenerService.cpp index 7d2f43713134..94189b6ab9c2 100644 --- a/dom/events/EventListenerService.cpp +++ b/dom/events/EventListenerService.cpp @@ -23,6 +23,44 @@ namespace mozilla { using namespace dom; +/****************************************************************************** + * mozilla::EventListenerChange + ******************************************************************************/ + +NS_IMPL_ISUPPORTS(EventListenerChange, nsIEventListenerChange) + +EventListenerChange::~EventListenerChange() +{ +} + +EventListenerChange::EventListenerChange(dom::EventTarget* aTarget) : + mTarget(aTarget) +{ + mChangedListenerNames = nsArrayBase::Create(); +} + +void +EventListenerChange::AddChangedListenerName(nsIAtom* aEventName) +{ + mChangedListenerNames->AppendElement(aEventName, false); +} + +NS_IMETHODIMP +EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget) +{ + NS_ENSURE_ARG_POINTER(aTarget); + NS_ADDREF(*aTarget = mTarget); + return NS_OK; +} + +NS_IMETHODIMP +EventListenerChange::GetChangedListenerNames(nsIArray** aEventNames) +{ + NS_ENSURE_ARG_POINTER(aEventNames); + NS_ADDREF(*aEventNames = mChangedListenerNames); + return NS_OK; +} + /****************************************************************************** * mozilla::EventListenerInfo ******************************************************************************/ @@ -323,7 +361,8 @@ EventListenerService::RemoveListenerChangeListener(nsIListenerChangeListener* aL }; void -EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget) +EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget, + nsIAtom* aName) { MOZ_ASSERT(NS_IsMainThread()); if (mChangeListeners.IsEmpty()) { @@ -337,10 +376,13 @@ EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarg NS_DispatchToCurrentThread(runnable); } - if (!mPendingListenerChangesSet.Get(aTarget)) { - mPendingListenerChanges->AppendElement(aTarget, false); - mPendingListenerChangesSet.Put(aTarget, true); + nsRefPtr changes = mPendingListenerChangesSet.Get(aTarget); + if (!changes) { + changes = new EventListenerChange(aTarget); + mPendingListenerChanges->AppendElement(changes, false); + mPendingListenerChangesSet.Put(aTarget, changes); } + changes->AddChangedListenerName(aName); } void diff --git a/dom/events/EventListenerService.h b/dom/events/EventListenerService.h index 51be12b065ba..3b67af0c8d5b 100644 --- a/dom/events/EventListenerService.h +++ b/dom/events/EventListenerService.h @@ -16,6 +16,7 @@ #include "nsString.h" #include "nsTObserverArray.h" #include "nsDataHashtable.h" +#include "nsGkAtoms.h" class nsIMutableArray; @@ -27,6 +28,23 @@ class EventTarget; template class Maybe; +class EventListenerChange final : public nsIEventListenerChange +{ +public: + explicit EventListenerChange(dom::EventTarget* aTarget); + + void AddChangedListenerName(nsIAtom* aEventName); + + NS_DECL_ISUPPORTS + NS_DECL_NSIEVENTLISTENERCHANGE + +protected: + virtual ~EventListenerChange(); + nsCOMPtr mTarget; + nsCOMPtr mChangedListenerNames; + +}; + class EventListenerInfo final : public nsIEventListenerInfo { public: @@ -70,19 +88,21 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIEVENTLISTENERSERVICE - static void NotifyAboutMainThreadListenerChange(dom::EventTarget* aTarget) + static void NotifyAboutMainThreadListenerChange(dom::EventTarget* aTarget, + nsIAtom* aName) { if (sInstance) { - sInstance->NotifyAboutMainThreadListenerChangeInternal(aTarget); + sInstance->NotifyAboutMainThreadListenerChangeInternal(aTarget, aName); } } void NotifyPendingChanges(); private: - void NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget); + void NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget, + nsIAtom* aName); nsTObserverArray> mChangeListeners; nsCOMPtr mPendingListenerChanges; - nsDataHashtable mPendingListenerChangesSet; + nsDataHashtable> mPendingListenerChangesSet; static EventListenerService* sInstance; }; diff --git a/dom/events/nsIEventListenerService.idl b/dom/events/nsIEventListenerService.idl index 250f208bfe63..46c65e21dd5d 100644 --- a/dom/events/nsIEventListenerService.idl +++ b/dom/events/nsIEventListenerService.idl @@ -9,10 +9,21 @@ interface nsIDOMEventListener; interface nsIDOMEventTarget; interface nsIArray; -[scriptable, function, uuid(8d5b5a6b-dec0-473d-86c4-591801dfaac1)] +/** + * Contains an event target along with an array of nsIAtom in form "oneventname" + * representing changed event listener names. + */ +[scriptable, uuid(07222b02-da12-4cf4-b2f7-761da007a8d8)] +interface nsIEventListenerChange : nsISupports +{ + readonly attribute nsIDOMEventTarget target; + readonly attribute nsIArray changedListenerNames; +}; + +[scriptable, function, uuid(aa7c95f6-d3b5-44b3-9597-1d9f19b9c5f2)] interface nsIListenerChangeListener : nsISupports { - void listenersChanged(in nsIArray aEventTargets); + void listenersChanged(in nsIArray aEventListenerChanges); }; /** diff --git a/dom/events/test/test_bug524674.xul b/dom/events/test/test_bug524674.xul index 4efc80859dbb..463d9269b31d 100644 --- a/dom/events/test/test_bug524674.xul +++ b/dom/events/test/test_bug524674.xul @@ -22,6 +22,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674 var els = Components.classes["@mozilla.org/eventlistenerservice;1"] .getService(Components.interfaces.nsIEventListenerService); + const Ci = Components.interfaces; + function dummyListener() {} var runningTest = null; @@ -35,29 +37,49 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674 d.addEventListener("foo", dummyListener); d.addEventListener("foo", dummyListener); xhr.addEventListener("foo", dummyListener); - tests[0] = [d, xhr]; + tests[0] = [{target: d, listeners: ["onfoo"]}, + {target: xhr, listeners: ["onfoo"]}]; + }, + function() { + d.addEventListener("bar", dummyListener); + d.addEventListener("baz", dummyListener); + xhr.addEventListener("bar", dummyListener); + xhr.addEventListener("baz", dummyListener); + tests[0] = [{target: d, listeners: ["onbaz", "onbar"]}, + {target: xhr, listeners: ["onbaz", "onbar"]}]; }, function() { d.onclick = dummyListener; d.onclick = dummyListener; xhr.onload = dummyListener; - tests[0] = [d, xhr]; + tests[0] = [{target: d, listeners: ["onclick"]}, + {target: xhr, listeners: ["onload"]}]; }, function() { d.onclick = function() {}; - tests[0] = [d]; + tests[0] = [{target: d, listeners: ["onclick"]}]; }, function() { d.removeEventListener("foo", dummyListener); d.removeEventListener("foo", dummyListener); xhr.removeEventListener("foo", dummyListener); - tests[0] = [d, xhr]; + tests[0] = [{target: d, listeners: ["onfoo"]}, + {target: xhr, listeners: ["onfoo"]}]; + }, + function() { + d.removeEventListener("bar", dummyListener); + d.removeEventListener("baz", dummyListener); + xhr.removeEventListener("bar", dummyListener); + xhr.removeEventListener("baz", dummyListener); + tests[0] = [{target: d, listeners: ["onbar", "onbaz"]}, + {target: xhr, listeners: ["onbar", "onbaz"]}]; }, function() { d.onclick = null; d.onclick = null; xhr.onload = null; - tests[0] = [d, xhr]; + tests[0] = [{target: d, listeners: ["onclick"]}, + {target: xhr, listeners: ["onload"]}]; }, function() { els.removeListenerChangeListener(changeListener); @@ -76,29 +98,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674 if (typeof tests[0] == "function") { return; } - var expectedEventTargets = tests[0]; - var e = array.enumerate(); + var expectedEventChanges = tests[0]; + var eventChanges = array.enumerate(); var i = 0; - while (e.hasMoreElements()) { + while (eventChanges.hasMoreElements() && i < expectedEventChanges.length) { var current; try { - current = e.getNext(); + current = eventChanges.getNext().QueryInterface(Ci.nsIEventListenerChange); + var expected = expectedEventChanges[i]; + + if (current.target == expected.target) { + // expected.target.listeners should be a subset of + // current.changedListenerNames if all expected listener changes were + // sent. We may get random other event listener changes here too, not + // just the one from the test. + is(current.target, expected.target, current.target + " = " + expected.target); + + var eNames = current.changedListenerNames.enumerate(); + var listeners = []; + while (eNames.hasMoreElements()) { + var listenerName = eNames.getNext().QueryInterface(Ci.nsIAtom).toString(); + listeners.push(listenerName); + } + var matchAll = expected.listeners.every(function(val) + { return listeners.indexOf(val) >= 0; }); + if (!matchAll) + return; + ++i; + } } catch(ex) { continue; } - var expected = expectedEventTargets[i]; - if (current == expected) { - is(current, expected, current + " = " + expected); - // We may get random other event listener changes here too, not just the one from the - // test. - ++i - } } - if (expectedEventTargets.length != i) { + if (expectedEventChanges.length != i) { return; } - is(expectedEventTargets.length, i, "Should have got notification for all the changes."); + is(expectedEventChanges.length, i, "Should have got notification for all the changes."); tests.shift(); ok(tests.length); diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp index 86b5c42e563a..998df50d6446 100644 --- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -128,15 +128,21 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte case nsIContentPolicy::TYPE_STYLESHEET: context = RequestContext::Style; break; - case nsIContentPolicy::TYPE_OBJECT: + case nsIContentPolicy::TYPE_INTERNAL_OBJECT: context = RequestContext::Object; break; + case nsIContentPolicy::TYPE_INTERNAL_EMBED: + context = RequestContext::Embed; + break; case nsIContentPolicy::TYPE_DOCUMENT: context = RequestContext::Internal; break; - case nsIContentPolicy::TYPE_SUBDOCUMENT: + case nsIContentPolicy::TYPE_INTERNAL_IFRAME: context = RequestContext::Iframe; break; + case nsIContentPolicy::TYPE_INTERNAL_FRAME: + context = RequestContext::Frame; + break; case nsIContentPolicy::TYPE_REFRESH: context = RequestContext::Internal; break; diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h index d20ac226f007..40a70d49aa67 100644 --- a/dom/fetch/InternalRequest.h +++ b/dom/fetch/InternalRequest.h @@ -34,22 +34,22 @@ namespace dom { * beacon | TYPE_BEACON * cspreport | TYPE_CSP_REPORT * download | - * embed | TYPE_OBJECT + * embed | TYPE_INTERNAL_EMBED * eventsource | * favicon | * fetch | TYPE_FETCH * font | TYPE_FONT * form | - * frame | TYPE_SUBDOCUMENT + * frame | TYPE_INTERNAL_FRAME * hyperlink | - * iframe | TYPE_SUBDOCUMENT + * iframe | TYPE_INTERNAL_IFRAME * image | TYPE_IMAGE * imageset | TYPE_IMAGESET * import | Not supported by Gecko * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER * location | * manifest | TYPE_WEB_MANIFEST - * object | TYPE_OBJECT + * object | TYPE_INTERNAL_OBJECT * ping | TYPE_PING * plugin | TYPE_OBJECT_SUBREQUEST * prefetch | @@ -67,7 +67,6 @@ namespace dom { * TODO: Figure out if TYPE_DTD maps to anything useful * TODO: Split TYPE_XMLHTTPREQUEST and TYPE_DATAREQUEST for EventSource * TODO: Figure out if TYPE_WEBSOCKET maps to anything useful - * TODO: Differentiate between frame and iframe * TODO: Add a content type for prefetch * TODO: Use the content type for manifest when it becomes available * TODO: Add a content type for location @@ -75,7 +74,6 @@ namespace dom { * TODO: Add a content type for form * TODO: Add a content type for favicon * TODO: Add a content type for download - * TODO: Split TYPE_OBJECT into TYPE_EMBED and TYPE_OBJECT */ class Request; diff --git a/dom/html/HTMLContentElement.cpp b/dom/html/HTMLContentElement.cpp index a3ce716d0409..964b6c72088f 100644 --- a/dom/html/HTMLContentElement.cpp +++ b/dom/html/HTMLContentElement.cpp @@ -297,10 +297,12 @@ HTMLContentElement::GetDistributedNodes() return list.forget(); } -NS_IMPL_CYCLE_COLLECTION(DistributedContentList, mParent, mDistributedNodes) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DistributedContentList, mParent, + mDistributedNodes) NS_INTERFACE_TABLE_HEAD(DistributedContentList) - NS_INTERFACE_TABLE(DistributedContentList, nsINodeList) + NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY + NS_INTERFACE_TABLE(DistributedContentList, nsINodeList, nsIDOMNodeList) NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DistributedContentList) NS_INTERFACE_MAP_END diff --git a/dom/html/HTMLContentElement.h b/dom/html/HTMLContentElement.h index 7dbf4d4f7209..ce95a686fd40 100644 --- a/dom/html/HTMLContentElement.h +++ b/dom/html/HTMLContentElement.h @@ -102,7 +102,7 @@ public: explicit DistributedContentList(HTMLContentElement* aHostElement); NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(DistributedContentList) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DistributedContentList) // nsIDOMNodeList NS_DECL_NSIDOMNODELIST diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 268ded9dbda4..bade5a28aae9 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -1172,25 +1172,6 @@ nsresult HTMLMediaElement::LoadResource() return NS_ERROR_FAILURE; } - MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video)); - nsContentPolicyType contentPolicyType = IsHTMLElement(nsGkAtoms::audio) ? - nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO; - - int16_t shouldLoad = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, - mLoadingSrc, - NodePrincipal(), - static_cast(this), - EmptyCString(), // mime type - nullptr, // extra - &shouldLoad, - nsContentUtils::GetContentPolicy(), - nsContentUtils::GetSecurityManager()); - NS_ENSURE_SUCCESS(rv, rv); - if (NS_CP_REJECTED(shouldLoad)) { - return NS_ERROR_FAILURE; - } - // Set the media element's CORS mode only when loading a resource mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); @@ -1212,7 +1193,7 @@ nsresult HTMLMediaElement::LoadResource() if (IsMediaStreamURI(mLoadingSrc)) { nsRefPtr stream; - rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream)); + nsresult rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream)); if (NS_FAILED(rv)) { nsAutoString spec; GetCurrentSrc(spec); @@ -1240,27 +1221,31 @@ nsresult HTMLMediaElement::LoadResource() return FinishDecoderSetup(decoder, resource, nullptr, nullptr); } - nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL; - if (nsContentUtils::ChannelShouldInheritPrincipal(NodePrincipal(), - mLoadingSrc, - false, // aInheritForAboutBlank - false // aForceInherit - )) { - securityFlags = nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; + // determine what security checks need to be performed in AsyncOpen2(). + nsSecurityFlags securityFlags = + ShouldCheckAllowOrigin() ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS : + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS; + + if (GetCORSMode() == CORS_USE_CREDENTIALS) { + securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS; } + MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video)); + nsContentPolicyType contentPolicyType = IsHTMLElement(nsGkAtoms::audio) ? + nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO; + nsCOMPtr loadGroup = GetDocumentLoadGroup(); nsCOMPtr channel; - rv = NS_NewChannel(getter_AddRefs(channel), - mLoadingSrc, - static_cast(this), - securityFlags, - contentPolicyType, - loadGroup, - nullptr, // aCallbacks - nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | - nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE | - nsIChannel::LOAD_CALL_CONTENT_SNIFFERS); + nsresult rv = NS_NewChannel(getter_AddRefs(channel), + mLoadingSrc, + static_cast(this), + securityFlags, + contentPolicyType, + loadGroup, + nullptr, // aCallbacks + nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | + nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE | + nsIChannel::LOAD_CALL_CONTENT_SNIFFERS); NS_ENSURE_SUCCESS(rv,rv); @@ -1274,24 +1259,6 @@ nsresult HTMLMediaElement::LoadResource() channel->SetNotificationCallbacks(loadListener); - nsCOMPtr listener; - if (ShouldCheckAllowOrigin()) { - nsRefPtr corsListener = - new nsCORSListenerProxy(loadListener, - NodePrincipal(), - GetCORSMode() == CORS_USE_CREDENTIALS); - rv = corsListener->Init(channel, DataURIHandling::Allow); - NS_ENSURE_SUCCESS(rv, rv); - listener = corsListener; - } else { - rv = nsContentUtils::GetSecurityManager()-> - CheckLoadURIWithPrincipal(NodePrincipal(), - mLoadingSrc, - nsIScriptSecurityManager::STANDARD); - listener = loadListener; - NS_ENSURE_SUCCESS(rv, rv); - } - nsCOMPtr hc = do_QueryInterface(channel); if (hc) { // Use a byte range request from the start of the resource. @@ -1304,7 +1271,7 @@ nsresult HTMLMediaElement::LoadResource() SetRequestHeaders(hc); } - rv = channel->AsyncOpen(listener, nullptr); + rv = channel->AsyncOpen2(loadListener); NS_ENSURE_SUCCESS(rv, rv); // Else the channel must be open and starting to download. If it encounters diff --git a/dom/html/HTMLObjectElement.h b/dom/html/HTMLObjectElement.h index 64ec1de99489..1526a7b24ba7 100644 --- a/dom/html/HTMLObjectElement.h +++ b/dom/html/HTMLObjectElement.h @@ -246,7 +246,12 @@ private: * value. This is used to know the default tabindex value. */ bool IsFocusableForTabIndex(); - + + nsContentPolicyType GetContentPolicyType() const override + { + return nsIContentPolicy::TYPE_INTERNAL_OBJECT; + } + virtual void GetItemValueText(DOMString& text) override; virtual void SetItemValueText(const nsAString& text) override; diff --git a/dom/html/HTMLSharedObjectElement.cpp b/dom/html/HTMLSharedObjectElement.cpp index 24da41be3e4b..7317746df37b 100644 --- a/dom/html/HTMLSharedObjectElement.cpp +++ b/dom/html/HTMLSharedObjectElement.cpp @@ -387,5 +387,18 @@ HTMLSharedObjectElement::WrapNode(JSContext* aCx, JS::Handle aGivenPr return rootedObj; } +nsContentPolicyType +HTMLSharedObjectElement::GetContentPolicyType() const +{ + if (mNodeInfo->Equals(nsGkAtoms::applet)) { + // We use TYPE_INTERNAL_OBJECT for applet too, since it is not exposed + // through RequestContext yet. + return nsIContentPolicy::TYPE_INTERNAL_OBJECT; + } else { + MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed)); + return nsIContentPolicy::TYPE_INTERNAL_EMBED; + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/html/HTMLSharedObjectElement.h b/dom/html/HTMLSharedObjectElement.h index a4df86064ffb..70c3e4b6bed5 100644 --- a/dom/html/HTMLSharedObjectElement.h +++ b/dom/html/HTMLSharedObjectElement.h @@ -207,6 +207,8 @@ private: nsGkAtoms::src; } + nsContentPolicyType GetContentPolicyType() const override; + // mIsDoneAddingChildren is only really used for . This boolean is // always true for , per the documentation in nsIContent.h. bool mIsDoneAddingChildren; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 9ad605a95d0b..7c975f64ff5c 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -163,7 +163,7 @@ parent: bool aSizeSpecified, nsString aURI, nsString aName, - nsString aFeatures, + nsCString aFeatures, nsString aBaseURI) returns (nsresult rv, bool windowOpened, diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 1e8783d45e96..47b6df3751e7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1597,16 +1597,12 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener, nsAutoCString baseURIString; baseURI->GetSpec(baseURIString); - // We can assume that if content is requesting to open a window from a remote - // tab, then we want to enforce that the new window is also a remote tab. - features.AppendLiteral(",remote"); - nsresult rv; if (!SendCreateWindow(newChild, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, url, - name, NS_ConvertUTF8toUTF16(features), + name, features, NS_ConvertUTF8toUTF16(baseURIString), &rv, aWindowIsNew, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 82f9bac685ac..341cab06253e 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -612,7 +612,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab, const bool& aSizeSpecified, const nsString& aURI, const nsString& aName, - const nsString& aFeatures, + const nsCString& aFeatures, const nsString& aBaseURI, nsresult* aResult, bool* aWindowIsNew, @@ -622,6 +622,13 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab, // We always expect to open a new window here. If we don't, it's an error. *aWindowIsNew = true; + // The content process should never be in charge of computing whether or + // not a window should be private or remote - the parent will do that. + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)); + if (NS_WARN_IF(IsBrowserOrApp())) return false; @@ -735,9 +742,11 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab, AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad); + const char* features = aFeatures.Length() ? aFeatures.get() : nullptr; + *aResult = pwwatch->OpenWindow2(parent, finalURIString.get(), NS_ConvertUTF16toUTF8(aName).get(), - NS_ConvertUTF16toUTF8(aFeatures).get(), aCalledFromJS, + features, aCalledFromJS, false, false, this, nullptr, getter_AddRefs(window)); if (NS_WARN_IF(NS_FAILED(*aResult))) @@ -3136,7 +3145,9 @@ public: NS_IMETHOD GetContentLength(int64_t*) NO_IMPL NS_IMETHOD SetContentLength(int64_t) NO_IMPL NS_IMETHOD Open(nsIInputStream**) NO_IMPL + NS_IMETHOD Open2(nsIInputStream**) NO_IMPL NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL + NS_IMETHOD AsyncOpen2(nsIStreamListener*) NO_IMPL NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 2cc56eebdfcc..d67b07332142 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -142,7 +142,7 @@ public: const bool& aSizeSpecified, const nsString& aURI, const nsString& aName, - const nsString& aFeatures, + const nsCString& aFeatures, const nsString& aBaseURI, nsresult* aResult, bool* aWindowIsNew, diff --git a/dom/jsurl/nsJSProtocolHandler.cpp b/dom/jsurl/nsJSProtocolHandler.cpp index 0018339a5bff..e024f4c53311 100644 --- a/dom/jsurl/nsJSProtocolHandler.cpp +++ b/dom/jsurl/nsJSProtocolHandler.cpp @@ -50,6 +50,7 @@ #include "nsSandboxFlags.h" #include "mozilla/dom/ScriptSettings.h" #include "nsILoadInfo.h" +#include "nsContentSecurityManager.h" #include "mozilla/ipc/URIUtils.h" @@ -552,6 +553,15 @@ nsJSChannel::Open(nsIInputStream **aResult) return mStreamChannel->Open(aResult); } +NS_IMETHODIMP +nsJSChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + NS_IMETHODIMP nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) { @@ -663,6 +673,15 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) return rv; } +NS_IMETHODIMP +nsJSChannel::AsyncOpen2(nsIStreamListener *aListener) +{ + nsCOMPtr listener = aListener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return AsyncOpen(listener, nullptr); +} + void nsJSChannel::EvaluateScript() { diff --git a/dom/media/gstreamer/GStreamerFormatHelper.cpp b/dom/media/gstreamer/GStreamerFormatHelper.cpp index c4b4fa335d45..3e989254db40 100644 --- a/dom/media/gstreamer/GStreamerFormatHelper.cpp +++ b/dom/media/gstreamer/GStreamerFormatHelper.cpp @@ -258,8 +258,9 @@ static gboolean FactoryFilter(GstPluginFeature *aFeature, gpointer) const gchar *className = gst_element_factory_get_klass(GST_ELEMENT_FACTORY_CAST(aFeature)); - if (!strstr(className, "Decoder") && !strstr(className, "Demux") && - !strstr(className, "Parser")) { + // NB: We skip filtering parsers here, because adding them to + // the list can give false decoder positives to canPlayType(). + if (!strstr(className, "Decoder") && !strstr(className, "Demux")) { return FALSE; } diff --git a/dom/media/mediasource/TrackBuffer.cpp b/dom/media/mediasource/TrackBuffer.cpp index 52b16235ac74..c9dae754ab8f 100644 --- a/dom/media/mediasource/TrackBuffer.cpp +++ b/dom/media/mediasource/TrackBuffer.cpp @@ -298,7 +298,11 @@ TrackBuffer::AppendDataToCurrentResource(MediaByteBuffer* aData, uint32_t aDurat nsRefPtr TrackBuffer::UpdateBufferedRanges(Interval aByteRange, bool aNotifyParent) { - if (aByteRange.Length()) { + if (!mParentDecoder) { + return BufferedRangesUpdatedPromise::CreateAndResolve(true, __func__); + } + + if (mCurrentDecoder && aByteRange.Length()) { mCurrentDecoder->GetReader()->NotifyDataArrived(aByteRange); } diff --git a/dom/media/platforms/wmf/WMFDecoderModule.cpp b/dom/media/platforms/wmf/WMFDecoderModule.cpp index ca25fafb3d1e..6f814633f899 100644 --- a/dom/media/platforms/wmf/WMFDecoderModule.cpp +++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp @@ -19,11 +19,13 @@ #include "GfxDriverInfo.h" #include "gfxWindowsPlatform.h" #include "MediaInfo.h" +#include "prsystem.h" namespace mozilla { static bool sIsWMFEnabled = false; static bool sDXVAEnabled = false; +static int sNumDecoderThreads = -1; WMFDecoderModule::WMFDecoderModule() : mWMFInitialized(false) @@ -44,6 +46,25 @@ WMFDecoderModule::DisableHardwareAcceleration() sDXVAEnabled = false; } +static void +SetNumOfDecoderThreads() +{ + MOZ_ASSERT(NS_IsMainThread(), "Preferences can only be read on main thread"); + int32_t numCores = PR_GetNumberOfProcessors(); + + // If we have more than 4 cores, let the decoder decide how many threads. + // On an 8 core machine, WMF chooses 4 decoder threads + const int WMF_DECODER_DEFAULT = -1; + int32_t prefThreadCount = Preferences::GetInt("media.wmf.decoder.thread-count", -1); + if (prefThreadCount != WMF_DECODER_DEFAULT) { + sNumDecoderThreads = std::max(prefThreadCount, 1); + } else if (numCores > 4) { + sNumDecoderThreads = WMF_DECODER_DEFAULT; + } else { + sNumDecoderThreads = std::max(numCores - 1, 1); + } +} + /* static */ void WMFDecoderModule::Init() @@ -51,6 +72,14 @@ WMFDecoderModule::Init() MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); sIsWMFEnabled = Preferences::GetBool("media.windows-media-foundation.enabled", false); sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding(); + SetNumOfDecoderThreads(); +} + +/* static */ +int +WMFDecoderModule::GetNumDecoderThreads() +{ + return sNumDecoderThreads; } nsresult diff --git a/dom/media/platforms/wmf/WMFDecoderModule.h b/dom/media/platforms/wmf/WMFDecoderModule.h index 5cbc5fa7d60b..3b713168f865 100644 --- a/dom/media/platforms/wmf/WMFDecoderModule.h +++ b/dom/media/platforms/wmf/WMFDecoderModule.h @@ -48,6 +48,9 @@ public: // Called on main thread. static void Init(); + + // Called from any thread, must call init first + static int GetNumDecoderThreads(); private: bool ShouldUseDXVA(const VideoInfo& aConfig) const; bool mWMFInitialized; diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index 828961f7a076..f031f9d5c99a 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -198,13 +198,15 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9) HRESULT hr = decoder->Create(GetMFTGUID()); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); - if (useDxva) { - RefPtr attr(decoder->GetAttributes()); - - UINT32 aware = 0; - if (attr) { + RefPtr attr(decoder->GetAttributes()); + UINT32 aware = 0; + if (attr) { attr->GetUINT32(MF_SA_D3D_AWARE, &aware); - } + attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads, + WMFDecoderModule::GetNumDecoderThreads()); + } + + if (useDxva) { if (aware) { // TODO: Test if I need this anywhere... Maybe on Vista? //hr = attr->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE); diff --git a/dom/security/moz.build b/dom/security/moz.build index 5b3118558303..b0c0f34aebe1 100644 --- a/dom/security/moz.build +++ b/dom/security/moz.build @@ -7,6 +7,7 @@ TEST_DIRS += ['test'] EXPORTS.mozilla.dom += [ + 'nsContentSecurityManager.h', 'nsCSPContext.h', 'nsCSPService.h', 'nsCSPUtils.h', @@ -14,10 +15,12 @@ EXPORTS.mozilla.dom += [ ] EXPORTS += [ + 'nsContentSecurityManager.h', 'nsCORSListenerProxy.h' ] UNIFIED_SOURCES += [ + 'nsContentSecurityManager.cpp', 'nsCORSListenerProxy.cpp', 'nsCSPContext.cpp', 'nsCSPParser.cpp', diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp new file mode 100644 index 000000000000..85dd05ce7140 --- /dev/null +++ b/dom/security/nsContentSecurityManager.cpp @@ -0,0 +1,263 @@ +#include "nsContentSecurityManager.h" +#include "nsIChannel.h" +#include "nsIStreamListener.h" +#include "nsILoadInfo.h" +#include "nsContentUtils.h" +#include "nsCORSListenerProxy.h" +#include "nsIStreamListener.h" + +#include "mozilla/dom/Element.h" + +nsresult +ValidateSecurityFlags(nsILoadInfo* aLoadInfo) +{ + nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode(); + + if (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS && + securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED && + securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS && + securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL && + securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { + MOZ_ASSERT(false, "need one securityflag from nsILoadInfo to perform security checks"); + return NS_ERROR_FAILURE; + } + + // make sure that cors-with-credentials is only used in combination with CORS. + if (aLoadInfo->GetRequireCorsWithCredentials() && + securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { + MOZ_ASSERT(false, "can not use cors-with-credentials without cors"); + return NS_ERROR_FAILURE; + } + // all good, found the right security flags + return NS_OK; +} + +nsresult +DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) +{ + nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode(); + + // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply + if ((securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) && + (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) { + return NS_OK; + } + + nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal(); + bool sameOriginDataInherits = + securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS; + return loadingPrincipal->CheckMayLoad(aURI, + true, // report to console + sameOriginDataInherits); +} + +nsresult +DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) +{ + nsresult rv = NS_OK; + nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode(); + // Please note that checkLoadURIWithPrincipal should only be enforced for + // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set + // within the loadInfo, then then CheckLoadURIWithPrincipal is performed + // within nsCorsListenerProxy + if ((securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) && + (securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) { + return NS_OK; + } + + nsCOMPtr loadingPrincipal = aLoadInfo->LoadingPrincipal(); + // XXX: @arg nsIScriptSecurityManager::STANDARD + // lets use STANDARD for now and evaluate on a callsite basis, see also: + // http://mxr.mozilla.org/mozilla-central/source/caps/nsIScriptSecurityManager.idl#62 + rv = nsContentUtils::GetSecurityManager()-> + CheckLoadURIWithPrincipal(loadingPrincipal, + aURI, + nsIScriptSecurityManager::STANDARD); + NS_ENSURE_SUCCESS(rv, rv); + + // If the loadingPrincipal and the triggeringPrincipal are different, then make + // sure the triggeringPrincipal is allowed to access that URI. + nsCOMPtr triggeringPrincipal = aLoadInfo->TriggeringPrincipal(); + if (loadingPrincipal != triggeringPrincipal) { + rv = nsContentUtils::GetSecurityManager()-> + CheckLoadURIWithPrincipal(triggeringPrincipal, + aURI, + nsIScriptSecurityManager::STANDARD); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +nsresult +DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo, + nsCOMPtr& aInAndOutListener) +{ + if (aLoadInfo->GetSecurityMode() != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) { + return NS_OK; + } + + nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal(); + nsRefPtr corsListener = + new nsCORSListenerProxy(aInAndOutListener, + loadingPrincipal, + aLoadInfo->GetRequireCorsWithCredentials()); + // XXX: @arg: DataURIHandling::Allow + // lets use DataURIHandling::Allow for now and then decide on callsite basis. see also: + // http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33 + nsresult rv = corsListener->Init(aChannel, DataURIHandling::Allow); + NS_ENSURE_SUCCESS(rv, rv); + aInAndOutListener = corsListener; + return NS_OK; +} + +nsresult +DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) +{ + nsContentPolicyType contentPolicyType = aLoadInfo->GetContentPolicyType(); + nsCString mimeTypeGuess; + nsCOMPtr requestingContext = nullptr; + + switch(contentPolicyType) { + case nsIContentPolicy::TYPE_OTHER: + case nsIContentPolicy::TYPE_SCRIPT: + case nsIContentPolicy::TYPE_IMAGE: + case nsIContentPolicy::TYPE_STYLESHEET: + case nsIContentPolicy::TYPE_OBJECT: + case nsIContentPolicy::TYPE_DOCUMENT: + case nsIContentPolicy::TYPE_SUBDOCUMENT: + case nsIContentPolicy::TYPE_REFRESH: + case nsIContentPolicy::TYPE_XBL: + case nsIContentPolicy::TYPE_PING: + case nsIContentPolicy::TYPE_XMLHTTPREQUEST: + // alias nsIContentPolicy::TYPE_DATAREQUEST: + case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: + case nsIContentPolicy::TYPE_DTD: + case nsIContentPolicy::TYPE_FONT: + MOZ_ASSERT(false, "contentPolicyType not supported yet"); + break; + + case nsIContentPolicy::TYPE_MEDIA: + mimeTypeGuess = EmptyCString(); + requestingContext = aLoadInfo->LoadingNode(); +#ifdef DEBUG + { + nsCOMPtr element = do_QueryInterface(requestingContext); + NS_ASSERTION(element != nullptr, + "type_media requires requestingContext of type Element"); + } +#endif + break; + + case nsIContentPolicy::TYPE_WEBSOCKET: + case nsIContentPolicy::TYPE_CSP_REPORT: + case nsIContentPolicy::TYPE_XSLT: + case nsIContentPolicy::TYPE_BEACON: + case nsIContentPolicy::TYPE_FETCH: + case nsIContentPolicy::TYPE_IMAGESET: + MOZ_ASSERT(false, "contentPolicyType not supported yet"); + break; + + default: + // nsIContentPolicy::TYPE_INVALID + MOZ_ASSERT(false, "can not perform security check without a valid contentType"); + } + + int16_t shouldLoad = nsIContentPolicy::ACCEPT; + nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, + aURI, + aLoadInfo->LoadingPrincipal(), + requestingContext, + mimeTypeGuess, + nullptr, //extra, + &shouldLoad, + nsContentUtils::GetContentPolicy(), + nsContentUtils::GetSecurityManager()); + NS_ENSURE_SUCCESS(rv, rv); + if (NS_CP_REJECTED(shouldLoad)) { + return NS_ERROR_CONTENT_BLOCKED; + } + return NS_OK; +} + +/* + * Based on the security flags provided in the loadInfo of the channel, + * doContentSecurityCheck() performs the following content security checks + * before opening the channel: + * + * (1) Same Origin Policy Check (if applicable) + * (2) Allow Cross Origin but perform sanity checks whether a principal + * is allowed to access the following URL. + * (3) Perform CORS check (if applicable) + * (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...) + * + * @param aChannel + * The channel to perform the security checks on. + * @param aInAndOutListener + * The streamListener that is passed to channel->AsyncOpen2() that is now potentially + * wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs + * to be set as new streamListener on the channel. + */ +nsresult +nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel, + nsCOMPtr& aInAndOutListener) +{ + NS_ENSURE_ARG(aChannel); + nsCOMPtr loadInfo = aChannel->GetLoadInfo(); + + if (!loadInfo) { + MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks"); + return NS_ERROR_UNEXPECTED; + } + + // make sure that only one of the five security flags is set in the loadinfo + // e.g. do not require same origin and allow cross origin at the same time + nsresult rv = ValidateSecurityFlags(loadInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // lets store the initialSecurityCheckDone flag which indicates whether the channel + // was initialy evaluated by the contentSecurityManager. Once the inital + // asyncOpen() of the channel went through the contentSecurityManager then + // redirects do not have perform all the security checks, e.g. no reason + // to setup CORS again. + bool initialSecurityCheckDone = loadInfo->GetInitialSecurityCheckDone(); + + // now lets set the initalSecurityFlag for subsequent calls + rv = loadInfo->SetInitialSecurityCheckDone(true); + NS_ENSURE_SUCCESS(rv, rv); + + // since aChannel was openend using asyncOpen2() we have to make sure + // that redirects of that channel also get openend using asyncOpen2() + // please note that some implementations of ::AsyncOpen2 might already + // have set that flag to true (e.g. nsViewSourceChannel) in which case + // we just set the flag again. + rv = loadInfo->SetEnforceSecurity(true); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr finalChannelURI; + rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI)); + NS_ENSURE_SUCCESS(rv, rv); + + // Perform Same Origin Policy check + rv = DoSOPChecks(finalChannelURI, loadInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // if dealing with a redirected channel then we only enforce SOP + // and can return at this point. + if (initialSecurityCheckDone) { + return NS_OK; + } + + rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // Check if CORS needs to be set up + rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener); + NS_ENSURE_SUCCESS(rv, rv); + + // Perform all ContentPolicy checks (MixedContent, CSP, ...) + rv = DoContentSecurityChecks(finalChannelURI, loadInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // all security checks passed - lets allow the load + return NS_OK; +} diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h new file mode 100644 index 000000000000..af1ede302b7d --- /dev/null +++ b/dom/security/nsContentSecurityManager.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsContentSecurityManager_h___ +#define nsContentSecurityManager_h___ + +#include "nsIChannel.h" +class nsIStreamListener; + +class nsContentSecurityManager +{ +private: + nsContentSecurityManager() {} + virtual ~nsContentSecurityManager() {} + +public: + static nsresult doContentSecurityCheck(nsIChannel* aChannel, + nsCOMPtr& aInAndOutListener); +}; + +#endif /* nsContentSecurityManager_h___ */ diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp index 021a27fcc1d9..772cf0bd48b2 100644 --- a/dom/workers/ServiceWorkerEvents.cpp +++ b/dom/workers/ServiceWorkerEvents.cpp @@ -435,8 +435,15 @@ PushMessageData::~PushMessageData() { } -NS_IMPL_ISUPPORTS0(PushMessageData); +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(PushMessageData); +NS_IMPL_CYCLE_COLLECTING_ADDREF(PushMessageData) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PushMessageData) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushMessageData) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END void PushMessageData::Json(JSContext* cx, JS::MutableHandle aRetval) diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h index 87a856ae1dd3..e5f5dc9db1d2 100644 --- a/dom/workers/ServiceWorkerEvents.h +++ b/dom/workers/ServiceWorkerEvents.h @@ -163,7 +163,8 @@ class PushMessageData final : public nsISupports, nsString mData; public: - NS_DECL_ISUPPORTS + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushMessageData) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override { diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index 7fa9967c5571..4a8fc7c791f6 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -340,7 +340,7 @@ public: }; WorkerCrossThreadDispatcher* -GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker); +GetWorkerCrossThreadDispatcher(JSContext* aCx, JS::Value aWorker); // Random unique constant to facilitate JSPrincipal debugging const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2; diff --git a/dom/workers/test/serviceworkers/fetch/context/context_test.js b/dom/workers/test/serviceworkers/fetch/context/context_test.js index 66d22b7da5b3..b98d2ab3ca73 100644 --- a/dom/workers/test/serviceworkers/fetch/context/context_test.js +++ b/dom/workers/test/serviceworkers/fetch/context/context_test.js @@ -46,8 +46,7 @@ self.addEventListener("fetch", function(event) { event.respondWith(fetch("context_test.js")); } } else if (event.request.url.indexOf("frame") >= 0) { - // FIXME: Bug 1148044: This should be "frame". - if (event.request.context == "iframe") { + if (event.request.context == "frame") { event.respondWith(fetch("context_test.js")); } } else if (event.request.url.indexOf("newwindow") >= 0) { diff --git a/dom/workers/test/serviceworkers/fetch/context/index.html b/dom/workers/test/serviceworkers/fetch/context/index.html index 218ead144bc7..c6dfef99c8da 100644 --- a/dom/workers/test/serviceworkers/fetch/context/index.html +++ b/dom/workers/test/serviceworkers/fetch/context/index.html @@ -128,8 +128,7 @@ document.documentElement.appendChild(embed); navigator.serviceWorker.addEventListener("message", function onMessage(e) { if (e.data.data == "embed") { - // FIXME: Bug 1148030: This should be "embed". - is(e.data.context, "object", "Expected the object context on an embed"); + is(e.data.context, "embed", "Expected the object context on an embed"); navigator.serviceWorker.removeEventListener("message", onMessage); resolve(); } diff --git a/embedding/components/windowwatcher/nsWindowWatcher.cpp b/embedding/components/windowwatcher/nsWindowWatcher.cpp index 6dd50b2c73e4..0f96f1ae4ae8 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -562,7 +562,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, // security checks. chromeFlags = CalculateChromeFlags(aParent, features.get(), featuresSpecified, aDialog, uriToLoadIsChrome, - hasChromeParent, openedFromRemoteTab); + hasChromeParent, aCalledFromJS, + openedFromRemoteTab); // If we are opening a window from a remote browser, the resulting window // should also be remote. @@ -1466,8 +1467,8 @@ nsWindowWatcher::URIfromURL(const char* aURL, #define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \ prefBranch->GetBoolPref(feature, &forceEnable); \ - if (forceEnable && !(aDialog && isCallerChrome) && \ - !(isCallerChrome && aHasChromeParent) && !aChromeURL) { \ + if (forceEnable && !(aDialog && !openedFromContentScript) && \ + !(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \ chromeFlags |= flag; \ } else { \ chromeFlags |= \ @@ -1491,26 +1492,30 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, bool aDialog, bool aChromeURL, bool aHasChromeParent, + bool aCalledFromJS, bool aOpenedFromRemoteTab) { + const bool inContentProcess = XRE_IsContentProcess(); uint32_t chromeFlags = 0; - bool isCallerChrome = - nsContentUtils::IsCallerChrome() && !aOpenedFromRemoteTab; - bool onlyPrivateFlag = aFeaturesSpecified && aFeatures && isCallerChrome && - nsCRT::strcasecmp(aFeatures, "private") == 0; - if (!aFeaturesSpecified || !aFeatures || onlyPrivateFlag) { + if (!aFeaturesSpecified || !aFeatures) { chromeFlags = nsIWebBrowserChrome::CHROME_ALL; if (aDialog) { chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | nsIWebBrowserChrome::CHROME_OPENAS_CHROME; } - if (onlyPrivateFlag) { - chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW; + + if (inContentProcess) { + return chromeFlags; } - return chromeFlags; + } else { + chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS; } + bool openedFromContentScript = + aOpenedFromRemoteTab ? aCalledFromJS + : !nsContentUtils::IsCallerChrome(); + /* This function has become complicated since browser windows and dialogs diverged. The difference is, browser windows assume all chrome not explicitly mentioned is off, if the features string @@ -1520,30 +1525,32 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, in the standards-compliant window.(normal)open. */ bool presenceFlag = false; - - chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS; if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) { chromeFlags = nsIWebBrowserChrome::CHROME_ALL; } /* Next, allow explicitly named options to override the initial settings */ - // Determine whether the window is a private browsing window - if (isCallerChrome) { + if (!inContentProcess && !openedFromContentScript) { + // Determine whether the window is a private browsing window chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ? nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0; chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ? nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0; } - // Determine whether the window should have remote tabs. - if (isCallerChrome || aOpenedFromRemoteTab) { - bool remote; - if (BrowserTabsRemoteAutostart()) { - remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag); - } else { - remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag); + if (!inContentProcess) { + // Determine whether the window should have remote tabs. + bool remote = BrowserTabsRemoteAutostart(); + + if (!openedFromContentScript) { + if (remote) { + remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag); + } else { + remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag); + } } + if (remote) { chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW; } @@ -1644,7 +1651,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, if (aParent) { aParent->GetFullScreen(&isFullScreen); } - if (isFullScreen && !isCallerChrome) { + if (isFullScreen && openedFromContentScript) { // If the parent window is in fullscreen & the caller context is content, // dialog feature is disabled. (see bug 803675) disableDialogFeature = true; @@ -1671,7 +1678,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, */ // Check security state for use in determing window dimensions - if (!isCallerChrome || !aHasChromeParent) { + if (openedFromContentScript || !aHasChromeParent) { // If priv check fails (or if we're called from chrome, but the // parent is not a chrome window), set all elements to minimum // reqs., else leave them alone. @@ -2270,12 +2277,19 @@ nsWindowWatcher::GetWindowOpenLocation(nsIDOMWindow* aParent, return nsIBrowserDOMWindow::OPEN_NEWWINDOW; } - if (restrictionPref == 2 && - // Only continue if there are no size/position features and no special - // chrome flags. - (aChromeFlags != nsIWebBrowserChrome::CHROME_ALL || - aPositionSpecified || aSizeSpecified)) { - return nsIBrowserDOMWindow::OPEN_NEWWINDOW; + if (restrictionPref == 2) { + // Only continue if there are no size/position features and no special + // chrome flags - with the exception of the remoteness and private flags, + // which might have been automatically flipped by Gecko. + int32_t uiChromeFlags = aChromeFlags; + uiChromeFlags &= ~(nsIWebBrowserChrome::CHROME_REMOTE_WINDOW | + nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW | + nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW | + nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME); + if (uiChromeFlags != nsIWebBrowserChrome::CHROME_ALL || + aPositionSpecified || aSizeSpecified) { + return nsIBrowserDOMWindow::OPEN_NEWWINDOW; + } } } diff --git a/embedding/components/windowwatcher/nsWindowWatcher.h b/embedding/components/windowwatcher/nsWindowWatcher.h index 04a025058371..a71bfab805fb 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.h +++ b/embedding/components/windowwatcher/nsWindowWatcher.h @@ -96,6 +96,7 @@ protected: bool aDialog, bool aChromeURL, bool aHasChromeParent, + bool aCalledFromJS, bool aOpenedFromRemoteTab); static int32_t WinHasOption(const char* aOptions, const char* aName, int32_t aDefault, bool* aPresenceFlag); diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 3023a9b9deba..5a901c965ca3 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -340,92 +340,95 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp // to guess what ports and protocols we want to add permissions for. // We find every URI which they have visited with this host (or a subdomain of this host), // and try to add it as a principal. + bool foundHistory = false; + nsCOMPtr histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); - nsCOMPtr histQuery; - rv = histSrv->GetNewQuery(getter_AddRefs(histQuery)); - NS_ENSURE_SUCCESS(rv, rv); + if (histSrv) { + nsCOMPtr histQuery; + rv = histSrv->GetNewQuery(getter_AddRefs(histQuery)); + NS_ENSURE_SUCCESS(rv, rv); - // We want to only find history items for this particular host, and subdomains - rv = histQuery->SetDomain(aHost); - NS_ENSURE_SUCCESS(rv, rv); + // We want to only find history items for this particular host, and subdomains + rv = histQuery->SetDomain(aHost); + NS_ENSURE_SUCCESS(rv, rv); - rv = histQuery->SetDomainIsHost(false); - NS_ENSURE_SUCCESS(rv, rv); + rv = histQuery->SetDomainIsHost(false); + NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr histQueryOpts; - rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr histQueryOpts; + rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts)); + NS_ENSURE_SUCCESS(rv, rv); - // We want to get the URIs for every item in the user's history with the given host - rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI); - NS_ENSURE_SUCCESS(rv, rv); + // We want to get the URIs for every item in the user's history with the given host + rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI); + NS_ENSURE_SUCCESS(rv, rv); - // We only search history, because searching both bookmarks and history - // is not supported, and history tends to be more comprehensive. - rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY); - NS_ENSURE_SUCCESS(rv, rv); + // We only search history, because searching both bookmarks and history + // is not supported, and history tends to be more comprehensive. + rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY); + NS_ENSURE_SUCCESS(rv, rv); - // We include hidden URIs (such as those visited via iFrames) as they may have permissions too - rv = histQueryOpts->SetIncludeHidden(true); - NS_ENSURE_SUCCESS(rv, rv); + // We include hidden URIs (such as those visited via iFrames) as they may have permissions too + rv = histQueryOpts->SetIncludeHidden(true); + NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr histResult; - rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr histResult; + rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult)); + NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr histResultContainer; - rv = histResult->GetRoot(getter_AddRefs(histResultContainer)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr histResultContainer; + rv = histResult->GetRoot(getter_AddRefs(histResultContainer)); + NS_ENSURE_SUCCESS(rv, rv); - rv = histResultContainer->SetContainerOpen(true); - NS_ENSURE_SUCCESS(rv, rv); + rv = histResultContainer->SetContainerOpen(true); + NS_ENSURE_SUCCESS(rv, rv); - uint32_t childCount = 0; - rv = histResultContainer->GetChildCount(&childCount); - NS_ENSURE_SUCCESS(rv, rv); + uint32_t childCount = 0; + rv = histResultContainer->GetChildCount(&childCount); + NS_ENSURE_SUCCESS(rv, rv); - bool foundHistory = false; - for (uint32_t i = 0; i < childCount; i++) { - nsCOMPtr child; - histResultContainer->GetChild(i, getter_AddRefs(child)); - if (NS_FAILED(rv)) continue; + for (uint32_t i = 0; i < childCount; i++) { + nsCOMPtr child; + histResultContainer->GetChild(i, getter_AddRefs(child)); + if (NS_FAILED(rv)) continue; - uint32_t type; - rv = child->GetType(&type); - if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) { - NS_WARNING("Unexpected non-RESULT_TYPE_URI node in " - "UpgradeHostToOriginAndInsert()"); - continue; + uint32_t type; + rv = child->GetType(&type); + if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) { + NS_WARNING("Unexpected non-RESULT_TYPE_URI node in " + "UpgradeHostToOriginAndInsert()"); + continue; + } + + nsAutoCString uriSpec; + rv = child->GetUri(uriSpec); + if (NS_FAILED(rv)) continue; + + nsCOMPtr uri; + rv = NS_NewURI(getter_AddRefs(uri), uriSpec); + if (NS_FAILED(rv)) continue; + + // Use the provided host - this URI may be for a subdomain, rather than the host we care about. + rv = uri->SetHost(aHost); + if (NS_FAILED(rv)) continue; + + // We now have a URI which we can make a nsIPrincipal out of + nsCOMPtr principal; + rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); + if (NS_FAILED(rv)) continue; + + // Insert it! (The backend should be able to deal with us inserting the same origin repeatedly) + foundHistory = true; + rv = aHelper->Insert(principal, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); + NS_WARN_IF(NS_FAILED(rv)); } - nsAutoCString uriSpec; - rv = child->GetUri(uriSpec); - if (NS_FAILED(rv)) continue; - - nsCOMPtr uri; - rv = NS_NewURI(getter_AddRefs(uri), uriSpec); - if (NS_FAILED(rv)) continue; - - // Use the provided host - this URI may be for a subdomain, rather than the host we care about. - rv = uri->SetHost(aHost); - if (NS_FAILED(rv)) continue; - - // We now have a URI which we can make a nsIPrincipal out of - nsCOMPtr principal; - rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); - if (NS_FAILED(rv)) continue; - - // Insert it! (The backend should be able to deal with us inserting the same origin repeatedly) - foundHistory = true; - rv = aHelper->Insert(principal, aType, aPermission, - aExpireType, aExpireTime, aModificationTime); - NS_WARN_IF(NS_FAILED(rv)); + rv = histResultContainer->SetContainerOpen(false); + NS_ENSURE_SUCCESS(rv, rv); } - rv = histResultContainer->SetContainerOpen(false); - NS_ENSURE_SUCCESS(rv, rv); - // If we didn't find any origins for this host in the poermissions database, // we can insert the default http:// and https:// permissions into the database. // This has a relatively high liklihood of applying the permission to the correct diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index 0cb819a82f73..f0fe552f6e99 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -44,6 +44,12 @@ #define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA 0x8C93 #define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA 0x87EE +// EGL_ANDROID_image_crop +#define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID 0x3148 +#define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID 0x3149 +#define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID 0x314A +#define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B + // Others #define LOCAL_EGL_PRESERVED_RESOURCES 0x3030 #define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp index 3affc6cb923d..761c698650ce 100644 --- a/gfx/gl/GLLibraryEGL.cpp +++ b/gfx/gl/GLLibraryEGL.cpp @@ -36,6 +36,7 @@ static const char *sEGLExtensionNames[] = { "EGL_KHR_image", "EGL_KHR_fence_sync", "EGL_ANDROID_native_fence_sync", + "EGL_ANDROID_image_crop", "ANGLE_platform_angle", "ANGLE_platform_angle_d3d" }; diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h index 135289de2a85..58459f07df03 100644 --- a/gfx/gl/GLLibraryEGL.h +++ b/gfx/gl/GLLibraryEGL.h @@ -131,6 +131,7 @@ public: KHR_image, KHR_fence_sync, ANDROID_native_fence_sync, + EGL_ANDROID_image_crop, ANGLE_platform_angle, ANGLE_platform_angle_d3d, Extensions_Max diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index cc2b93699d7a..2979bc5858cf 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -95,6 +95,9 @@ ImageHost::UseTextureHost(const nsTArray& aTextures) img.mTextureSource = mImages.LastElement().mTextureSource; mImages.RemoveElementAt(mImages.Length() - 1); } + // SetCropRect() affects only on a specific platform. + // If it is not implemented, it does nothing. + img.mFrontBuffer->SetCropRect(img.mPictureRect); img.mFrontBuffer->Updated(); img.mFrontBuffer->PrepareTextureSource(img.mTextureSource); } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 94532bf298d5..f03368d4081e 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -417,6 +417,11 @@ public: virtual gfx::IntSize GetSize() const = 0; + /** + * Should be overridden if TextureHost supports crop rect. + */ + virtual void SetCropRect(nsIntRect aCropRect) {} + /** * Debug facility. * XXX - cool kids use Moz2D. See bug 882113. diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 5d6ecaee4be3..03f305c86729 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -84,12 +84,6 @@ struct EGLImageDescriptor { struct NewSurfaceDescriptorGralloc { MaybeMagicGrallocBufferHandle buffer; - /** - * android::GraphicBuffer has a size information. But there are cases - * that GraphicBuffer's size and actual video's size are different. - * Extra size member is necessary. See Bug 850566. - */ - IntSize size; bool isOpaque; }; diff --git a/gfx/layers/opengl/EGLImageHelpers.cpp b/gfx/layers/opengl/EGLImageHelpers.cpp index 6b9a6b6ca553..4a720302f03e 100644 --- a/gfx/layers/opengl/EGLImageHelpers.cpp +++ b/gfx/layers/opengl/EGLImageHelpers.cpp @@ -15,17 +15,32 @@ namespace layers { using namespace gl; EGLImage -EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer) +EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize) { EGLint attrs[] = { LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE, - LOCAL_EGL_NONE, LOCAL_EGL_NONE + LOCAL_EGL_NONE, LOCAL_EGL_NONE, }; + EGLint cropAttrs[] = { + LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE, + LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID, 0, + LOCAL_EGL_IMAGE_CROP_TOP_ANDROID, 0, + LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID, aCropSize.width, + LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID, aCropSize.height, + LOCAL_EGL_NONE, LOCAL_EGL_NONE, + }; + + bool hasCropRect = (aCropSize.width != 0 && aCropSize.height != 0); + EGLint* usedAttrs = attrs; + if (hasCropRect && sEGLLibrary.IsExtensionSupported(GLLibraryEGL::EGL_ANDROID_image_crop)) { + usedAttrs = cropAttrs; + } + return sEGLLibrary.fCreateImage(sEGLLibrary.Display(), EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, - aBuffer, attrs); + aBuffer, usedAttrs); } void diff --git a/gfx/layers/opengl/EGLImageHelpers.h b/gfx/layers/opengl/EGLImageHelpers.h index ba38dfdd1451..3e03a499ca56 100644 --- a/gfx/layers/opengl/EGLImageHelpers.h +++ b/gfx/layers/opengl/EGLImageHelpers.h @@ -7,6 +7,8 @@ #ifndef EGLIMAGEHELPERS_H_ #define EGLIMAGEHELPERS_H_ +#include "mozilla/gfx/Point.h" + typedef void* EGLImage; namespace mozilla { @@ -16,7 +18,7 @@ namespace gl { namespace layers { -EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer); +EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize); void EGLImageDestroy(gl::GLContext* aGL, EGLImage aImage); } // namespace layers diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index 4caf58e49917..ca485f6f8c17 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -71,7 +71,7 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) return false; } - aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mSize, mIsOpaque); + aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mIsOpaque); return true; } diff --git a/gfx/layers/opengl/GrallocTextureClient.h b/gfx/layers/opengl/GrallocTextureClient.h index 71d4defd400c..0276b610c03a 100644 --- a/gfx/layers/opengl/GrallocTextureClient.h +++ b/gfx/layers/opengl/GrallocTextureClient.h @@ -139,13 +139,6 @@ protected: RefPtr mDrawTarget; - /** - * android::GraphicBuffer has a size information. But there are cases - * that GraphicBuffer's size and actual video's size are different. - * Extra size member is necessary. See Bug 850566. - */ - gfx::IntSize mSize; - android::MediaBuffer* mMediaBuffer; bool mIsOpaque; diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index 6caad935d8da..1a9f52a69d58 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -103,7 +103,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags, : TextureHost(aFlags) , mGrallocHandle(aDescriptor) , mSize(0, 0) - , mDescriptorSize(aDescriptor.size()) + , mCropSize(0, 0) , mFormat(gfx::SurfaceFormat::UNKNOWN) , mEGLImage(EGL_NO_IMAGE) , mIsOpaque(aDescriptor.isOpaque()) @@ -116,6 +116,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags, SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(), aFlags & TextureFlags::RB_SWAPPED); mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight()); + mCropSize = mSize; } else { printf_stderr("gralloc buffer is nullptr"); } @@ -222,7 +223,7 @@ GrallocTextureHostOGL::GetRenderState() flags |= LayerRenderStateFlags::FORMAT_RB_SWAP; } return LayerRenderState(graphicBuffer, - mDescriptorSize, + mCropSize, flags, this); } @@ -344,8 +345,12 @@ GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextu } if (mEGLImage == EGL_NO_IMAGE) { + gfx::IntSize cropSize(0, 0); + if (mCropSize != mSize) { + cropSize = mCropSize; + } // Should only happen the first time. - mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer()); + mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer(), cropSize); } GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat()); @@ -414,6 +419,23 @@ GrallocTextureHostOGL::WaitAcquireFenceHandleSyncComplete() MOZ_ALWAYS_TRUE( sEGLLibrary.fDestroySync(EGL_DISPLAY(), sync) ); } +void +GrallocTextureHostOGL::SetCropRect(nsIntRect aCropRect) +{ + MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0)); + MOZ_ASSERT(!aCropRect.IsEmpty()); + MOZ_ASSERT(aCropRect.width <= mSize.width); + MOZ_ASSERT(aCropRect.height <= mSize.height); + + gfx::IntSize cropSize(aCropRect.width, aCropRect.height); + if (mCropSize == cropSize) { + return; + } + + mCropSize = cropSize; + mGLTextureSource = nullptr; +} + bool GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource) { diff --git a/gfx/layers/opengl/GrallocTextureHost.h b/gfx/layers/opengl/GrallocTextureHost.h index 0e9d1062edda..a258a1e427f2 100644 --- a/gfx/layers/opengl/GrallocTextureHost.h +++ b/gfx/layers/opengl/GrallocTextureHost.h @@ -38,7 +38,7 @@ public: virtual gfx::SurfaceFormat GetFormat() const; - virtual gfx::IntSize GetSize() const override { return mDescriptorSize; } + virtual gfx::IntSize GetSize() const override { return mCropSize; } virtual LayerRenderState GetRenderState() override; @@ -52,6 +52,8 @@ public: virtual void WaitAcquireFenceHandleSyncComplete() override; + virtual void SetCropRect(nsIntRect aCropRect) override; + bool IsValid() const; virtual const char* Name() override { return "GrallocTextureHostOGL"; } @@ -68,7 +70,7 @@ private: gfx::IntSize mSize; // Size reported by TextureClient, can be different in some cases (video?), // used by LayerRenderState. - gfx::IntSize mDescriptorSize; + gfx::IntSize mCropSize; gfx::SurfaceFormat mFormat; EGLImage mEGLImage; bool mIsOpaque; diff --git a/image/FrameAnimator.cpp b/image/FrameAnimator.cpp index 6cfb100013aa..942c6a142d6f 100644 --- a/image/FrameAnimator.cpp +++ b/image/FrameAnimator.cpp @@ -273,8 +273,7 @@ FrameAnimator::GetCompositedFrame(uint32_t aFrameNum) // If we have a composited version of this frame, return that. if (mLastCompositedFrameIndex == int32_t(aFrameNum)) { - return LookupResult(mCompositingFrame->DrawableRef(), - /* aIsExactMatch = */ true); + return LookupResult(mCompositingFrame->DrawableRef(), MatchType::EXACT); } // Otherwise return the raw frame. DoBlend is required to ensure that we only diff --git a/image/LookupResult.h b/image/LookupResult.h index 91fb2b4033ae..67aebf576fe9 100644 --- a/image/LookupResult.h +++ b/image/LookupResult.h @@ -18,6 +18,16 @@ namespace mozilla { namespace image { +enum class MatchType : uint8_t +{ + NOT_FOUND, // No matching surface and no placeholder. + PENDING, // Found a matching placeholder, but no surface. + EXACT, // Found a surface that matches exactly. + SUBSTITUTE_BECAUSE_NOT_FOUND, // No exact match, but found a similar one. + SUBSTITUTE_BECAUSE_PENDING // Found a similar surface and a placeholder + // for an exact match. +}; + /** * LookupResult is the return type of SurfaceCache's Lookup*() functions. It * combines a surface with relevant metadata tracked by SurfaceCache. @@ -25,25 +35,36 @@ namespace image { class MOZ_STACK_CLASS LookupResult { public: - LookupResult() - : mIsExactMatch(false) - { } + explicit LookupResult(MatchType aMatchType) + : mMatchType(aMatchType) + { + MOZ_ASSERT(mMatchType == MatchType::NOT_FOUND || + mMatchType == MatchType::PENDING, + "Only NOT_FOUND or PENDING make sense with no surface"); + } LookupResult(LookupResult&& aOther) : mDrawableRef(Move(aOther.mDrawableRef)) - , mIsExactMatch(aOther.mIsExactMatch) + , mMatchType(aOther.mMatchType) { } - LookupResult(DrawableFrameRef&& aDrawableRef, bool aIsExactMatch) + LookupResult(DrawableFrameRef&& aDrawableRef, MatchType aMatchType) : mDrawableRef(Move(aDrawableRef)) - , mIsExactMatch(aIsExactMatch) - { } + , mMatchType(aMatchType) + { + MOZ_ASSERT(!mDrawableRef || !(mMatchType == MatchType::NOT_FOUND || + mMatchType == MatchType::PENDING), + "Only NOT_FOUND or PENDING make sense with no surface"); + MOZ_ASSERT(mDrawableRef || mMatchType == MatchType::NOT_FOUND || + mMatchType == MatchType::PENDING, + "NOT_FOUND or PENDING do not make sense with a surface"); + } LookupResult& operator=(LookupResult&& aOther) { MOZ_ASSERT(&aOther != this, "Self-move-assignment is not supported"); mDrawableRef = Move(aOther.mDrawableRef); - mIsExactMatch = aOther.mIsExactMatch; + mMatchType = aOther.mMatchType; return *this; } @@ -53,14 +74,14 @@ public: /// @return true if this LookupResult contains a surface. explicit operator bool() const { return bool(mDrawableRef); } - /// @return true if the surface is an exact match for the Lookup*() arguments. - bool IsExactMatch() const { return mIsExactMatch; } + /// @return what kind of match this is (exact, substitute, etc.) + MatchType Type() const { return mMatchType; } private: LookupResult(const LookupResult&) = delete; DrawableFrameRef mDrawableRef; - bool mIsExactMatch; + MatchType mMatchType; }; } // namespace image diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 01b238a8a866..802a32f8c9a4 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -526,8 +526,12 @@ RasterImage::LookupFrame(uint32_t aFrameNum, return DrawableFrameRef(); } - if (!result || !result.IsExactMatch()) { - // The OS threw this frame away. We need to redecode if we can. + if (result.Type() == MatchType::NOT_FOUND || + result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND || + ((aFlags & FLAG_SYNC_DECODE) && !result)) { + // We don't have a copy of this frame, and there's no decoder working on + // one. (Or we're sync decoding and the existing decoder hasn't even started + // yet.) Trigger decoding so it'll be available next time. MOZ_ASSERT(!mAnim, "Animated frames should be locked"); Decode(Some(requestedSize), aFlags); @@ -1499,6 +1503,19 @@ RasterImage::CreateDecoder(const Maybe& aSize, uint32_t aFlags) return nullptr; } + if (aSize) { + // Add a placeholder for the first frame to the SurfaceCache so we won't + // trigger any more decoders with the same parameters. + InsertOutcome outcome = + SurfaceCache::InsertPlaceholder(ImageKey(this), + RasterSurfaceKey(*aSize, + decoder->GetDecodeFlags(), + /* aFrameNum = */ 0)); + if (outcome != InsertOutcome::SUCCESS) { + return nullptr; + } + } + if (!aSize) { Telemetry::GetHistogramById( Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount); diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp index c6c6c2b9827c..d791b1f776b0 100644 --- a/image/SurfaceCache.cpp +++ b/image/SurfaceCache.cpp @@ -16,6 +16,7 @@ #include "mozilla/Likely.h" #include "mozilla/Move.h" #include "mozilla/Mutex.h" +#include "mozilla/Pair.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" #include "nsIMemoryReporter.h" @@ -67,6 +68,10 @@ static StaticRefPtr sInstance; */ typedef size_t Cost; +// Placeholders do not have surfaces, but need to be given a trivial cost for +// our invariants to hold. +static const Cost sPlaceholderCost = 1; + static Cost ComputeCost(const IntSize& aSize, uint32_t aBytesPerPixel) { @@ -137,17 +142,28 @@ public: , mSurfaceKey(aSurfaceKey) , mLifetime(aLifetime) { - MOZ_ASSERT(mSurface, "Must have a valid surface"); + MOZ_ASSERT(!IsPlaceholder() || + (mCost == sPlaceholderCost && mLifetime == Lifetime::Transient), + "Placeholder should have trivial cost and transient lifetime"); MOZ_ASSERT(mImageKey, "Must have a valid image key"); } DrawableFrameRef DrawableRef() const { + if (MOZ_UNLIKELY(IsPlaceholder())) { + MOZ_ASSERT_UNREACHABLE("Shouldn't call DrawableRef() on a placeholder"); + return DrawableFrameRef(); + } + return mSurface->DrawableRef(); } void SetLocked(bool aLocked) { + if (IsPlaceholder()) { + return; // Can't lock a placeholder. + } + if (aLocked && mLifetime == Lifetime::Persistent) { // This may fail, and that's OK. We make no guarantees about whether // locking is successful if you call SurfaceCache::LockImage() after @@ -158,6 +174,7 @@ public: } } + bool IsPlaceholder() const { return !bool(mSurface); } bool IsLocked() const { return bool(mDrawableRef); } ImageKey GetImageKey() const { return mImageKey; } @@ -165,7 +182,11 @@ public: CostEntry GetCostEntry() { return image::CostEntry(this, mCost); } nsExpirationState* GetExpirationState() { return &mExpirationState; } Lifetime GetLifetime() const { return mLifetime; } - bool IsDecoded() const { return mSurface->IsImageComplete(); } + + bool IsDecoded() const + { + return !IsPlaceholder() && mSurface->IsImageComplete(); + } // A helper type used by SurfaceCacheImpl::CollectSizeOfSurfaces. struct MOZ_STACK_CLASS SurfaceMemoryReport @@ -262,21 +283,47 @@ public: return surface.forget(); } - already_AddRefed + MOZ_WARN_UNUSED_RESULT // See bug 1185044. + Pair, MatchType> LookupBestMatch(const SurfaceKey& aSurfaceKey, const Maybe& aAlternateFlags) { - // Try for a perfect match first. - nsRefPtr surface; - mSurfaces.Get(aSurfaceKey, getter_AddRefs(surface)); - if (surface && surface->IsDecoded()) { - return surface.forget(); + // Try for an exact match first. + nsRefPtr exactMatch; + mSurfaces.Get(aSurfaceKey, getter_AddRefs(exactMatch)); + if (exactMatch && exactMatch->IsDecoded()) { + return MakePair(exactMatch.forget(), MatchType::EXACT); } // There's no perfect match, so find the best match we can. MatchContext matchContext(aSurfaceKey, aAlternateFlags); ForEach(TryToImproveMatch, &matchContext); - return matchContext.mBestMatch.forget(); + + MatchType matchType; + if (matchContext.mBestMatch) { + if (!exactMatch) { + // No exact match, but we found a substitute. + matchType = MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND; + } else if (exactMatch != matchContext.mBestMatch) { + // The exact match is still decoding, but we found a substitute. + matchType = MatchType::SUBSTITUTE_BECAUSE_PENDING; + } else { + // The exact match is still decoding, but it's the best we've got. + matchType = MatchType::EXACT; + } + } else { + if (exactMatch) { + // We found an "exact match", but since TryToImproveMatch didn't return + // it, it must have been a placeholder. + MOZ_ASSERT(exactMatch->IsPlaceholder()); + matchType = MatchType::PENDING; + } else { + // We couldn't find an exact match *or* a substitute. + matchType = MatchType::NOT_FOUND; + } + } + + return MakePair(matchContext.mBestMatch.forget(), matchType); } void ForEach(SurfaceTable::EnumReadFunction aFunction, void* aData) @@ -308,6 +355,11 @@ private: auto context = static_cast(aContext); const SurfaceKey& idealKey = context->mIdealKey; + // We never match a placeholder. + if (aSurface->IsPlaceholder()) { + return PL_DHASH_NEXT; + } + // Matching the animation time and SVG context is required. if (aSurfaceKey.AnimationTime() != idealKey.AnimationTime() || aSurfaceKey.SVGContext() != idealKey.SVGContext()) { @@ -425,10 +477,21 @@ public: Lifetime aLifetime) { // If this is a duplicate surface, refuse to replace the original. - if (MOZ_UNLIKELY(Lookup(aImageKey, aSurfaceKey, /* aMarkUsed = */ false))) { + // XXX(seth): Calling Lookup() and then RemoveSurface() does the lookup + // twice. We'll make this more efficient in bug 1185137. + LookupResult result = Lookup(aImageKey, aSurfaceKey, /* aMarkUsed = */ false); + if (MOZ_UNLIKELY(result)) { return InsertOutcome::FAILURE_ALREADY_PRESENT; } + if (result.Type() == MatchType::PENDING) { + RemoveSurface(aImageKey, aSurfaceKey); + } + + MOZ_ASSERT(result.Type() == MatchType::NOT_FOUND || + result.Type() == MatchType::PENDING, + "A LookupResult with no surface should be NOT_FOUND or PENDING"); + // If this is bigger than we can hold after discarding everything we can, // refuse to cache it. if (MOZ_UNLIKELY(!CanHoldAfterDiscarding(aCost))) { @@ -458,6 +521,7 @@ public: // We require that locking succeed if the image is locked and the surface is // persistent; the caller may need to know this to handle errors correctly. if (cache->IsLocked() && aLifetime == Lifetime::Persistent) { + MOZ_ASSERT(!surface->IsPlaceholder(), "Placeholders should be transient"); surface->SetLocked(true); if (!surface->IsLocked()) { return InsertOutcome::FAILURE; @@ -550,12 +614,18 @@ public: { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) { - return LookupResult(); // No cached surfaces for this image. + // No cached surfaces for this image. + return LookupResult(MatchType::NOT_FOUND); } nsRefPtr surface = cache->Lookup(aSurfaceKey); if (!surface) { - return LookupResult(); // Lookup in the per-image cache missed. + // Lookup in the per-image cache missed. + return LookupResult(MatchType::NOT_FOUND); + } + + if (surface->IsPlaceholder()) { + return LookupResult(MatchType::PENDING); } DrawableFrameRef ref = surface->DrawableRef(); @@ -563,14 +633,16 @@ public: // The surface was released by the operating system. Remove the cache // entry as well. Remove(surface); - return LookupResult(); + return LookupResult(MatchType::NOT_FOUND); } if (aMarkUsed) { MarkUsed(surface, cache); } - return LookupResult(Move(ref), /* aIsExactMatch = */ true); + MOZ_ASSERT(surface->GetSurfaceKey() == aSurfaceKey, + "Lookup() not returning an exact match?"); + return LookupResult(Move(ref), MatchType::EXACT); } LookupResult LookupBestMatch(const ImageKey aImageKey, @@ -579,7 +651,8 @@ public: { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) { - return LookupResult(); // No cached surfaces for this image. + // No cached surfaces for this image. + return LookupResult(MatchType::NOT_FOUND); } // Repeatedly look up the best match, trying again if the resulting surface @@ -590,10 +663,16 @@ public: nsRefPtr surface; DrawableFrameRef ref; + MatchType matchType = MatchType::NOT_FOUND; while (true) { - surface = cache->LookupBestMatch(aSurfaceKey, aAlternateFlags); + // XXX(seth): This code is begging for std::tie. See bug 1184385. + Pair, MatchType> lookupResult = + cache->LookupBestMatch(aSurfaceKey, aAlternateFlags); + surface = lookupResult.first(); + matchType = lookupResult.second(); + if (!surface) { - return LookupResult(); // Lookup in the per-image cache missed. + return LookupResult(matchType); // Lookup in the per-image cache missed. } ref = surface->DrawableRef(); @@ -606,20 +685,18 @@ public: Remove(surface); } - SurfaceKey key = surface->GetSurfaceKey(); - const bool isExactMatch = key.Size() == aSurfaceKey.Size(); - - MOZ_ASSERT(isExactMatch == - (key == aSurfaceKey || - (aAlternateFlags && key == aSurfaceKey.WithNewFlags(*aAlternateFlags))), + MOZ_ASSERT((matchType == MatchType::EXACT) == + (surface->GetSurfaceKey() == aSurfaceKey || + (aAlternateFlags && + surface->GetSurfaceKey() == + aSurfaceKey.WithNewFlags(*aAlternateFlags))), "Result differs in a way other than size or alternate flags"); - - if (isExactMatch) { + if (matchType == MatchType::EXACT) { MarkUsed(surface, cache); } - return LookupResult(Move(ref), isExactMatch); + return LookupResult(Move(ref), matchType); } void RemoveSurface(const ImageKey aImageKey, @@ -992,7 +1069,7 @@ SurfaceCache::Lookup(const ImageKey aImageKey, const Maybe& aAlternateFlags /* = Nothing() */) { if (!sInstance) { - return LookupResult(); + return LookupResult(MatchType::NOT_FOUND); } MutexAutoLock lock(sInstance->GetMutex()); @@ -1013,7 +1090,7 @@ SurfaceCache::LookupBestMatch(const ImageKey aImageKey, /* = Nothing() */) { if (!sInstance) { - return LookupResult(); + return LookupResult(MatchType::NOT_FOUND); } MutexAutoLock lock(sInstance->GetMutex()); @@ -1040,6 +1117,19 @@ SurfaceCache::Insert(imgFrame* aSurface, return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime); } +/* static */ InsertOutcome +SurfaceCache::InsertPlaceholder(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) +{ + if (!sInstance) { + return InsertOutcome::FAILURE; + } + + MutexAutoLock lock(sInstance->GetMutex()); + return sInstance->Insert(nullptr, sPlaceholderCost, aImageKey, aSurfaceKey, + Lifetime::Transient); +} + /* static */ bool SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */) { diff --git a/image/SurfaceCache.h b/image/SurfaceCache.h index cedf38d08374..32d61b068ca1 100644 --- a/image/SurfaceCache.h +++ b/image/SurfaceCache.h @@ -230,6 +230,7 @@ struct SurfaceCache /** * Insert a surface into the cache. If a surface with the same ImageKey and * SurfaceKey is already in the cache, Insert returns FAILURE_ALREADY_PRESENT. + * If a matching placeholder is already present, the placeholder is removed. * * Each surface in the cache has a lifetime, either Transient or Persistent. * Transient surfaces can expire from the cache at any time. Persistent @@ -280,6 +281,33 @@ struct SurfaceCache const SurfaceKey& aSurfaceKey, Lifetime aLifetime); + /** + * Insert a placeholder for a surface into the cache. If a surface with the + * same ImageKey and SurfaceKey is already in the cache, InsertPlaceholder() + * returns FAILURE_ALREADY_PRESENT. + * + * Placeholders exist to allow lazy allocation of surfaces. The Lookup*() + * methods will report whether a placeholder for an exactly matching surface + * existed by returning a MatchType of PENDING or SUBSTITUTE_BECAUSE_PENDING, + * but they will never return a placeholder directly. (They couldn't, since + * placeholders don't have an associated surface.) + * + * Once inserted, placeholders can be removed using RemoveSurface() or + * RemoveImage(), just like a surface. They're automatically removed when a + * real surface that matches the placeholder is inserted with Insert(). + * + * @param aImageKey Key data identifying which image the placeholder + * belongs to. + * @param aSurfaceKey Key data which uniquely identifies the surface the + * placeholder stands in for. + * @return SUCCESS if the placeholder was inserted successfully. + * FAILURE if the placeholder could not be inserted for some reason. + * FAILURE_ALREADY_PRESENT if a surface with the same ImageKey and + * SurfaceKey already exists in the cache. + */ + static InsertOutcome InsertPlaceholder(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey); + /** * Checks if a surface of a given size could possibly be stored in the cache. * If CanHold() returns false, Insert() will always fail to insert the @@ -362,8 +390,8 @@ struct SurfaceCache static void UnlockSurfaces(const ImageKey aImageKey); /** - * Removes a surface from the cache, if it's present. If it's not present, - * RemoveSurface() has no effect. + * Removes a surface or placeholder from the cache, if it's present. If it's + * not present, RemoveSurface() has no effect. * * Use this function to remove individual surfaces that have become invalid. * Prefer RemoveImage() or DiscardAll() when they're applicable, as they have @@ -378,8 +406,9 @@ struct SurfaceCache const SurfaceKey& aSurfaceKey); /** - * Removes all cached surfaces associated with the given image from the cache. - * If the image is locked, it is automatically unlocked. + * Removes all cached surfaces and placeholders associated with the given + * image from the cache. If the image is locked, it is automatically + * unlocked. * * This MUST be called, at a minimum, when an Image which could be storing * surfaces in the surface cache is destroyed. If another image were allocated diff --git a/image/decoders/icon/mac/nsIconChannelCocoa.mm b/image/decoders/icon/mac/nsIconChannelCocoa.mm index 62733a5f34f3..77e0c31bb020 100644 --- a/image/decoders/icon/mac/nsIconChannelCocoa.mm +++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm @@ -25,6 +25,7 @@ #include "nsTArray.h" #include "nsObjCExceptions.h" #include "nsProxyRelease.h" +#include "nsContentSecurityManager.h" #include @@ -177,6 +178,15 @@ nsIconChannel::Open(nsIInputStream** _retval) return MakeInputStream(_retval, false); } +NS_IMETHODIMP +nsIconChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile, uint32_t* aDesiredImageSize, @@ -236,6 +246,15 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener, return rv; } +NS_IMETHODIMP +nsIconChannel::AsyncOpen2(nsIStreamListener* aListener) +{ + nsCOMPtr listener = aListener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return AsyncOpen(listener, nullptr); +} + nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, bool aNonBlocking) diff --git a/image/decoders/icon/win/nsIconChannel.cpp b/image/decoders/icon/win/nsIconChannel.cpp index d4a96edbe38c..f180aa73b4e2 100644 --- a/image/decoders/icon/win/nsIconChannel.cpp +++ b/image/decoders/icon/win/nsIconChannel.cpp @@ -26,6 +26,7 @@ #include "nsCExternalHandlerService.h" #include "nsDirectoryServiceDefs.h" #include "nsProxyRelease.h" +#include "nsContentSecurityManager.h" #ifdef _WIN32_WINNT #undef _WIN32_WINNT @@ -198,6 +199,15 @@ nsIconChannel::Open(nsIInputStream** _retval) return MakeInputStream(_retval, false); } +NS_IMETHODIMP +nsIconChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile, uint32_t* aDesiredImageSize, nsCString& aContentType, @@ -253,6 +263,15 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener, return rv; } +NS_IMETHODIMP +nsIconChannel::AsyncOpen2(nsIStreamListener* aListener) +{ + nsCOMPtr listener = aListener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return AsyncOpen(listener, nullptr); +} + static DWORD GetSpecialFolderIcon(nsIFile* aFile, int aFolder, SHFILEINFOW* aSFI, UINT aInfoFlags) diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 19dc5580aa96..1db7fee623db 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -16,6 +16,7 @@ #include "nsNullPrincipal.h" #include "nsServiceManagerUtils.h" #include "nsString.h" +#include "nsTArray.h" namespace mozilla { namespace net { @@ -244,6 +245,12 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); + nsTArray redirectChain; + for (const nsCOMPtr& principal : aLoadInfo->RedirectChain()) { + rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement()); + NS_ENSURE_SUCCESS(rv, rv); + } + *aOptionalLoadInfoArgs = LoadInfoArgs( requestingPrincipalInfo, @@ -253,7 +260,10 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), - aLoadInfo->GetParentOuterWindowID()); + aLoadInfo->GetParentOuterWindowID(), + aLoadInfo->GetEnforceSecurity(), + aLoadInfo->GetInitialSecurityCheckDone(), + redirectChain); return NS_OK; } @@ -278,6 +288,14 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, PrincipalInfoToPrincipal(loadInfoArgs.triggeringPrincipalInfo(), &rv); NS_ENSURE_SUCCESS(rv, rv); + nsTArray> redirectChain; + for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChain()) { + nsCOMPtr redirectedPrincipal = + PrincipalInfoToPrincipal(principalInfo, &rv); + NS_ENSURE_SUCCESS(rv, rv); + redirectChain.AppendElement(redirectedPrincipal.forget()); + } + nsCOMPtr loadInfo = new mozilla::LoadInfo(requestingPrincipal, triggeringPrincipal, @@ -286,7 +304,10 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, loadInfoArgs.upgradeInsecureRequests(), loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), - loadInfoArgs.parentOuterWindowID()); + loadInfoArgs.parentOuterWindowID(), + loadInfoArgs.enforceSecurity(), + loadInfoArgs.initialSecurityCheckDone(), + redirectChain); loadInfo.forget(outLoadInfo); return NS_OK; diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 4a17911c39e9..474e86a63e1a 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -508,6 +508,69 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase namespace js { +/* + * InternalHandle is a handle to an internal pointer into a gcthing. Use + * InternalHandle when you have a pointer to a direct field of a gcthing, or + * when you need a parameter type for something that *may* be a pointer to a + * direct field of a gcthing. + */ +template +class InternalHandle {}; + +template +class InternalHandle +{ + void * const* holder; + size_t offset; + + public: + /* + * Create an InternalHandle using a Handle to the gcthing containing the + * field in question, and a pointer to the field. + */ + template + InternalHandle(const JS::Handle& handle, T* field) + : holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get())) + {} + + /* + * Create an InternalHandle to a field within a Rooted<>. + */ + template + InternalHandle(const JS::Rooted& root, T* field) + : holder((void**)root.address()), offset(uintptr_t(field) - uintptr_t(root.get())) + {} + + InternalHandle(const InternalHandle& other) + : holder(other.holder), offset(other.offset) {} + + T* get() const { return reinterpret_cast(uintptr_t(*holder) + offset); } + + const T& operator*() const { return *get(); } + T* operator->() const { return get(); } + + static InternalHandle fromMarkedLocation(T* fieldPtr) { + return InternalHandle(fieldPtr); + } + + private: + /* + * Create an InternalHandle to something that is not a pointer to a + * gcthing, and so does not need to be rooted in the first place. Use these + * InternalHandles to pass pointers into functions that also need to accept + * regular InternalHandles to gcthing fields. + * + * Make this private to prevent accidental misuse; this is only for + * fromMarkedLocation(). + */ + explicit InternalHandle(T* field) + : holder(&js::ConstNullValue), + offset(uintptr_t(field)) + {} + + void operator=(InternalHandle other) = delete; +}; + /* * By default, things should use the inheritance hierarchy to find their * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that diff --git a/js/public/Value.h b/js/public/Value.h index c30209793d5a..9f7c44369c32 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1940,13 +1940,6 @@ static_assert(sizeof(LayoutAlignmentTester) == 16, } // namespace JS -/* - * JS::Value and jsval are the same type; jsval is the old name, kept around - * for backwards compatibility along with all the JSVAL_* operations below. - * jsval_layout is an implementation detail and should not be used externally. - */ -typedef JS::Value jsval; - static_assert(sizeof(jsval_layout) == sizeof(JS::Value), "jsval_layout and JS::Value must have identical layouts"); diff --git a/js/src/builtin/AtomicsObject.h b/js/src/builtin/AtomicsObject.h index 9cf0a0f6daaf..b07b4ae60f38 100644 --- a/js/src/builtin/AtomicsObject.h +++ b/js/src/builtin/AtomicsObject.h @@ -17,7 +17,7 @@ class AtomicsObject : public JSObject public: static const Class class_; static JSObject* initClass(JSContext* cx, Handle global); - static bool toString(JSContext* cx, unsigned int argc, jsval* vp); + static bool toString(JSContext* cx, unsigned int argc, Value* vp); // Defined return values for futexWait. // The error values must be negative because APIs such as futexWaitOrRequeue diff --git a/js/src/builtin/Profilers.cpp b/js/src/builtin/Profilers.cpp index 9a36d1672b51..43708372dc72 100644 --- a/js/src/builtin/Profilers.cpp +++ b/js/src/builtin/Profilers.cpp @@ -229,7 +229,7 @@ struct RequiredStringArg { }; static bool -StartProfiling(JSContext* cx, unsigned argc, jsval* vp) +StartProfiling(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -256,7 +256,7 @@ StartProfiling(JSContext* cx, unsigned argc, jsval* vp) } static bool -StopProfiling(JSContext* cx, unsigned argc, jsval* vp) +StopProfiling(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -272,7 +272,7 @@ StopProfiling(JSContext* cx, unsigned argc, jsval* vp) } static bool -PauseProfilers(JSContext* cx, unsigned argc, jsval* vp) +PauseProfilers(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -288,7 +288,7 @@ PauseProfilers(JSContext* cx, unsigned argc, jsval* vp) } static bool -ResumeProfilers(JSContext* cx, unsigned argc, jsval* vp) +ResumeProfilers(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -305,7 +305,7 @@ ResumeProfilers(JSContext* cx, unsigned argc, jsval* vp) /* Usage: DumpProfile([filename[, profileName]]) */ static bool -DumpProfile(JSContext* cx, unsigned argc, jsval* vp) +DumpProfile(JSContext* cx, unsigned argc, Value* vp) { bool ret; CallArgs args = CallArgsFromVp(argc, vp); @@ -332,7 +332,7 @@ DumpProfile(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, jsval* vp) +GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setNumber(uint32_t(cx->runtime()->gc.stats.getMaxGCPauseSinceClear())); @@ -340,7 +340,7 @@ GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, jsval* vp) } static bool -ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, jsval* vp) +ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setNumber(uint32_t(cx->runtime()->gc.stats.clearMaxGCPauseAccumulator())); @@ -350,7 +350,7 @@ ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, jsval* vp) #if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS) static bool -IgnoreAndReturnTrue(JSContext* cx, unsigned argc, jsval* vp) +IgnoreAndReturnTrue(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setBoolean(true); @@ -361,7 +361,7 @@ IgnoreAndReturnTrue(JSContext* cx, unsigned argc, jsval* vp) #ifdef MOZ_CALLGRIND static bool -StartCallgrind(JSContext* cx, unsigned argc, jsval* vp) +StartCallgrind(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setBoolean(js_StartCallgrind()); @@ -369,7 +369,7 @@ StartCallgrind(JSContext* cx, unsigned argc, jsval* vp) } static bool -StopCallgrind(JSContext* cx, unsigned argc, jsval* vp) +StopCallgrind(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setBoolean(js_StopCallgrind()); @@ -377,7 +377,7 @@ StopCallgrind(JSContext* cx, unsigned argc, jsval* vp) } static bool -DumpCallgrind(JSContext* cx, unsigned argc, jsval* vp) +DumpCallgrind(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index ae1c03cf11ac..e0b54ad92b42 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -3621,7 +3621,7 @@ ASTSerializer::functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst } static bool -reflect_parse(JSContext* cx, uint32_t argc, jsval* vp) +reflect_parse(JSContext* cx, uint32_t argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index db702b28d2a0..dfc46906b806 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -416,11 +416,12 @@ static bool FillLanes(JSContext* cx, Handle result, const CallArgs& args) { typedef typename T::Elem Elem; + InternalHandle mem(result, reinterpret_cast(result->typedMem())); Elem tmp; for (unsigned i = 0; i < T::lanes; i++) { if (!T::toType(cx, args.get(i), &tmp)) return false; - reinterpret_cast(result->typedMem())[i] = tmp; + mem.get()[i] = tmp; } args.rval().setObject(*result); return true; diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index 0682aacf623e..4b8b80d3d123 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -361,7 +361,7 @@ class SIMDObject : public JSObject public: static const Class class_; static JSObject* initClass(JSContext* cx, Handle global); - static bool toString(JSContext* cx, unsigned int argc, jsval* vp); + static bool toString(JSContext* cx, unsigned int argc, Value* vp); }; // These classes exist for use with templates below. diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 3aa278b770bf..b7c38fa568ab 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -49,7 +49,7 @@ using mozilla::UniquePtr; static bool fuzzingSafe = false; static bool -GetBuildConfiguration(JSContext* cx, unsigned argc, jsval* vp) +GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject info(cx, JS_NewPlainObject(cx)); @@ -229,7 +229,7 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, jsval* vp) } static bool -GC(JSContext* cx, unsigned argc, jsval* vp) +GC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -285,7 +285,7 @@ GC(JSContext* cx, unsigned argc, jsval* vp) } static bool -MinorGC(JSContext* cx, unsigned argc, jsval* vp) +MinorGC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.get(0) == BooleanValue(true)) @@ -459,7 +459,7 @@ IsRelazifiableFunction(JSContext* cx, unsigned argc, Value* vp) } static bool -InternalConst(JSContext* cx, unsigned argc, jsval* vp) +InternalConst(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -484,7 +484,7 @@ InternalConst(JSContext* cx, unsigned argc, jsval* vp) } static bool -GCPreserveCode(JSContext* cx, unsigned argc, jsval* vp) +GCPreserveCode(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -585,7 +585,7 @@ SelectForGC(JSContext* cx, unsigned argc, Value* vp) } static bool -VerifyPreBarriers(JSContext* cx, unsigned argc, jsval* vp) +VerifyPreBarriers(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -601,7 +601,7 @@ VerifyPreBarriers(JSContext* cx, unsigned argc, jsval* vp) } static bool -VerifyPostBarriers(JSContext* cx, unsigned argc, jsval* vp) +VerifyPostBarriers(JSContext* cx, unsigned argc, Value* vp) { // This is a no-op since the post barrier verifier was removed. CallArgs args = CallArgsFromVp(argc, vp); @@ -615,7 +615,7 @@ VerifyPostBarriers(JSContext* cx, unsigned argc, jsval* vp) } static bool -GCState(JSContext* cx, unsigned argc, jsval* vp) +GCState(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -646,7 +646,7 @@ GCState(JSContext* cx, unsigned argc, jsval* vp) } static bool -DeterministicGC(JSContext* cx, unsigned argc, jsval* vp) +DeterministicGC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -750,7 +750,7 @@ AbortGC(JSContext* cx, unsigned argc, Value* vp) } static bool -ValidateGC(JSContext* cx, unsigned argc, jsval* vp) +ValidateGC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -766,7 +766,7 @@ ValidateGC(JSContext* cx, unsigned argc, jsval* vp) } static bool -FullCompartmentChecks(JSContext* cx, unsigned argc, jsval* vp) +FullCompartmentChecks(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -782,7 +782,7 @@ FullCompartmentChecks(JSContext* cx, unsigned argc, jsval* vp) } static bool -NondeterministicGetWeakMapKeys(JSContext* cx, unsigned argc, jsval* vp) +NondeterministicGetWeakMapKeys(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -830,7 +830,7 @@ class HasChildTracer : public JS::CallbackTracer }; static bool -HasChild(JSContext* cx, unsigned argc, jsval* vp) +HasChild(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedValue parent(cx, args.get(0)); @@ -848,7 +848,7 @@ HasChild(JSContext* cx, unsigned argc, jsval* vp) } static bool -SetSavedStacksRNGState(JSContext* cx, unsigned argc, jsval* vp) +SetSavedStacksRNGState(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.requireAtLeast(cx, "setSavedStacksRNGState", 1)) @@ -863,7 +863,7 @@ SetSavedStacksRNGState(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetSavedFrameCount(JSContext* cx, unsigned argc, jsval* vp) +GetSavedFrameCount(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setNumber(cx->compartment()->savedStacks().count()); @@ -871,7 +871,7 @@ GetSavedFrameCount(JSContext* cx, unsigned argc, jsval* vp) } static bool -SaveStack(JSContext* cx, unsigned argc, jsval* vp) +SaveStack(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -918,7 +918,7 @@ SaveStack(JSContext* cx, unsigned argc, jsval* vp) } static bool -CallFunctionWithAsyncStack(JSContext* cx, unsigned argc, jsval* vp) +CallFunctionWithAsyncStack(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -949,14 +949,14 @@ CallFunctionWithAsyncStack(JSContext* cx, unsigned argc, jsval* vp) } static bool -EnableTrackAllocations(JSContext* cx, unsigned argc, jsval* vp) +EnableTrackAllocations(JSContext* cx, unsigned argc, Value* vp) { SetObjectMetadataCallback(cx, SavedStacksMetadataCallback); return true; } static bool -DisableTrackAllocations(JSContext* cx, unsigned argc, jsval* vp) +DisableTrackAllocations(JSContext* cx, unsigned argc, Value* vp) { SetObjectMetadataCallback(cx, nullptr); return true; @@ -964,7 +964,7 @@ DisableTrackAllocations(JSContext* cx, unsigned argc, jsval* vp) #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) static bool -OOMAfterAllocations(JSContext* cx, unsigned argc, jsval* vp) +OOMAfterAllocations(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -982,7 +982,7 @@ OOMAfterAllocations(JSContext* cx, unsigned argc, jsval* vp) } static bool -OOMAtAllocation(JSContext* cx, unsigned argc, jsval* vp) +OOMAtAllocation(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -1000,7 +1000,7 @@ OOMAtAllocation(JSContext* cx, unsigned argc, jsval* vp) } static bool -ResetOOMFailure(JSContext* cx, unsigned argc, jsval* vp) +ResetOOMFailure(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setBoolean(OOM_counter >= OOM_maxAllocations); @@ -1014,7 +1014,7 @@ static const js::Class FakePromiseClass = { }; static bool -MakeFakePromise(JSContext* cx, unsigned argc, jsval* vp) +MakeFakePromise(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1028,7 +1028,7 @@ MakeFakePromise(JSContext* cx, unsigned argc, jsval* vp) } static bool -SettleFakePromise(JSContext* cx, unsigned argc, jsval* vp) +SettleFakePromise(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.requireAtLeast(cx, "settleFakePromise", 1)) @@ -1065,7 +1065,7 @@ static const JSClass FinalizeCounterClass = { }; static bool -MakeFinalizeObserver(JSContext* cx, unsigned argc, jsval* vp) +MakeFinalizeObserver(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1078,7 +1078,7 @@ MakeFinalizeObserver(JSContext* cx, unsigned argc, jsval* vp) } static bool -FinalizeCount(JSContext* cx, unsigned argc, jsval* vp) +FinalizeCount(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setInt32(finalizeCount); @@ -1144,7 +1144,7 @@ DumpHeap(JSContext* cx, unsigned argc, Value* vp) } static bool -Terminate(JSContext* cx, unsigned arg, jsval* vp) +Terminate(JSContext* cx, unsigned arg, Value* vp) { #ifdef JS_MORE_DETERMINISTIC // Print a message to stderr in more-deterministic builds to help jsfunfuzz @@ -1161,7 +1161,7 @@ static ProfileEntry SPS_PROFILING_STACK[SPS_PROFILING_STACK_MAX_SIZE]; static uint32_t SPS_PROFILING_STACK_SIZE = 0; static bool -EnableSPSProfiling(JSContext* cx, unsigned argc, jsval* vp) +EnableSPSProfiling(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1179,7 +1179,7 @@ EnableSPSProfiling(JSContext* cx, unsigned argc, jsval* vp) } static bool -EnableSPSProfilingWithSlowAssertions(JSContext* cx, unsigned argc, jsval* vp) +EnableSPSProfilingWithSlowAssertions(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); @@ -1208,7 +1208,7 @@ EnableSPSProfilingWithSlowAssertions(JSContext* cx, unsigned argc, jsval* vp) } static bool -DisableSPSProfiling(JSContext* cx, unsigned argc, jsval* vp) +DisableSPSProfiling(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (cx->runtime()->spsProfiler.installed()) @@ -1218,7 +1218,7 @@ DisableSPSProfiling(JSContext* cx, unsigned argc, jsval* vp) } static bool -ReadSPSProfilingStack(JSContext* cx, unsigned argc, jsval* vp) +ReadSPSProfilingStack(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); @@ -1304,7 +1304,7 @@ ReadSPSProfilingStack(JSContext* cx, unsigned argc, jsval* vp) } static bool -EnableOsiPointRegisterChecks(JSContext*, unsigned argc, jsval* vp) +EnableOsiPointRegisterChecks(JSContext*, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); #ifdef CHECK_OSIPOINT_REGISTERS @@ -1315,7 +1315,7 @@ EnableOsiPointRegisterChecks(JSContext*, unsigned argc, jsval* vp) } static bool -DisplayName(JSContext* cx, unsigned argc, jsval* vp) +DisplayName(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.get(0).isObject() || !args[0].toObject().is()) { @@ -1376,7 +1376,7 @@ ShellObjectMetadataCallback(JSContext* cx, JSObject*) } static bool -SetObjectMetadataCallback(JSContext* cx, unsigned argc, jsval* vp) +SetObjectMetadataCallback(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1388,7 +1388,7 @@ SetObjectMetadataCallback(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetObjectMetadata(JSContext* cx, unsigned argc, jsval* vp) +GetObjectMetadata(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1 || !args[0].isObject()) { @@ -1401,7 +1401,7 @@ GetObjectMetadata(JSContext* cx, unsigned argc, jsval* vp) } bool -js::testingFunc_bailout(JSContext* cx, unsigned argc, jsval* vp) +js::testingFunc_bailout(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1411,7 +1411,7 @@ js::testingFunc_bailout(JSContext* cx, unsigned argc, jsval* vp) } bool -js::testingFunc_inJit(JSContext* cx, unsigned argc, jsval* vp) +js::testingFunc_inJit(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1439,7 +1439,7 @@ js::testingFunc_inJit(JSContext* cx, unsigned argc, jsval* vp) } bool -js::testingFunc_inIon(JSContext* cx, unsigned argc, jsval* vp) +js::testingFunc_inIon(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1476,7 +1476,7 @@ js::testingFunc_inIon(JSContext* cx, unsigned argc, jsval* vp) } bool -js::testingFunc_assertFloat32(JSContext* cx, unsigned argc, jsval* vp) +js::testingFunc_assertFloat32(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -1490,7 +1490,7 @@ js::testingFunc_assertFloat32(JSContext* cx, unsigned argc, jsval* vp) } static bool -TestingFunc_assertJitStackInvariants(JSContext* cx, unsigned argc, jsval* vp) +TestingFunc_assertJitStackInvariants(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1500,7 +1500,7 @@ TestingFunc_assertJitStackInvariants(JSContext* cx, unsigned argc, jsval* vp) } bool -js::testingFunc_assertRecoveredOnBailout(JSContext* cx, unsigned argc, jsval* vp) +js::testingFunc_assertRecoveredOnBailout(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -1514,7 +1514,7 @@ js::testingFunc_assertRecoveredOnBailout(JSContext* cx, unsigned argc, jsval* vp } static bool -SetJitCompilerOption(JSContext* cx, unsigned argc, jsval* vp) +SetJitCompilerOption(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject callee(cx, &args.callee()); @@ -1573,7 +1573,7 @@ SetJitCompilerOption(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetJitCompilerOptions(JSContext* cx, unsigned argc, jsval* vp) +GetJitCompilerOptions(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject info(cx, JS_NewPlainObject(cx)); @@ -1598,7 +1598,7 @@ GetJitCompilerOptions(JSContext* cx, unsigned argc, jsval* vp) } static bool -SetIonCheckGraphCoherency(JSContext* cx, unsigned argc, jsval* vp) +SetIonCheckGraphCoherency(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); jit::js_JitOptions.checkGraphConsistency = ToBoolean(args.get(0)); @@ -1762,7 +1762,7 @@ const JSPropertySpec CloneBufferObject::props_[] = { }; static bool -Serialize(JSContext* cx, unsigned argc, jsval* vp) +Serialize(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1779,7 +1779,7 @@ Serialize(JSContext* cx, unsigned argc, jsval* vp) } static bool -Deserialize(JSContext* cx, unsigned argc, jsval* vp) +Deserialize(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1820,7 +1820,7 @@ Deserialize(JSContext* cx, unsigned argc, jsval* vp) } static bool -Neuter(JSContext* cx, unsigned argc, jsval* vp) +Neuter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1862,7 +1862,7 @@ Neuter(JSContext* cx, unsigned argc, jsval* vp) } static bool -HelperThreadCount(JSContext* cx, unsigned argc, jsval* vp) +HelperThreadCount(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); #ifdef JS_MORE_DETERMINISTIC @@ -1878,7 +1878,7 @@ HelperThreadCount(JSContext* cx, unsigned argc, jsval* vp) } static bool -TimesAccessed(JSContext* cx, unsigned argc, jsval* vp) +TimesAccessed(JSContext* cx, unsigned argc, Value* vp) { static int32_t accessed = 0; CallArgs args = CallArgsFromVp(argc, vp); @@ -1888,7 +1888,7 @@ TimesAccessed(JSContext* cx, unsigned argc, jsval* vp) #ifdef JS_TRACE_LOGGING static bool -EnableTraceLogger(JSContext* cx, unsigned argc, jsval* vp) +EnableTraceLogger(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime()); @@ -1900,7 +1900,7 @@ EnableTraceLogger(JSContext* cx, unsigned argc, jsval* vp) } static bool -DisableTraceLogger(JSContext* cx, unsigned argc, jsval* vp) +DisableTraceLogger(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime()); @@ -1912,7 +1912,7 @@ DisableTraceLogger(JSContext* cx, unsigned argc, jsval* vp) #ifdef DEBUG static bool -DumpObject(JSContext* cx, unsigned argc, jsval* vp) +DumpObject(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, ToObject(cx, args.get(0))); @@ -1928,7 +1928,7 @@ DumpObject(JSContext* cx, unsigned argc, jsval* vp) #ifdef NIGHTLY_BUILD static bool -ObjectAddress(JSContext* cx, unsigned argc, jsval* vp) +ObjectAddress(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -1961,7 +1961,7 @@ ObjectAddress(JSContext* cx, unsigned argc, jsval* vp) #endif static bool -DumpBacktrace(JSContext* cx, unsigned argc, jsval* vp) +DumpBacktrace(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); DumpBacktrace(cx); @@ -1970,7 +1970,7 @@ DumpBacktrace(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetBacktrace(JSContext* cx, unsigned argc, jsval* vp) +GetBacktrace(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2014,7 +2014,7 @@ GetBacktrace(JSContext* cx, unsigned argc, jsval* vp) } static bool -ReportOutOfMemory(JSContext* cx, unsigned argc, jsval* vp) +ReportOutOfMemory(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JS_ReportOutOfMemory(cx); @@ -2024,7 +2024,7 @@ ReportOutOfMemory(JSContext* cx, unsigned argc, jsval* vp) } static bool -ReportLargeAllocationFailure(JSContext* cx, unsigned argc, jsval* vp) +ReportLargeAllocationFailure(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); void* buf = cx->runtime()->onOutOfMemoryCanGC(AllocFunction::Malloc, JSRuntime::LARGE_ALLOCATION); @@ -2147,7 +2147,7 @@ struct FindPathHandler { } // namespace heaptools static bool -FindPath(JSContext* cx, unsigned argc, jsval* vp) +FindPath(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (argc < 2) { @@ -2247,7 +2247,7 @@ FindPath(JSContext* cx, unsigned argc, jsval* vp) } static bool -EvalReturningScope(JSContext* cx, unsigned argc, jsval* vp) +EvalReturningScope(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.requireAtLeast(cx, "evalReturningScope", 1)) @@ -2495,7 +2495,7 @@ GetConstructorName(JSContext* cx, unsigned argc, Value* vp) } static bool -AllocationMarker(JSContext* cx, unsigned argc, jsval* vp) +AllocationMarker(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2557,7 +2557,7 @@ MinorGC* prevMinorGC = nullptr; } /* namespace gcCallback */ static bool -SetGCCallback(JSContext* cx, unsigned argc, jsval* vp) +SetGCCallback(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 01e1ad4b0575..f92dc5612e03 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -221,10 +221,10 @@ struct Property } }; -static bool ConstructAbstract(JSContext* cx, unsigned argc, jsval* vp); +static bool ConstructAbstract(JSContext* cx, unsigned argc, Value* vp); namespace CType { - static bool ConstructData(JSContext* cx, unsigned argc, jsval* vp); + static bool ConstructData(JSContext* cx, unsigned argc, Value* vp); static bool ConstructBasic(JSContext* cx, HandleObject obj, const CallArgs& args); static void Trace(JSTracer* trc, JSObject* obj); @@ -238,9 +238,9 @@ namespace CType { bool SizeGetter(JSContext* cx, JS::CallArgs args); bool PtrGetter(JSContext* cx, JS::CallArgs args); - static bool CreateArray(JSContext* cx, unsigned argc, jsval* vp); - static bool ToString(JSContext* cx, unsigned argc, jsval* vp); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); + static bool CreateArray(JSContext* cx, unsigned argc, Value* vp); + static bool ToString(JSContext* cx, unsigned argc, Value* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); static bool HasInstance(JSContext* cx, HandleObject obj, MutableHandleValue v, bool* bp); @@ -257,11 +257,11 @@ namespace CType { namespace ABI { bool IsABI(JSObject* obj); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); } // namespace ABI namespace PointerType { - static bool Create(JSContext* cx, unsigned argc, jsval* vp); + static bool Create(JSContext* cx, unsigned argc, Value* vp); static bool ConstructData(JSContext* cx, HandleObject obj, const CallArgs& args); bool IsPointerType(HandleValue v); @@ -271,9 +271,9 @@ namespace PointerType { bool ContentsGetter(JSContext* cx, JS::CallArgs args); bool ContentsSetter(JSContext* cx, JS::CallArgs args); - static bool IsNull(JSContext* cx, unsigned argc, jsval* vp); - static bool Increment(JSContext* cx, unsigned argc, jsval* vp); - static bool Decrement(JSContext* cx, unsigned argc, jsval* vp); + static bool IsNull(JSContext* cx, unsigned argc, Value* vp); + static bool Increment(JSContext* cx, unsigned argc, Value* vp); + static bool Decrement(JSContext* cx, unsigned argc, Value* vp); // The following is not an instance function, since we don't want to expose arbitrary // pointer arithmetic at this moment. static bool OffsetBy(JSContext* cx, const CallArgs& args, int offset); @@ -283,7 +283,7 @@ namespace ArrayType { bool IsArrayType(HandleValue v); bool IsArrayOrArrayType(HandleValue v); - static bool Create(JSContext* cx, unsigned argc, jsval* vp); + static bool Create(JSContext* cx, unsigned argc, Value* vp); static bool ConstructData(JSContext* cx, HandleObject obj, const CallArgs& args); bool ElementTypeGetter(JSContext* cx, JS::CallArgs args); @@ -292,13 +292,13 @@ namespace ArrayType { static bool Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp); static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp, ObjectOpResult& result); - static bool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp); + static bool AddressOfElement(JSContext* cx, unsigned argc, Value* vp); } // namespace ArrayType namespace StructType { bool IsStruct(HandleValue v); - static bool Create(JSContext* cx, unsigned argc, jsval* vp); + static bool Create(JSContext* cx, unsigned argc, Value* vp); static bool ConstructData(JSContext* cx, HandleObject obj, const CallArgs& args); bool FieldsArrayGetter(JSContext* cx, JS::CallArgs args); @@ -309,16 +309,16 @@ namespace StructType { static bool FieldGetter(JSContext* cx, unsigned argc, Value* vp); static bool FieldSetter(JSContext* cx, unsigned argc, Value* vp); - static bool AddressOfField(JSContext* cx, unsigned argc, jsval* vp); - static bool Define(JSContext* cx, unsigned argc, jsval* vp); + static bool AddressOfField(JSContext* cx, unsigned argc, Value* vp); + static bool Define(JSContext* cx, unsigned argc, Value* vp); } // namespace StructType namespace FunctionType { - static bool Create(JSContext* cx, unsigned argc, jsval* vp); + static bool Create(JSContext* cx, unsigned argc, Value* vp); static bool ConstructData(JSContext* cx, HandleObject typeObj, - HandleObject dataObj, HandleObject fnObj, HandleObject thisObj, jsval errVal); + HandleObject dataObj, HandleObject fnObj, HandleObject thisObj, Value errVal); - static bool Call(JSContext* cx, unsigned argc, jsval* vp); + static bool Call(JSContext* cx, unsigned argc, Value* vp); bool IsFunctionType(HandleValue v); @@ -355,10 +355,10 @@ namespace CData { bool ValueGetter(JSContext* cx, JS::CallArgs args); bool ValueSetter(JSContext* cx, JS::CallArgs args); - static bool Address(JSContext* cx, unsigned argc, jsval* vp); - static bool ReadString(JSContext* cx, unsigned argc, jsval* vp); - static bool ReadStringReplaceMalformed(JSContext* cx, unsigned argc, jsval* vp); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); + static bool Address(JSContext* cx, unsigned argc, Value* vp); + static bool ReadString(JSContext* cx, unsigned argc, Value* vp); + static bool ReadStringReplaceMalformed(JSContext* cx, unsigned argc, Value* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); static JSString* GetSourceString(JSContext* cx, HandleObject typeObj, void* data); @@ -382,7 +382,7 @@ namespace CDataFinalizer { * Where |finalizer| is a one-argument function taking a value * with the same type as |value|. */ - static bool Construct(JSContext* cx, unsigned argc, jsval* vp); + static bool Construct(JSContext* cx, unsigned argc, Value* vp); /* * Private data held by |CDataFinalizer|. @@ -428,10 +428,10 @@ namespace CDataFinalizer { * Methods of instances of |CDataFinalizer| */ namespace Methods { - static bool Dispose(JSContext* cx, unsigned argc, jsval* vp); - static bool Forget(JSContext* cx, unsigned argc, jsval* vp); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); - static bool ToString(JSContext* cx, unsigned argc, jsval* vp); + static bool Dispose(JSContext* cx, unsigned argc, Value* vp); + static bool Forget(JSContext* cx, unsigned argc, Value* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); + static bool ToString(JSContext* cx, unsigned argc, Value* vp); } // namespace Methods /* @@ -473,9 +473,9 @@ namespace CDataFinalizer { static void Finalize(JSFreeOp* fop, JSObject* obj); /* - * Return the jsval contained by this finalizer. + * Return the Value contained by this finalizer. * - * Note that the jsval is actually not recorded, but converted back from C. + * Note that the Value is actually not recorded, but converted back from C. */ static bool GetValue(JSContext* cx, JSObject* obj, MutableHandleValue result); @@ -500,27 +500,27 @@ namespace Int64Base { } // namespace Int64Base namespace Int64 { - static bool Construct(JSContext* cx, unsigned argc, jsval* vp); + static bool Construct(JSContext* cx, unsigned argc, Value* vp); - static bool ToString(JSContext* cx, unsigned argc, jsval* vp); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); + static bool ToString(JSContext* cx, unsigned argc, Value* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); - static bool Compare(JSContext* cx, unsigned argc, jsval* vp); - static bool Lo(JSContext* cx, unsigned argc, jsval* vp); - static bool Hi(JSContext* cx, unsigned argc, jsval* vp); - static bool Join(JSContext* cx, unsigned argc, jsval* vp); + static bool Compare(JSContext* cx, unsigned argc, Value* vp); + static bool Lo(JSContext* cx, unsigned argc, Value* vp); + static bool Hi(JSContext* cx, unsigned argc, Value* vp); + static bool Join(JSContext* cx, unsigned argc, Value* vp); } // namespace Int64 namespace UInt64 { - static bool Construct(JSContext* cx, unsigned argc, jsval* vp); + static bool Construct(JSContext* cx, unsigned argc, Value* vp); - static bool ToString(JSContext* cx, unsigned argc, jsval* vp); - static bool ToSource(JSContext* cx, unsigned argc, jsval* vp); + static bool ToString(JSContext* cx, unsigned argc, Value* vp); + static bool ToSource(JSContext* cx, unsigned argc, Value* vp); - static bool Compare(JSContext* cx, unsigned argc, jsval* vp); - static bool Lo(JSContext* cx, unsigned argc, jsval* vp); - static bool Hi(JSContext* cx, unsigned argc, jsval* vp); - static bool Join(JSContext* cx, unsigned argc, jsval* vp); + static bool Compare(JSContext* cx, unsigned argc, Value* vp); + static bool Lo(JSContext* cx, unsigned argc, Value* vp); + static bool Hi(JSContext* cx, unsigned argc, Value* vp); + static bool Join(JSContext* cx, unsigned argc, Value* vp); } // namespace UInt64 /******************************************************************************* @@ -872,7 +872,7 @@ GetABICode(JSObject* obj) if (JS_GetClass(obj) != &sCABIClass) return INVALID_ABI; - jsval result = JS_GetReservedSlot(obj, SLOT_ABICODE); + Value result = JS_GetReservedSlot(obj, SLOT_ABICODE); return ABICode(result.toInt32()); } @@ -1001,7 +1001,7 @@ BuildFunctionTypeSource(JSContext* cx, HandleObject funObj, AutoString& source) MOZ_ASSERT(CData::IsCData(funObj) || CType::IsCType(funObj)); if (CData::IsCData(funObj)) { - jsval slot = JS_GetReservedSlot(funObj, SLOT_REFERENT); + Value slot = JS_GetReservedSlot(funObj, SLOT_REFERENT); if (!slot.isUndefined() && Library::IsLibrary(&slot.toObject())) { slot = JS_GetReservedSlot(funObj, SLOT_FUNNAME); MOZ_ASSERT(!slot.isUndefined()); @@ -1922,7 +1922,7 @@ GetCallbacks(JSObject* obj) { MOZ_ASSERT(IsCTypesGlobal(obj)); - jsval result = JS_GetReservedSlot(obj, SLOT_CALLBACKS); + Value result = JS_GetReservedSlot(obj, SLOT_CALLBACKS); if (result.isUndefined()) return nullptr; @@ -2022,7 +2022,7 @@ SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj) return 0; size_t n = 0; - jsval slot = JS_GetReservedSlot(obj, ctypes::SLOT_OWNS); + Value slot = JS_GetReservedSlot(obj, ctypes::SLOT_OWNS); if (!slot.isUndefined()) { bool owns = slot.toBoolean(); slot = JS_GetReservedSlot(obj, ctypes::SLOT_DATA); @@ -2212,7 +2212,7 @@ static MOZ_ALWAYS_INLINE bool IsNegative(Type i) // Implicitly convert val to bool, allowing bool, int, and double // arguments numerically equal to 0 or 1. static bool -jsvalToBool(JSContext* cx, jsval val, bool* result) +jsvalToBool(JSContext* cx, Value val, bool* result) { if (val.isBoolean()) { *result = val.toBoolean(); @@ -2238,7 +2238,7 @@ jsvalToBool(JSContext* cx, jsval val, bool* result) // representable by IntegerType. template static bool -jsvalToInteger(JSContext* cx, jsval val, IntegerType* result) +jsvalToInteger(JSContext* cx, Value val, IntegerType* result) { JS_STATIC_ASSERT(NumericLimits::is_exact); @@ -2328,7 +2328,7 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result) // representable by FloatType. template static bool -jsvalToFloat(JSContext* cx, jsval val, FloatType* result) +jsvalToFloat(JSContext* cx, Value val, FloatType* result) { JS_STATIC_ASSERT(!NumericLimits::is_exact); @@ -2454,7 +2454,7 @@ StringToInteger(JSContext* cx, JSString* string, IntegerType* result) template static bool jsvalToBigInteger(JSContext* cx, - jsval val, + Value val, bool allowString, IntegerType* result) { @@ -2510,7 +2510,7 @@ jsvalToBigInteger(JSContext* cx, // Implicitly convert val to a size value, where the size value is represented // by size_t but must also fit in a double. static bool -jsvalToSize(JSContext* cx, jsval val, bool allowString, size_t* result) +jsvalToSize(JSContext* cx, Value val, bool allowString, size_t* result) { if (!jsvalToBigInteger(cx, val, allowString, result)) return false; @@ -2559,7 +2559,7 @@ jsidToSize(JSContext* cx, jsid val, bool allowString, size_t* result) return Convert(double(*result)) == *result; } -// Implicitly convert a size value to a jsval, ensuring that the size_t value +// Implicitly convert a size value to a Value, ensuring that the size_t value // fits in a double. static bool SizeTojsval(JSContext* cx, size_t size, MutableHandleValue result) @@ -2576,7 +2576,7 @@ SizeTojsval(JSContext* cx, size_t size, MutableHandleValue result) // Forcefully convert val to IntegerType when explicitly requested. template static bool -jsvalToIntegerExplicit(jsval val, IntegerType* result) +jsvalToIntegerExplicit(Value val, IntegerType* result) { JS_STATIC_ASSERT(NumericLimits::is_exact); @@ -2605,7 +2605,7 @@ jsvalToIntegerExplicit(jsval val, IntegerType* result) // Forcefully convert val to a pointer value when explicitly requested. static bool -jsvalToPtrExplicit(JSContext* cx, jsval val, uintptr_t* result) +jsvalToPtrExplicit(JSContext* cx, Value val, uintptr_t* result) { if (val.isInt32()) { // int32_t always fits in intptr_t. If the integer is negative, cast through @@ -2858,7 +2858,7 @@ bool CanConvertTypedArrayItemTo(JSObject* baseType, JSObject* valObj, JSContext* return elementTypeCode == baseTypeCode; } -// Implicitly convert jsval 'val' to a C binary representation of CType +// Implicitly convert Value 'val' to a C binary representation of CType // 'targetType', storing the result in 'buffer'. Adequate space must be // provided in 'buffer' by the caller. This function generally does minimal // coercion between types. There are two cases in which this function is used: @@ -3320,7 +3320,7 @@ ImplicitConvert(JSContext* cx, return true; } -// Convert jsval 'val' to a C binary representation of CType 'targetType', +// Convert Value 'val' to a C binary representation of CType 'targetType', // storing the result in 'buffer'. This function is more forceful than // ImplicitConvert. static bool @@ -3822,7 +3822,7 @@ BuildDataSource(JSContext* cx, bool ConstructAbstract(JSContext* cx, unsigned argc, - jsval* vp) + Value* vp) { // Calling an abstract base class constructor is disallowed. JS_ReportError(cx, "cannot construct from abstract type"); @@ -3836,7 +3836,7 @@ ConstructAbstract(JSContext* cx, bool CType::ConstructData(JSContext* cx, unsigned argc, - jsval* vp) + Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // get the callee object... @@ -3898,8 +3898,8 @@ CType::Create(JSContext* cx, HandleObject dataProto, TypeCode type, JSString* name_, - jsval size_, - jsval align_, + Value size_, + Value align_, ffi_type* ffiType) { RootedString name(cx, name_); @@ -3970,8 +3970,8 @@ CType::DefineBuiltin(JSContext* cx, JSObject* dataProto_, const char* name, TypeCode type, - jsval size_, - jsval align_, + Value size_, + Value align_, ffi_type* ffiType) { RootedObject typeProto(cx, typeProto_); @@ -4000,7 +4000,7 @@ void CType::Finalize(JSFreeOp* fop, JSObject* obj) { // Make sure our TypeCode slot is legit. If it's not, bail. - jsval slot = JS_GetReservedSlot(obj, SLOT_TYPECODE); + Value slot = JS_GetReservedSlot(obj, SLOT_TYPECODE); if (slot.isUndefined()) return; @@ -4057,7 +4057,7 @@ void CType::Trace(JSTracer* trc, JSObject* obj) { // Make sure our TypeCode slot is legit. If it's not, bail. - jsval slot = obj->as().getSlot(SLOT_TYPECODE); + Value slot = obj->as().getSlot(SLOT_TYPECODE); if (slot.isUndefined()) return; @@ -4112,7 +4112,7 @@ CType::GetTypeCode(JSObject* typeObj) { MOZ_ASSERT(IsCType(typeObj)); - jsval result = JS_GetReservedSlot(typeObj, SLOT_TYPECODE); + Value result = JS_GetReservedSlot(typeObj, SLOT_TYPECODE); return TypeCode(result.toInt32()); } @@ -4190,7 +4190,7 @@ CType::GetSafeSize(JSObject* obj, size_t* result) { MOZ_ASSERT(CType::IsCType(obj)); - jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); + Value size = JS_GetReservedSlot(obj, SLOT_SIZE); // The "size" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. @@ -4212,7 +4212,7 @@ CType::GetSize(JSObject* obj) { MOZ_ASSERT(CType::IsCType(obj)); - jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); + Value size = JS_GetReservedSlot(obj, SLOT_SIZE); MOZ_ASSERT(!size.isUndefined()); @@ -4230,7 +4230,7 @@ CType::IsSizeDefined(JSObject* obj) { MOZ_ASSERT(CType::IsCType(obj)); - jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); + Value size = JS_GetReservedSlot(obj, SLOT_SIZE); // The "size" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. @@ -4243,7 +4243,7 @@ CType::GetAlignment(JSObject* obj) { MOZ_ASSERT(CType::IsCType(obj)); - jsval slot = JS_GetReservedSlot(obj, SLOT_ALIGN); + Value slot = JS_GetReservedSlot(obj, SLOT_ALIGN); return static_cast(slot.toInt32()); } @@ -4252,7 +4252,7 @@ CType::GetFFIType(JSContext* cx, JSObject* obj) { MOZ_ASSERT(CType::IsCType(obj)); - jsval slot = JS_GetReservedSlot(obj, SLOT_FFITYPE); + Value slot = JS_GetReservedSlot(obj, SLOT_FFITYPE); if (!slot.isUndefined()) { return static_cast(slot.toPrivate()); @@ -4283,7 +4283,7 @@ CType::GetName(JSContext* cx, HandleObject obj) { MOZ_ASSERT(CType::IsCType(obj)); - jsval string = JS_GetReservedSlot(obj, SLOT_NAME); + Value string = JS_GetReservedSlot(obj, SLOT_NAME); if (!string.isUndefined()) return string.toString(); @@ -4300,13 +4300,13 @@ CType::GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot) { // Get ctypes.{Pointer,Array,Struct}Type.prototype from a reserved slot // on the type constructor. - jsval protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO); + Value protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO); JSObject* proto = &protoslot.toObject(); MOZ_ASSERT(proto); MOZ_ASSERT(CType::IsCTypeProto(proto)); // Get the desired prototype. - jsval result = JS_GetReservedSlot(proto, slot); + Value result = JS_GetReservedSlot(proto, slot); return &result.toObject(); } @@ -4324,7 +4324,7 @@ CType::GetProtoFromType(JSContext* cx, JSObject* objArg, CTypeProtoSlot slot) MOZ_ASSERT(CType::IsCTypeProto(proto)); // Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype. - jsval result = JS_GetReservedSlot(proto, slot); + Value result = JS_GetReservedSlot(proto, slot); MOZ_ASSERT(result.isObject()); return &result.toObject(); } @@ -4389,7 +4389,7 @@ CType::PtrGetter(JSContext* cx, JS::CallArgs args) } bool -CType::CreateArray(JSContext* cx, unsigned argc, jsval* vp) +CType::CreateArray(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject baseType(cx, JS_THIS_OBJECT(cx, vp)); @@ -4421,7 +4421,7 @@ CType::CreateArray(JSContext* cx, unsigned argc, jsval* vp) } bool -CType::ToString(JSContext* cx, unsigned argc, jsval* vp) +CType::ToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); @@ -4452,7 +4452,7 @@ CType::ToString(JSContext* cx, unsigned argc, jsval* vp) } bool -CType::ToSource(JSContext* cx, unsigned argc, jsval* vp) +CType::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -4486,7 +4486,7 @@ CType::HasInstance(JSContext* cx, HandleObject obj, MutableHandleValue v, bool* { MOZ_ASSERT(CType::IsCType(obj)); - jsval slot = JS_GetReservedSlot(obj, SLOT_PROTO); + Value slot = JS_GetReservedSlot(obj, SLOT_PROTO); JS::Rooted prototype(cx, &slot.toObject()); MOZ_ASSERT(prototype); MOZ_ASSERT(CData::IsCDataProto(prototype)); @@ -4521,7 +4521,7 @@ CType::GetGlobalCTypes(JSContext* cx, JSObject* objArg) MOZ_ASSERT(objTypeProto); MOZ_ASSERT(CType::IsCTypeProto(objTypeProto)); - jsval valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES); + Value valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES); MOZ_ASSERT(valCTypes.isObject()); return &valCTypes.toObject(); } @@ -4537,7 +4537,7 @@ ABI::IsABI(JSObject* obj) } bool -ABI::ToSource(JSContext* cx, unsigned argc, jsval* vp) +ABI::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -4580,7 +4580,7 @@ ABI::ToSource(JSContext* cx, unsigned argc, jsval* vp) *******************************************************************************/ bool -PointerType::Create(JSContext* cx, unsigned argc, jsval* vp) +PointerType::Create(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Construct and return a new PointerType object. @@ -4588,7 +4588,7 @@ PointerType::Create(JSContext* cx, unsigned argc, jsval* vp) return ArgumentLengthError(cx, "PointerType", "one", ""); } - jsval arg = args[0]; + Value arg = args[0]; RootedObject obj(cx); if (arg.isPrimitive() || !CType::IsCType(obj = &arg.toObject())) { return ArgumentTypeMismatch(cx, "", "PointerType", "a CType"); @@ -4606,7 +4606,7 @@ JSObject* PointerType::CreateInternal(JSContext* cx, HandleObject baseType) { // check if we have a cached PointerType on our base CType. - jsval slot = JS_GetReservedSlot(baseType, SLOT_PTR); + Value slot = JS_GetReservedSlot(baseType, SLOT_PTR); if (!slot.isUndefined()) return &slot.toObject(); @@ -4724,7 +4724,7 @@ PointerType::GetBaseType(JSObject* obj) { MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_pointer); - jsval type = JS_GetReservedSlot(obj, SLOT_TARGET_T); + Value type = JS_GetReservedSlot(obj, SLOT_TARGET_T); MOZ_ASSERT(!type.isNull()); return &type.toObject(); } @@ -4757,7 +4757,7 @@ PointerType::TargetTypeGetter(JSContext* cx, JS::CallArgs args) } bool -PointerType::IsNull(JSContext* cx, unsigned argc, jsval* vp) +PointerType::IsNull(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -4817,14 +4817,14 @@ PointerType::OffsetBy(JSContext* cx, const CallArgs& args, int offset) } bool -PointerType::Increment(JSContext* cx, unsigned argc, jsval* vp) +PointerType::Increment(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return OffsetBy(cx, args, 1); } bool -PointerType::Decrement(JSContext* cx, unsigned argc, jsval* vp) +PointerType::Decrement(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return OffsetBy(cx, args, -1); @@ -4880,7 +4880,7 @@ PointerType::ContentsSetter(JSContext* cx, JS::CallArgs args) *******************************************************************************/ bool -ArrayType::Create(JSContext* cx, unsigned argc, jsval* vp) +ArrayType::Create(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Construct and return a new ArrayType object. @@ -5073,7 +5073,7 @@ ArrayType::GetBaseType(JSObject* obj) MOZ_ASSERT(CType::IsCType(obj)); MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array); - jsval type = JS_GetReservedSlot(obj, SLOT_ELEMENT_T); + Value type = JS_GetReservedSlot(obj, SLOT_ELEMENT_T); MOZ_ASSERT(!type.isNull()); return &type.toObject(); } @@ -5084,7 +5084,7 @@ ArrayType::GetSafeLength(JSObject* obj, size_t* result) MOZ_ASSERT(CType::IsCType(obj)); MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array); - jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH); + Value length = JS_GetReservedSlot(obj, SLOT_LENGTH); // The "length" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. @@ -5107,7 +5107,7 @@ ArrayType::GetLength(JSObject* obj) MOZ_ASSERT(CType::IsCType(obj)); MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array); - jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH); + Value length = JS_GetReservedSlot(obj, SLOT_LENGTH); MOZ_ASSERT(!length.isUndefined()); @@ -5290,7 +5290,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle } bool -ArrayType::AddressOfElement(JSContext* cx, unsigned argc, jsval* vp) +ArrayType::AddressOfElement(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); @@ -5347,7 +5347,7 @@ ArrayType::AddressOfElement(JSContext* cx, unsigned argc, jsval* vp) // For a struct field descriptor 'val' of the form { name : type }, extract // 'name' and 'type'. static JSFlatString* -ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj) +ExtractStructField(JSContext* cx, Value val, MutableHandleObject typeObj) { if (val.isPrimitive()) { JS_ReportError(cx, "struct field descriptors require a valid name and type"); @@ -5423,7 +5423,7 @@ AddFieldToArray(JSContext* cx, } bool -StructType::Create(JSContext* cx, unsigned argc, jsval* vp) +StructType::Create(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -5432,7 +5432,7 @@ StructType::Create(JSContext* cx, unsigned argc, jsval* vp) return ArgumentLengthError(cx, "StructType", "one or two", "s"); } - jsval name = args[0]; + Value name = args[0]; if (!name.isString()) { return ArgumentTypeMismatch(cx, "first ", "StructType", "a string"); } @@ -5717,7 +5717,7 @@ StructType::BuildFFIType(JSContext* cx, JSObject* obj) } bool -StructType::Define(JSContext* cx, unsigned argc, jsval* vp) +StructType::Define(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); @@ -5738,7 +5738,7 @@ StructType::Define(JSContext* cx, unsigned argc, jsval* vp) return ArgumentLengthError(cx, "StructType.prototype.define", "one", ""); } - jsval arg = args[0]; + Value arg = args[0]; if (arg.isPrimitive()) { return ArgumentTypeMismatch(cx, "", "StructType.prototype.define", "an array"); @@ -5838,7 +5838,7 @@ StructType::GetFieldInfo(JSObject* obj) MOZ_ASSERT(CType::IsCType(obj)); MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_struct); - jsval slot = JS_GetReservedSlot(obj, SLOT_FIELDINFO); + Value slot = JS_GetReservedSlot(obj, SLOT_FIELDINFO); MOZ_ASSERT(!slot.isUndefined() && slot.toPrivate()); return static_cast(slot.toPrivate()); @@ -6007,7 +6007,7 @@ StructType::FieldSetter(JSContext* cx, unsigned argc, Value* vp) } bool -StructType::AddressOfField(JSContext* cx, unsigned argc, jsval* vp) +StructType::AddressOfField(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); @@ -6088,7 +6088,7 @@ struct AutoValue }; static bool -GetABI(JSContext* cx, jsval abiType, ffi_abi* result) +GetABI(JSContext* cx, Value abiType, ffi_abi* result) { if (abiType.isPrimitive()) return false; @@ -6120,7 +6120,7 @@ GetABI(JSContext* cx, jsval abiType, ffi_abi* result) } static JSObject* -PrepareType(JSContext* cx, jsval type) +PrepareType(JSContext* cx, Value type) { if (type.isPrimitive() || !CType::IsCType(type.toObjectOrNull())) { JS_ReportError(cx, "not a ctypes type"); @@ -6156,7 +6156,7 @@ PrepareType(JSContext* cx, jsval type) } static JSObject* -PrepareReturnType(JSContext* cx, jsval type) +PrepareReturnType(JSContext* cx, Value type) { if (type.isPrimitive() || !CType::IsCType(type.toObjectOrNull())) { JS_ReportError(cx, "not a ctypes type"); @@ -6184,7 +6184,7 @@ PrepareReturnType(JSContext* cx, jsval type) } static MOZ_ALWAYS_INLINE bool -IsEllipsis(JSContext* cx, jsval v, bool* isEllipsis) +IsEllipsis(JSContext* cx, Value v, bool* isEllipsis) { *isEllipsis = false; if (!v.isString()) @@ -6365,7 +6365,7 @@ CreateFunctionInfo(JSContext* cx, } bool -FunctionType::Create(JSContext* cx, unsigned argc, jsval* vp) +FunctionType::Create(JSContext* cx, unsigned argc, Value* vp) { // Construct and return a new FunctionType object. CallArgs args = CallArgsFromVp(argc, vp); @@ -6377,7 +6377,7 @@ FunctionType::Create(JSContext* cx, unsigned argc, jsval* vp) RootedObject arrayObj(cx, nullptr); if (args.length() == 3) { - // Prepare an array of jsvals for the arguments. + // Prepare an array of Values for the arguments. if (args[2].isObject()) arrayObj = &args[2].toObject(); if (!arrayObj || !JS_IsArrayObject(cx, arrayObj)) { @@ -6451,7 +6451,7 @@ FunctionType::ConstructData(JSContext* cx, HandleObject dataObj, HandleObject fnObj, HandleObject thisObj, - jsval errVal) + Value errVal) { MOZ_ASSERT(CType::GetTypeCode(typeObj) == TYPE_function); @@ -6522,7 +6522,7 @@ ConvertArgument(JSContext* cx, bool FunctionType::Call(JSContext* cx, unsigned argc, - jsval* vp) + Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // get the callee object... @@ -6554,7 +6554,7 @@ FunctionType::Call(JSContext* cx, } // Check if we have a Library object. If we do, make sure it's open. - jsval slot = JS_GetReservedSlot(obj, SLOT_REFERENT); + Value slot = JS_GetReservedSlot(obj, SLOT_REFERENT); if (!slot.isUndefined() && Library::IsLibrary(&slot.toObject())) { PRLibrary* library = Library::GetLibrary(&slot.toObject()); if (!library) { @@ -6691,7 +6691,7 @@ FunctionType::GetFunctionInfo(JSObject* obj) MOZ_ASSERT(CType::IsCType(obj)); MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_function); - jsval slot = JS_GetReservedSlot(obj, SLOT_FNINFO); + Value slot = JS_GetReservedSlot(obj, SLOT_FNINFO); MOZ_ASSERT(!slot.isUndefined() && slot.toPrivate()); return static_cast(slot.toPrivate()); @@ -6774,7 +6774,7 @@ CClosure::Create(JSContext* cx, HandleObject typeObj, HandleObject fnObj, HandleObject thisObj, - jsval errVal_, + Value errVal_, PRFuncPtr* fnptr) { RootedValue errVal(cx, errVal_); @@ -6868,7 +6868,7 @@ void CClosure::Trace(JSTracer* trc, JSObject* obj) { // Make sure our ClosureInfo slot is legit. If it's not, bail. - jsval slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO); + Value slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO); if (slot.isUndefined()) return; @@ -6886,7 +6886,7 @@ void CClosure::Finalize(JSFreeOp* fop, JSObject* obj) { // Make sure our ClosureInfo slot is legit. If it's not, bail. - jsval slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO); + Value slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO); if (slot.isUndefined()) return; @@ -7069,7 +7069,7 @@ CData::Create(JSContext* cx, MOZ_ASSERT_IF(refObj && CData::IsCData(refObj), !ownResult); // Get the 'prototype' property from the type. - jsval slot = JS_GetReservedSlot(typeObj, SLOT_PROTO); + Value slot = JS_GetReservedSlot(typeObj, SLOT_PROTO); MOZ_ASSERT(slot.isObject()); RootedObject proto(cx, &slot.toObject()); @@ -7126,7 +7126,7 @@ void CData::Finalize(JSFreeOp* fop, JSObject* obj) { // Delete our buffer, and the data it contains if we own it. - jsval slot = JS_GetReservedSlot(obj, SLOT_OWNS); + Value slot = JS_GetReservedSlot(obj, SLOT_OWNS); if (slot.isUndefined()) return; @@ -7147,7 +7147,7 @@ CData::GetCType(JSObject* dataObj) { MOZ_ASSERT(CData::IsCData(dataObj)); - jsval slot = JS_GetReservedSlot(dataObj, SLOT_CTYPE); + Value slot = JS_GetReservedSlot(dataObj, SLOT_CTYPE); JSObject* typeObj = slot.toObjectOrNull(); MOZ_ASSERT(CType::IsCType(typeObj)); return typeObj; @@ -7158,7 +7158,7 @@ CData::GetData(JSObject* dataObj) { MOZ_ASSERT(CData::IsCData(dataObj)); - jsval slot = JS_GetReservedSlot(dataObj, SLOT_DATA); + Value slot = JS_GetReservedSlot(dataObj, SLOT_DATA); void** buffer = static_cast(slot.toPrivate()); MOZ_ASSERT(buffer); @@ -7204,7 +7204,7 @@ CData::ValueSetter(JSContext* cx, JS::CallArgs args) } bool -CData::Address(JSContext* cx, unsigned argc, jsval* vp) +CData::Address(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -7238,7 +7238,7 @@ CData::Address(JSContext* cx, unsigned argc, jsval* vp) } bool -CData::Cast(JSContext* cx, unsigned argc, jsval* vp) +CData::Cast(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -7276,7 +7276,7 @@ CData::Cast(JSContext* cx, unsigned argc, jsval* vp) } bool -CData::GetRuntime(JSContext* cx, unsigned argc, jsval* vp) +CData::GetRuntime(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -7307,7 +7307,7 @@ CData::GetRuntime(JSContext* cx, unsigned argc, jsval* vp) typedef JS::TwoByteCharsZ (*InflateUTF8Method)(JSContext*, const JS::UTF8Chars, size_t*); static bool -ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc, jsval* vp) +ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -7394,13 +7394,13 @@ ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc, js } bool -CData::ReadString(JSContext* cx, unsigned argc, jsval* vp) +CData::ReadString(JSContext* cx, unsigned argc, Value* vp) { return ReadStringCommon(cx, JS::UTF8CharsToNewTwoByteCharsZ, argc, vp); } bool -CData::ReadStringReplaceMalformed(JSContext* cx, unsigned argc, jsval* vp) +CData::ReadStringReplaceMalformed(JSContext* cx, unsigned argc, Value* vp) { return ReadStringCommon(cx, JS::LossyUTF8CharsToNewTwoByteCharsZ, argc, vp); } @@ -7426,7 +7426,7 @@ CData::GetSourceString(JSContext* cx, HandleObject typeObj, void* data) } bool -CData::ToSource(JSContext* cx, unsigned argc, jsval* vp) +CData::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -7475,7 +7475,7 @@ CData::LastErrorGetter(JSContext* cx, JS::CallArgs args) #endif // defined(XP_WIN) bool -CDataFinalizer::Methods::ToSource(JSContext* cx, unsigned argc, jsval* vp) +CDataFinalizer::Methods::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject objThis(cx, JS_THIS_OBJECT(cx, vp)); @@ -7507,7 +7507,7 @@ CDataFinalizer::Methods::ToSource(JSContext* cx, unsigned argc, jsval* vp) } AppendString(source, srcValue); AppendString(source, ", "); - jsval valCodePtrType = JS_GetReservedSlot(objThis, + Value valCodePtrType = JS_GetReservedSlot(objThis, SLOT_DATAFINALIZER_CODETYPE); if (valCodePtrType.isPrimitive()) { return false; @@ -7534,7 +7534,7 @@ CDataFinalizer::Methods::ToSource(JSContext* cx, unsigned argc, jsval* vp) } bool -CDataFinalizer::Methods::ToString(JSContext* cx, unsigned argc, jsval* vp) +CDataFinalizer::Methods::ToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* objThis = JS_THIS_OBJECT(cx, vp); @@ -7578,7 +7578,7 @@ CDataFinalizer::GetCType(JSContext* cx, JSObject* obj) { MOZ_ASSERT(IsCDataFinalizer(obj)); - jsval valData = JS_GetReservedSlot(obj, + Value valData = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_VALTYPE); if (valData.isUndefined()) { return nullptr; @@ -7640,7 +7640,7 @@ CDataFinalizer::GetValue(JSContext* cx, JSObject* obj, MutableHandleValue aResul * CData functions are initialized during creation. */ bool -CDataFinalizer::Construct(JSContext* cx, unsigned argc, jsval* vp) +CDataFinalizer::Construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject objSelf(cx, &args.callee()); @@ -7868,7 +7868,7 @@ CDataFinalizer::CallFinalizer(CDataFinalizer::Private* p, * strong references. */ bool -CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, jsval* vp) +CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -7916,7 +7916,7 @@ CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, jsval* vp) * strong references. */ bool -CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval* vp) +CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -7940,14 +7940,14 @@ CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval* vp) return false; } - jsval valType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_VALTYPE); + Value valType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_VALTYPE); MOZ_ASSERT(valType.isObject()); JSObject* objCTypes = CType::GetGlobalCTypes(cx, &valType.toObject()); if (!objCTypes) return false; - jsval valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE); + Value valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE); MOZ_ASSERT(valCodePtrType.isObject()); JSObject* objCodePtrType = &valCodePtrType.toObject(); @@ -8072,7 +8072,7 @@ Int64Base::Construct(JSContext* cx, void Int64Base::Finalize(JSFreeOp* fop, JSObject* obj) { - jsval slot = JS_GetReservedSlot(obj, SLOT_INT64); + Value slot = JS_GetReservedSlot(obj, SLOT_INT64); if (slot.isUndefined()) return; @@ -8083,7 +8083,7 @@ uint64_t Int64Base::GetInt(JSObject* obj) { MOZ_ASSERT(Int64::IsInt64(obj) || UInt64::IsUInt64(obj)); - jsval slot = JS_GetReservedSlot(obj, SLOT_INT64); + Value slot = JS_GetReservedSlot(obj, SLOT_INT64); return *static_cast(slot.toPrivate()); } @@ -8104,7 +8104,7 @@ Int64Base::ToString(JSContext* cx, int radix = 10; if (args.length() == 1) { - jsval arg = args[0]; + Value arg = args[0]; if (arg.isInt32()) radix = arg.toInt32(); if (!arg.isInt32() || radix < 2 || radix > 36) { @@ -8165,7 +8165,7 @@ Int64Base::ToSource(JSContext* cx, bool Int64::Construct(JSContext* cx, unsigned argc, - jsval* vp) + Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -8201,7 +8201,7 @@ Int64::IsInt64(JSObject* obj) } bool -Int64::ToString(JSContext* cx, unsigned argc, jsval* vp) +Int64::ToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -8216,7 +8216,7 @@ Int64::ToString(JSContext* cx, unsigned argc, jsval* vp) } bool -Int64::ToSource(JSContext* cx, unsigned argc, jsval* vp) +Int64::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -8231,7 +8231,7 @@ Int64::ToSource(JSContext* cx, unsigned argc, jsval* vp) } bool -Int64::Compare(JSContext* cx, unsigned argc, jsval* vp) +Int64::Compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -8265,7 +8265,7 @@ Int64::Compare(JSContext* cx, unsigned argc, jsval* vp) #define INT64_HI(i) ((i) >> 32) bool -Int64::Lo(JSContext* cx, unsigned argc, jsval* vp) +Int64::Lo(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -8284,7 +8284,7 @@ Int64::Lo(JSContext* cx, unsigned argc, jsval* vp) } bool -Int64::Hi(JSContext* cx, unsigned argc, jsval* vp) +Int64::Hi(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -8303,7 +8303,7 @@ Int64::Hi(JSContext* cx, unsigned argc, jsval* vp) } bool -Int64::Join(JSContext* cx, unsigned argc, jsval* vp) +Int64::Join(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -8322,7 +8322,7 @@ Int64::Join(JSContext* cx, unsigned argc, jsval* vp) // Get Int64.prototype from the function's reserved slot. JSObject* callee = &args.callee(); - jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO); + Value slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO); RootedObject proto(cx, &slot.toObject()); MOZ_ASSERT(JS_GetClass(proto) == &sInt64ProtoClass); @@ -8337,7 +8337,7 @@ Int64::Join(JSContext* cx, unsigned argc, jsval* vp) bool UInt64::Construct(JSContext* cx, unsigned argc, - jsval* vp) + Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -8373,7 +8373,7 @@ UInt64::IsUInt64(JSObject* obj) } bool -UInt64::ToString(JSContext* cx, unsigned argc, jsval* vp) +UInt64::ToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -8388,7 +8388,7 @@ UInt64::ToString(JSContext* cx, unsigned argc, jsval* vp) } bool -UInt64::ToSource(JSContext* cx, unsigned argc, jsval* vp) +UInt64::ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -8403,7 +8403,7 @@ UInt64::ToSource(JSContext* cx, unsigned argc, jsval* vp) } bool -UInt64::Compare(JSContext* cx, unsigned argc, jsval* vp) +UInt64::Compare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -8433,7 +8433,7 @@ UInt64::Compare(JSContext* cx, unsigned argc, jsval* vp) } bool -UInt64::Lo(JSContext* cx, unsigned argc, jsval* vp) +UInt64::Lo(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -8452,7 +8452,7 @@ UInt64::Lo(JSContext* cx, unsigned argc, jsval* vp) } bool -UInt64::Hi(JSContext* cx, unsigned argc, jsval* vp) +UInt64::Hi(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -8471,7 +8471,7 @@ UInt64::Hi(JSContext* cx, unsigned argc, jsval* vp) } bool -UInt64::Join(JSContext* cx, unsigned argc, jsval* vp) +UInt64::Join(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 2) { @@ -8490,7 +8490,7 @@ UInt64::Join(JSContext* cx, unsigned argc, jsval* vp) // Get UInt64.prototype from the function's reserved slot. JSObject* callee = &args.callee(); - jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO); + Value slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO); RootedObject proto(cx, &slot.toObject()); MOZ_ASSERT(JS_GetClass(proto) == &sUInt64ProtoClass); diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index 01b0e79e51f8..280cceb39c03 100644 --- a/js/src/ctypes/CTypes.h +++ b/js/src/ctypes/CTypes.h @@ -294,7 +294,7 @@ struct FunctionInfo ffi_cif mCIF; // Calling convention of the function. Convert to ffi_abi using GetABI - // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing. + // and ObjectValue. Stored as a JSObject* for ease of tracing. JS::Heap mABI; // The CType of the value returned by the function. @@ -351,8 +351,8 @@ const JSCTypesCallbacks* GetCallbacks(JSObject* obj); enum CTypesGlobalSlot { SLOT_CALLBACKS = 0, // pointer to JSCTypesCallbacks struct - SLOT_ERRNO = 1, // jsval for latest |errno| - SLOT_LASTERROR = 2, // jsval for latest |GetLastError|, used only with Windows + SLOT_ERRNO = 1, // Value for latest |errno| + SLOT_LASTERROR = 2, // Value for latest |GetLastError|, used only with Windows CTYPESGLOBAL_SLOTS }; @@ -402,7 +402,7 @@ enum CDataSlot { SLOT_CTYPE = 0, // CType object representing the underlying type SLOT_REFERENT = 1, // JSObject this object must keep alive, if any SLOT_DATA = 2, // pointer to a buffer containing the binary data - SLOT_OWNS = 3, // JSVAL_TRUE if this CData owns its own buffer + SLOT_OWNS = 3, // TrueValue() if this CData owns its own buffer SLOT_FUNNAME = 4, // JSString representing the function name CDATA_SLOTS }; @@ -443,11 +443,11 @@ enum Int64FunctionSlot { namespace CType { JSObject* Create(JSContext* cx, HandleObject typeProto, HandleObject dataProto, - TypeCode type, JSString* name, jsval size, jsval align, ffi_type* ffiType); + TypeCode type, JSString* name, Value size, Value align, ffi_type* ffiType); JSObject* DefineBuiltin(JSContext* cx, HandleObject ctypesObj, const char* propName, JSObject* typeProto, JSObject* dataProto, const char* name, TypeCode type, - jsval size, jsval align, ffi_type* ffiType); + Value size, Value align, ffi_type* ffiType); bool IsCType(JSObject* obj); bool IsCTypeProto(JSObject* obj); @@ -505,7 +505,7 @@ namespace FunctionType { namespace CClosure { JSObject* Create(JSContext* cx, HandleObject typeObj, HandleObject fnObj, - HandleObject thisObj, jsval errVal, PRFuncPtr* fnptr); + HandleObject thisObj, Value errVal, PRFuncPtr* fnptr); } // namespace CClosure namespace CData { @@ -519,9 +519,9 @@ namespace CData { bool IsCDataProto(JSObject* obj); // Attached by JSAPI as the function 'ctypes.cast' - bool Cast(JSContext* cx, unsigned argc, jsval* vp); + bool Cast(JSContext* cx, unsigned argc, Value* vp); // Attached by JSAPI as the function 'ctypes.getRuntime' - bool GetRuntime(JSContext* cx, unsigned argc, jsval* vp); + bool GetRuntime(JSContext* cx, unsigned argc, Value* vp); } // namespace CData namespace Int64 { diff --git a/js/src/ctypes/Library.cpp b/js/src/ctypes/Library.cpp index 3578b2feffc5..19895d8b6ff3 100644 --- a/js/src/ctypes/Library.cpp +++ b/js/src/ctypes/Library.cpp @@ -22,8 +22,8 @@ namespace Library { static void Finalize(JSFreeOp* fop, JSObject* obj); - static bool Close(JSContext* cx, unsigned argc, jsval* vp); - static bool Declare(JSContext* cx, unsigned argc, jsval* vp); + static bool Close(JSContext* cx, unsigned argc, Value* vp); + static bool Declare(JSContext* cx, unsigned argc, Value* vp); } // namespace Library /******************************************************************************* @@ -49,7 +49,7 @@ static const JSFunctionSpec sLibraryFunctions[] = { }; bool -Library::Name(JSContext* cx, unsigned argc, jsval* vp) +Library::Name(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -81,7 +81,7 @@ Library::Name(JSContext* cx, unsigned argc, jsval* vp) } JSObject* -Library::Create(JSContext* cx, jsval path_, const JSCTypesCallbacks* callbacks) +Library::Create(JSContext* cx, Value path_, const JSCTypesCallbacks* callbacks) { RootedValue path(cx, path_); RootedObject libraryObj(cx, JS_NewObject(cx, &sLibraryClass)); @@ -182,7 +182,7 @@ Library::GetLibrary(JSObject* obj) { MOZ_ASSERT(IsLibrary(obj)); - jsval slot = JS_GetReservedSlot(obj, SLOT_LIBRARY); + Value slot = JS_GetReservedSlot(obj, SLOT_LIBRARY); return static_cast(slot.toPrivate()); } @@ -201,7 +201,7 @@ Library::Finalize(JSFreeOp* fop, JSObject* obj) } bool -Library::Open(JSContext* cx, unsigned argc, jsval* vp) +Library::Open(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* ctypesObj = JS_THIS_OBJECT(cx, vp); @@ -226,7 +226,7 @@ Library::Open(JSContext* cx, unsigned argc, jsval* vp) } bool -Library::Close(JSContext* cx, unsigned argc, jsval* vp) +Library::Close(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSObject* obj = JS_THIS_OBJECT(cx, vp); @@ -251,7 +251,7 @@ Library::Close(JSContext* cx, unsigned argc, jsval* vp) } bool -Library::Declare(JSContext* cx, unsigned argc, jsval* vp) +Library::Declare(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 38d63c097762..2da448fcee2b 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -448,13 +448,12 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco // scope dynamically via JSOP_DEFFUN/VAR). They may have block-scoped // locals, however, which are allocated to the fixed part of the stack // frame. - Rooted bindings(cx, script->bindings); - if (!Bindings::initWithTemporaryStorage(cx, &bindings, 0, 0, 0, + InternalHandle bindings(script, &script->bindings); + if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, 0, pc->blockScopeDepth, 0, 0, nullptr)) { return nullptr; } - script->bindings = bindings; if (!JSScript::fullyInitFromEmitter(cx, script, &bce)) return nullptr; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 35fc03faf7ee..0333248945de 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -3414,7 +3414,8 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body) switchToPrologue(); if (!emit1(JSOP_ARGUMENTS)) return false; - BindingIter bi = Bindings::argumentsBinding(cx, script); + InternalBindingsHandle bindings(script, &script->bindings); + BindingIter bi = Bindings::argumentsBinding(cx, bindings); if (script->bindingIsAliased(bi)) { ScopeCoordinate sc; sc.setHops(0); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 7d38c4f21e59..d56fdf2adf98 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -371,7 +371,7 @@ template bool ParseContext::generateFunctionBindings(ExclusiveContext* cx, TokenStream& ts, LifoAlloc& alloc, - MutableHandle bindings) const + InternalHandle bindings) const { MOZ_ASSERT(sc->isFunctionBox()); MOZ_ASSERT(args_.length() < ARGNO_LIMIT); @@ -847,10 +847,10 @@ Parser::standaloneFunctionBody(HandleFunction fun, const AutoN } } - Rooted bindings(context, funbox->bindings); - if (!funpc.generateFunctionBindings(context, tokenStream, alloc, &bindings)) + InternalHandle funboxBindings = + InternalHandle::fromMarkedLocation(&funbox->bindings); + if (!funpc.generateFunctionBindings(context, tokenStream, alloc, funboxBindings)) return null(); - funbox->bindings = bindings; return fn; } @@ -1470,12 +1470,9 @@ Parser::leaveFunction(ParseNode* fn, ParseContext bindings(context, funbox->bindings); - if (!pc->generateFunctionBindings(context, tokenStream, alloc, &bindings)) - return false; - funbox->bindings = bindings; - - return true; + InternalHandle bindings = + InternalHandle::fromMarkedLocation(&funbox->bindings); + return pc->generateFunctionBindings(context, tokenStream, alloc, bindings); } template <> @@ -2495,10 +2492,10 @@ Parser::standaloneLazyFunction(HandleFunction fun, unsigned st } } - Rooted bindings(context, funbox->bindings); - if (!pc->generateFunctionBindings(context, tokenStream, alloc, &bindings)) + InternalHandle bindings = + InternalHandle::fromMarkedLocation(&funbox->bindings); + if (!pc->generateFunctionBindings(context, tokenStream, alloc, bindings)) return null(); - funbox->bindings = bindings; if (!FoldConstants(context, &pn, this)) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 9e5dff90a633..12236772bb4e 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -213,7 +213,7 @@ struct ParseContext : public GenericParseContext */ bool generateFunctionBindings(ExclusiveContext* cx, TokenStream& ts, LifoAlloc& alloc, - MutableHandle bindings) const; + InternalHandle bindings) const; private: ParseContext** parserPC; /* this points to the Parser's active pc diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 4b87262a7908..0ec78eb358ea 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -237,6 +237,8 @@ struct InternalGCMethods { static bool isMarkable(T* v) { return v != nullptr; } + static bool isMarkableTaggedPointer(T* v) { return !IsNullTaggedPointer(v); } + static void preBarrier(T* v) { T::writeBarrierPre(v); } static void postBarrier(T** vp, T* prev, T* next) { T::writeBarrierPost(vp, prev, next); } @@ -256,6 +258,7 @@ template <> struct InternalGCMethods { static bool isMarkable(Value v) { return v.isMarkable(); } + static bool isMarkableTaggedPointer(Value v) { return isMarkable(v); } static void preBarrier(Value v) { DispatchValueTyped(PreBarrierFunctor(), v); @@ -291,6 +294,7 @@ template <> struct InternalGCMethods { static bool isMarkable(jsid id) { return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id); } + static bool isMarkableTaggedPointer(jsid id) { return isMarkable(id); } static void preBarrier(jsid id) { DispatchIdTyped(PreBarrierFunctor(), id); } static void postBarrier(jsid* idp, jsid prev, jsid next) {} diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 98514d480a5f..71ad5d2b4adc 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -449,6 +449,15 @@ js::TraceRoot(JSTracer* trc, T* thingp, const char* name) DispatchToTracer(trc, ConvertToBase(thingp), name); } +template +void +js::TraceNullableRoot(JSTracer* trc, T* thingp, const char* name) +{ + AssertRootMarkingPhase(trc); + if (InternalGCMethods::isMarkableTaggedPointer(*thingp)) + DispatchToTracer(trc, ConvertToBase(thingp), name); +} + template void js::TraceRange(JSTracer* trc, size_t len, BarrieredBase* vec, const char* name) @@ -479,6 +488,7 @@ js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) template void js::TraceEdge(JSTracer*, BarrieredBase*, const char*); \ template void js::TraceManuallyBarrieredEdge(JSTracer*, type*, const char*); \ template void js::TraceRoot(JSTracer*, type*, const char*); \ + template void js::TraceNullableRoot(JSTracer*, type*, const char*); \ template void js::TraceRange(JSTracer*, size_t, BarrieredBase*, const char*); \ template void js::TraceRootRange(JSTracer*, size_t, type*, const char*); FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS) diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index bdd928ff58bb..0016eacf61f6 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -44,42 +44,29 @@ typedef RootedValueMap::Enum RootEnum; // GCC 4.4, since it requires template function parameters to have external // linkage. +void +MarkBindingsRoot(JSTracer* trc, Bindings* bindings, const char* name) +{ + bindings->trace(trc); +} + void MarkPropertyDescriptorRoot(JSTracer* trc, JSPropertyDescriptor* pd, const char* name) { pd->trace(trc); } -template -static inline bool -IgnoreExactRoot(T* thingp) -{ - return false; -} +template +using TraceFunction = void (*)(JSTracer* trc, T* ref, const char* name); -template -inline bool -IgnoreExactRoot(T** thingp) -{ - return IsNullTaggedPointer(*thingp); -} - -template <> -inline bool -IgnoreExactRoot(JSObject** thingp) -{ - return IsNullTaggedPointer(*thingp) || *thingp == TaggedProto::LazyProto; -} - -template +template TraceFn = TraceNullableRoot, class Source> static inline void MarkExactStackRootList(JSTracer* trc, Source* s, const char* name) { Rooted* rooter = s->roots.template gcRooters(); while (rooter) { T* addr = rooter->address(); - if (!IgnoreExactRoot(addr)) - MarkFunc(trc, addr, name); + TraceFn(trc, addr, name); rooter = rooter->previous(); } } @@ -88,18 +75,19 @@ template static void MarkExactStackRootsAcrossTypes(T context, JSTracer* trc) { - MarkExactStackRootList(trc, context, "exact-object"); - MarkExactStackRootList(trc, context, "exact-shape"); - MarkExactStackRootList(trc, context, "exact-baseshape"); - MarkExactStackRootList( + MarkExactStackRootList(trc, context, "exact-object"); + MarkExactStackRootList(trc, context, "exact-shape"); + MarkExactStackRootList(trc, context, "exact-baseshape"); + MarkExactStackRootList( trc, context, "exact-objectgroup"); - MarkExactStackRootList(trc, context, "exact-string"); - MarkExactStackRootList(trc, context, "exact-symbol"); - MarkExactStackRootList(trc, context, "exact-jitcode"); - MarkExactStackRootList(trc, context, "exact-script"); - MarkExactStackRootList(trc, context, "exact-lazy-script"); - MarkExactStackRootList(trc, context, "exact-id"); - MarkExactStackRootList(trc, context, "exact-value"); + MarkExactStackRootList(trc, context, "exact-string"); + MarkExactStackRootList(trc, context, "exact-symbol"); + MarkExactStackRootList(trc, context, "exact-jitcode"); + MarkExactStackRootList(trc, context, "exact-script"); + MarkExactStackRootList(trc, context, "exact-lazy-script"); + MarkExactStackRootList(trc, context, "exact-id"); + MarkExactStackRootList(trc, context, "exact-value"); + MarkExactStackRootList(trc, context, "Bindings"); MarkExactStackRootList( trc, context, "JSPropertyDescriptor"); MarkExactStackRootList List; typedef void (*MarkFunc)(JSTracer* trc, T* ref, const char* name); - static void - markChainIfNotNull(JSTracer* trc, List& list, const char* name) - { - for (Element* r = list.getFirst(); r; r = r->getNext()) { - if (r->get()) - TraceRoot(trc, r->address(), name); - } - } - static void markChain(JSTracer* trc, List& list, const char* name) { for (Element* r = list.getFirst(); r; r = r->getNext()) - TraceRoot(trc, r->address(), name); + TraceNullableRoot(trc, r->address(), name); } }; @@ -358,17 +337,14 @@ js::gc::MarkPersistentRootedChains(JSTracer* trc) { JSRuntime* rt = trc->runtime(); - // Mark the PersistentRooted chains of types that may be null. - PersistentRootedMarker::markChainIfNotNull(trc, rt->functionPersistentRooteds, - "PersistentRooted"); - PersistentRootedMarker::markChainIfNotNull(trc, rt->objectPersistentRooteds, - "PersistentRooted"); - PersistentRootedMarker::markChainIfNotNull(trc, rt->scriptPersistentRooteds, - "PersistentRooted"); - PersistentRootedMarker::markChainIfNotNull(trc, rt->stringPersistentRooteds, - "PersistentRooted"); - - // Mark the PersistentRooted chains of types that are never null. + PersistentRootedMarker::markChain(trc, rt->functionPersistentRooteds, + "PersistentRooted"); + PersistentRootedMarker::markChain(trc, rt->objectPersistentRooteds, + "PersistentRooted"); + PersistentRootedMarker::markChain(trc, rt->scriptPersistentRooteds, + "PersistentRooted"); + PersistentRootedMarker::markChain(trc, rt->stringPersistentRooteds, + "PersistentRooted"); PersistentRootedMarker::markChain(trc, rt->idPersistentRooteds, "PersistentRooted"); PersistentRootedMarker::markChain(trc, rt->valuePersistentRooteds, diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index b81b790072d8..7d1fd0ca0155 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -62,6 +62,12 @@ template void TraceRoot(JSTracer* trc, T* thingp, const char* name); +// Idential to TraceRoot, except that this variant will not crash if |*thingp| +// is null. +template +void +TraceNullableRoot(JSTracer* trc, T* thingp, const char* name); + // Like TraceEdge, but for edges that do not use one of the automatic barrier // classes and, thus, must be treated specially for moving GC. This method is // separate from TraceEdge to make accidental use of such edges more obvious. diff --git a/js/src/gdb/tests/test-Root.cpp b/js/src/gdb/tests/test-Root.cpp index e067a0bea0a8..82cfb2581dec 100644 --- a/js/src/gdb/tests/test-Root.cpp +++ b/js/src/gdb/tests/test-Root.cpp @@ -28,7 +28,7 @@ FRAGMENT(Root, handle) { } FRAGMENT(Root, HeapSlot) { - JS::Rooted plinth(cx, JS::StringValue(JS_NewStringCopyZ(cx, "plinth"))); + JS::Rooted plinth(cx, JS::StringValue(JS_NewStringCopyZ(cx, "plinth"))); JS::Rooted array(cx, JS_NewArrayObject(cx, JS::HandleValueArray(plinth))); breakpoint(); diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index ca09cf01ce2d..810552a741b2 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -3314,6 +3314,34 @@ BaselineCompiler::emit_JSOP_TOID() return true; } +typedef JSString* (*ToStringFn)(JSContext*, HandleValue); +static const VMFunction ToStringInfo = FunctionInfo(ToStringSlow); + +bool +BaselineCompiler::emit_JSOP_TOSTRING() +{ + // Keep top stack value in R0. + frame.popRegsAndSync(1); + + // Inline path for string. + Label done; + masm.branchTestString(Assembler::Equal, R0, &done); + + prepareVMCall(); + + pushArg(R0); + + // Call ToStringSlow which doesn't handle string inputs. + if (!callVM(ToStringInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_STRING, ReturnReg, R0); + + masm.bind(&done); + frame.push(R0); + return true; +} + bool BaselineCompiler::emit_JSOP_TABLESWITCH() { diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index b13a74e4ce5b..c9da772f032d 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -183,6 +183,7 @@ namespace jit { _(JSOP_RUNONCE) \ _(JSOP_REST) \ _(JSOP_TOID) \ + _(JSOP_TOSTRING) \ _(JSOP_TABLESWITCH) \ _(JSOP_ITER) \ _(JSOP_MOREITER) \ diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 08f8f0c249a8..ef5012665b8a 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -24,7 +24,7 @@ namespace jit { static Register CallReg = ip; static const int defaultShift = 3; -JS_STATIC_ASSERT(1 << defaultShift == sizeof(jsval)); +JS_STATIC_ASSERT(1 << defaultShift == sizeof(JS::Value)); // MacroAssemblerARM is inheriting form Assembler defined in // Assembler-arm.{h,cpp} diff --git a/js/src/jit/mips/MacroAssembler-mips.h b/js/src/jit/mips/MacroAssembler-mips.h index e98c513df44f..465bffe6375b 100644 --- a/js/src/jit/mips/MacroAssembler-mips.h +++ b/js/src/jit/mips/MacroAssembler-mips.h @@ -63,7 +63,7 @@ static const ValueOperand softfpReturnOperand = ValueOperand(v1, v0); static Register CallReg = t9; static const int defaultShift = 3; -static_assert(1 << defaultShift == sizeof(jsval), "The defaultShift is wrong"); +static_assert(1 << defaultShift == sizeof(JS::Value), "The defaultShift is wrong"); class MacroAssemblerMIPS : public Assembler { diff --git a/js/src/jsapi-tests/testChromeBuffer.cpp b/js/src/jsapi-tests/testChromeBuffer.cpp index 43f29c548296..c425e155f9b1 100644 --- a/js/src/jsapi-tests/testChromeBuffer.cpp +++ b/js/src/jsapi-tests/testChromeBuffer.cpp @@ -30,7 +30,7 @@ static JS::PersistentRootedObject trusted_glob; static JS::PersistentRootedObject trusted_fun; static bool -CallTrusted(JSContext* cx, unsigned argc, jsval* vp) +CallTrusted(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); diff --git a/js/src/jsapi-tests/testClassGetter.cpp b/js/src/jsapi-tests/testClassGetter.cpp index b94feebd9fc7..ef21848a8803 100644 --- a/js/src/jsapi-tests/testClassGetter.cpp +++ b/js/src/jsapi-tests/testClassGetter.cpp @@ -19,7 +19,7 @@ static bool test_prop_get( JSContext* cx, JS::HandleObject obj, JS::HandleId id, } static bool -PTest(JSContext* cx, unsigned argc, jsval* vp); +PTest(JSContext* cx, unsigned argc, JS::Value* vp); static const JSClass ptestClass = { "PTest", @@ -31,7 +31,7 @@ static const JSClass ptestClass = { }; static bool -PTest(JSContext* cx, unsigned argc, jsval* vp) +PTest(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JSObject* obj = JS_NewObjectForConstructor(cx, &ptestClass, args); @@ -40,7 +40,7 @@ PTest(JSContext* cx, unsigned argc, jsval* vp) args.rval().setObject(*obj); return true; } -static bool test_fn(JSContext* cx, unsigned argc, jsval* vp) +static bool test_fn(JSContext* cx, unsigned argc, JS::Value* vp) { called_test_fn++; return true; diff --git a/js/src/jsapi-tests/testContexts.cpp b/js/src/jsapi-tests/testContexts.cpp index 86852b69714d..f9d5c4e14345 100644 --- a/js/src/jsapi-tests/testContexts.cpp +++ b/js/src/jsapi-tests/testContexts.cpp @@ -13,7 +13,7 @@ BEGIN_TEST(testContexts_IsRunning) return true; } - static bool chk(JSContext* cx, unsigned argc, jsval* vp) + static bool chk(JSContext* cx, unsigned argc, JS::Value* vp) { JSRuntime* rt = JS_GetRuntime(cx); JSContext* acx = JS_NewContext(rt, 8192); diff --git a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp index adf2bffc41b2..2c82725fc984 100644 --- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp +++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp @@ -8,7 +8,7 @@ #include "jsapi-tests/tests.h" static bool -NativeGetterSetter(JSContext* cx, unsigned argc, jsval* vp) +NativeGetterSetter(JSContext* cx, unsigned argc, JS::Value* vp) { return true; } diff --git a/js/src/jsapi-tests/testNewObject.cpp b/js/src/jsapi-tests/testNewObject.cpp index 3178140f4798..3a7e6e2f5b01 100644 --- a/js/src/jsapi-tests/testNewObject.cpp +++ b/js/src/jsapi-tests/testNewObject.cpp @@ -8,7 +8,7 @@ #include "jsapi-tests/tests.h" static bool -constructHook(JSContext* cx, unsigned argc, jsval* vp) +constructHook(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = CallArgsFromVp(argc, vp); diff --git a/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp b/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp index 8ba4b4b634a5..6d0e7979c31f 100644 --- a/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp +++ b/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp @@ -10,7 +10,7 @@ static const JSClass ObjectEmulatingUndefinedClass = { }; static bool -ObjectEmulatingUndefinedConstructor(JSContext* cx, unsigned argc, jsval* vp) +ObjectEmulatingUndefinedConstructor(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JSObject* obj = JS_NewObjectForConstructor(cx, &ObjectEmulatingUndefinedClass, args); diff --git a/js/src/jsapi-tests/testOps.cpp b/js/src/jsapi-tests/testOps.cpp index 1cd34cac6e5c..dd48076f7ce9 100644 --- a/js/src/jsapi-tests/testOps.cpp +++ b/js/src/jsapi-tests/testOps.cpp @@ -27,7 +27,7 @@ static const JSClass myClass = { }; static bool -createMyObject(JSContext* context, unsigned argc, jsval* vp) +createMyObject(JSContext* context, unsigned argc, JS::Value* vp) { JS_BeginRequest(context); diff --git a/js/src/jsapi-tests/testParseJSON.cpp b/js/src/jsapi-tests/testParseJSON.cpp index f381825088eb..75c8c799d564 100644 --- a/js/src/jsapi-tests/testParseJSON.cpp +++ b/js/src/jsapi-tests/testParseJSON.cpp @@ -327,7 +327,7 @@ ReportJSONError(JSContext* cx, const char* message, JSErrorReport* report) END_TEST(testParseJSON_error) static bool -Censor(JSContext* cx, unsigned argc, jsval* vp) +Censor(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); MOZ_RELEASE_ASSERT(args.length() == 2); diff --git a/js/src/jsapi-tests/testProfileStrings.cpp b/js/src/jsapi-tests/testProfileStrings.cpp index 9bfa29bb6cd4..903c87af582a 100644 --- a/js/src/jsapi-tests/testProfileStrings.cpp +++ b/js/src/jsapi-tests/testProfileStrings.cpp @@ -30,14 +30,14 @@ static const JSClass ptestClass = { }; static bool -test_fn(JSContext* cx, unsigned argc, jsval* vp) +test_fn(JSContext* cx, unsigned argc, JS::Value* vp) { max_stack = psize; return true; } static bool -test_fn2(JSContext* cx, unsigned argc, jsval* vp) +test_fn2(JSContext* cx, unsigned argc, JS::Value* vp) { JS::RootedValue r(cx); JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); @@ -45,21 +45,21 @@ test_fn2(JSContext* cx, unsigned argc, jsval* vp) } static bool -enable(JSContext* cx, unsigned argc, jsval* vp) +enable(JSContext* cx, unsigned argc, JS::Value* vp) { js::EnableRuntimeProfilingStack(cx->runtime(), true); return true; } static bool -disable(JSContext* cx, unsigned argc, jsval* vp) +disable(JSContext* cx, unsigned argc, JS::Value* vp) { js::EnableRuntimeProfilingStack(cx->runtime(), false); return true; } static bool -Prof(JSContext* cx, unsigned argc, jsval* vp) +Prof(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JSObject* obj = JS_NewObjectForConstructor(cx, &ptestClass, args); diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index b70d45b23db5..a34a40dd47d1 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -182,7 +182,7 @@ class JSAPITest return false; \ } while (false) - bool checkSame(jsval actualArg, jsval expectedArg, + bool checkSame(JS::Value actualArg, JS::Value expectedArg, const char* actualExpr, const char* expectedExpr, const char* filename, int lineno) { bool same; @@ -238,7 +238,7 @@ class JSAPITest protected: static bool - print(JSContext* cx, unsigned argc, jsval* vp) + print(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 84653b470c00..2305230a04b1 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -266,25 +266,25 @@ JS_Now() return PRMJ_Now(); } -JS_PUBLIC_API(jsval) +JS_PUBLIC_API(Value) JS_GetNaNValue(JSContext* cx) { return cx->runtime()->NaNValue; } -JS_PUBLIC_API(jsval) +JS_PUBLIC_API(Value) JS_GetNegativeInfinityValue(JSContext* cx) { return cx->runtime()->negativeInfinityValue; } -JS_PUBLIC_API(jsval) +JS_PUBLIC_API(Value) JS_GetPositiveInfinityValue(JSContext* cx) { return cx->runtime()->positiveInfinityValue; } -JS_PUBLIC_API(jsval) +JS_PUBLIC_API(Value) JS_GetEmptyStringValue(JSContext* cx) { return StringValue(cx->runtime()->emptyString); @@ -1435,8 +1435,8 @@ JS::CurrentGlobalOrNull(JSContext* cx) return cx->global(); } -JS_PUBLIC_API(jsval) -JS_ComputeThis(JSContext* cx, jsval* vp) +JS_PUBLIC_API(Value) +JS_ComputeThis(JSContext* cx, Value* vp) { AssertHeapIsIdle(cx); assertSameCompartment(cx, JSValueArray(vp, 2)); @@ -3144,7 +3144,7 @@ JS_Enumerate(JSContext* cx, HandleObject obj) return ida; } -JS_PUBLIC_API(jsval) +JS_PUBLIC_API(Value) JS_GetReservedSlot(JSObject* obj, uint32_t index) { return obj->as().getReservedSlot(index); @@ -3528,7 +3528,7 @@ GenericNativeMethodDispatcher(JSContext* cx, unsigned argc, Value* vp) * call the corresponding prototype native method with our first argument * passed as |this|. */ - memmove(vp + 1, vp + 2, argc * sizeof(jsval)); + memmove(vp + 1, vp + 2, argc * sizeof(Value)); /* Clear the last parameter in case too few arguments were passed. */ vp[2 + --argc].setUndefined(); @@ -4323,7 +4323,7 @@ JS_DecompileFunctionBody(JSContext* cx, HandleFunction fun, unsigned indent) } MOZ_NEVER_INLINE static bool -ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, jsval* rval) +ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval) { MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); AssertHeapIsIdle(cx); @@ -4335,7 +4335,7 @@ ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, jsval* rva } static bool -ExecuteScript(JSContext* cx, AutoObjectVector& scopeChain, HandleScript scriptArg, jsval* rval) +ExecuteScript(JSContext* cx, AutoObjectVector& scopeChain, HandleScript scriptArg, Value* rval) { RootedObject dynamicScope(cx); Rooted staticScope(cx); @@ -5813,7 +5813,7 @@ JS_ThrowStopIteration(JSContext* cx) } JS_PUBLIC_API(bool) -JS_IsStopIteration(jsval v) +JS_IsStopIteration(Value v) { return v.isObject() && v.toObject().is(); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index f4a5cec94265..b2d67217f086 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -734,7 +734,7 @@ typedef void* /************************************************************************/ -static MOZ_ALWAYS_INLINE jsval +static MOZ_ALWAYS_INLINE JS::Value JS_NumberValue(double d) { int32_t i; @@ -936,17 +936,17 @@ JS_CallOnce(JSCallOnceType* once, JSInitCallback func); extern JS_PUBLIC_API(int64_t) JS_Now(void); -/* Don't want to export data, so provide accessors for non-inline jsvals. */ -extern JS_PUBLIC_API(jsval) +/* Don't want to export data, so provide accessors for non-inline Values. */ +extern JS_PUBLIC_API(JS::Value) JS_GetNaNValue(JSContext* cx); -extern JS_PUBLIC_API(jsval) +extern JS_PUBLIC_API(JS::Value) JS_GetNegativeInfinityValue(JSContext* cx); -extern JS_PUBLIC_API(jsval) +extern JS_PUBLIC_API(JS::Value) JS_GetPositiveInfinityValue(JSContext* cx); -extern JS_PUBLIC_API(jsval) +extern JS_PUBLIC_API(JS::Value) JS_GetEmptyStringValue(JSContext* cx); extern JS_PUBLIC_API(JSString*) @@ -3192,11 +3192,11 @@ JS_ReleaseMappedArrayBufferContents(void* contents, size_t length); extern JS_PUBLIC_API(JSIdArray*) JS_Enumerate(JSContext* cx, JS::HandleObject obj); -extern JS_PUBLIC_API(jsval) +extern JS_PUBLIC_API(JS::Value) JS_GetReservedSlot(JSObject* obj, uint32_t index); extern JS_PUBLIC_API(void) -JS_SetReservedSlot(JSObject* obj, uint32_t index, jsval v); +JS_SetReservedSlot(JSObject* obj, uint32_t index, JS::Value v); /************************************************************************/ @@ -4926,7 +4926,7 @@ extern JS_PUBLIC_API(bool) JS_ThrowStopIteration(JSContext* cx); extern JS_PUBLIC_API(bool) -JS_IsStopIteration(jsval v); +JS_IsStopIteration(JS::Value v); extern JS_PUBLIC_API(intptr_t) JS_GetCurrentThread(); diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index fd06a81b6283..eb7a8554ec9a 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1306,10 +1306,12 @@ class MOZ_STACK_CLASS AutoStableStringChars {} ~AutoStableStringChars(); - bool init(JSContext* cx, JSString* s) MOZ_WARN_UNUSED_RESULT; + MOZ_WARN_UNUSED_RESULT + bool init(JSContext* cx, JSString* s); /* Like init(), but Latin1 chars are inflated to TwoByte. */ - bool initTwoByte(JSContext* cx, JSString* s) MOZ_WARN_UNUSED_RESULT; + MOZ_WARN_UNUSED_RESULT + bool initTwoByte(JSContext* cx, JSString* s); bool isLatin1() const { return state_ == Latin1; } bool isTwoByte() const { return state_ == TwoByte; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 1006eacd61d3..26a720bad4dd 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -669,10 +669,10 @@ IsConstructor(const Value& v) class JSValueArray { public: - const jsval* array; + const js::Value* array; size_t length; - JSValueArray(const jsval* v, size_t c) : array(v), length(c) {} + JSValueArray(const js::Value* v, size_t c) : array(v), length(c) {} }; class ValueArray { diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 8910dc788daf..0f11a789936a 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -325,6 +325,7 @@ enum ThingRootKind THING_ROOT_LAZY_SCRIPT, THING_ROOT_ID, THING_ROOT_VALUE, + THING_ROOT_BINDINGS, THING_ROOT_PROPERTY_DESCRIPTOR, THING_ROOT_PROP_DESC, THING_ROOT_STATIC_TRACEABLE, diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index e24f0c50a3f1..5f0428fc2180 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -61,25 +61,24 @@ using mozilla::PodZero; using mozilla::RotateLeft; /* static */ BindingIter -Bindings::argumentsBinding(ExclusiveContext* cx, HandleScript script) +Bindings::argumentsBinding(ExclusiveContext* cx, InternalBindingsHandle bindings) { HandlePropertyName arguments = cx->names().arguments; - BindingIter bi(script); + BindingIter bi(bindings); while (bi->name() != arguments) bi++; return bi; } bool -Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle self, +Bindings::initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle self, uint32_t numArgs, uint32_t numVars, uint32_t numBodyLevelLexicals, uint32_t numBlockScoped, uint32_t numUnaliasedVars, uint32_t numUnaliasedBodyLevelLexicals, - const Binding* bindingArray) + Binding* bindingArray) { - MOZ_ASSERT(!self.callObjShape()); - MOZ_ASSERT(self.bindingArrayUsingTemporaryStorage()); - MOZ_ASSERT(!self.bindingArray()); + MOZ_ASSERT(!self->callObjShape_); + MOZ_ASSERT(self->bindingArrayAndFlag_ == TEMPORARY_STORAGE_BIT); MOZ_ASSERT(!(uintptr_t(bindingArray) & TEMPORARY_STORAGE_BIT)); MOZ_ASSERT(numArgs <= ARGC_LIMIT); MOZ_ASSERT(numVars <= LOCALNO_LIMIT); @@ -94,13 +93,13 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle MOZ_ASSERT(numUnaliasedVars <= numVars); MOZ_ASSERT(numUnaliasedBodyLevelLexicals <= numBodyLevelLexicals); - self.setBindingArray(bindingArray, TEMPORARY_STORAGE_BIT); - self.setNumArgs(numArgs); - self.setNumVars(numVars); - self.setNumBodyLevelLexicals(numBodyLevelLexicals); - self.setNumBlockScoped(numBlockScoped); - self.setNumUnaliasedVars(numUnaliasedVars); - self.setNumUnaliasedBodyLevelLexicals(numUnaliasedBodyLevelLexicals); + self->bindingArrayAndFlag_ = uintptr_t(bindingArray) | TEMPORARY_STORAGE_BIT; + self->numArgs_ = numArgs; + self->numVars_ = numVars; + self->numBodyLevelLexicals_ = numBodyLevelLexicals; + self->numBlockScoped_ = numBlockScoped; + self->numUnaliasedVars_ = numUnaliasedVars; + self->numUnaliasedBodyLevelLexicals_ = numUnaliasedBodyLevelLexicals; // Get the initial shape to use when creating CallObjects for this script. // After creation, a CallObject's shape may change completely (via direct eval() or @@ -135,7 +134,7 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle nslots++; } } - self.setAliasedBodyLevelLexicalBegin(aliasedBodyLevelLexicalBegin); + self->aliasedBodyLevelLexicalBegin_ = aliasedBodyLevelLexicalBegin; // Put as many of nslots inline into the object header as possible. uint32_t nfixed = gc::GetGCKindSlots(gc::GetGCObjectKind(nslots)); @@ -191,7 +190,7 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle MOZ_ASSERT(slot == nslots); MOZ_ASSERT(!shape->inDictionary()); - self.setCallObjShape(shape); + self->callObjShape_.init(shape); return true; } @@ -219,12 +218,12 @@ Bindings::switchToScriptStorage(Binding* newBindingArray) return reinterpret_cast(newBindingArray + count()); } -/* static */ bool -Bindings::clone(JSContext* cx, MutableHandle self, +bool +Bindings::clone(JSContext* cx, InternalBindingsHandle self, uint8_t* dstScriptData, HandleScript srcScript) { /* The clone has the same bindingArray_ offset as 'src'. */ - Handle src = Handle::fromMarkedLocation(&srcScript->bindings); + Bindings& src = srcScript->bindings; ptrdiff_t off = (uint8_t*)src.bindingArray() - srcScript->data; MOZ_ASSERT(off >= 0); MOZ_ASSERT(size_t(off) <= srcScript->dataSize()); @@ -244,10 +243,16 @@ Bindings::clone(JSContext* cx, MutableHandle self, return false; } - self.switchToScriptStorage(dstPackedBindings); + self->switchToScriptStorage(dstPackedBindings); return true; } +/* static */ Bindings +GCMethods::initial() +{ + return Bindings(); +} + template static bool XDRScriptBindings(XDRState* xdr, LifoAllocScope& las, uint16_t numArgs, uint32_t numVars, @@ -297,15 +302,14 @@ XDRScriptBindings(XDRState* xdr, LifoAllocScope& las, uint16_t numArgs, ui bindingArray[i] = Binding(name, kind, aliased); } - Rooted bindings(cx, script->bindings); - if (!Bindings::initWithTemporaryStorage(cx, &bindings, numArgs, numVars, + InternalBindingsHandle bindings(script, &script->bindings); + if (!Bindings::initWithTemporaryStorage(cx, bindings, numArgs, numVars, numBodyLevelLexicals, numBlockScoped, numUnaliasedVars, numUnaliasedBodyLevelLexicals, bindingArray)) { return false; } - script->bindings = bindings; } return true; @@ -2360,7 +2364,7 @@ js::FreeScriptData(JSRuntime* rt) * * IMPORTANT: This layout has two key properties. * - It ensures that everything has sufficient alignment; in particular, the - * consts() elements need jsval alignment. + * consts() elements need Value alignment. * - It ensures there are no gaps between elements, which saves space and makes * manual layout easy. In particular, in the second part, arrays with larger * elements precede arrays with smaller elements. @@ -2383,12 +2387,12 @@ js::FreeScriptData(JSRuntime* rt) */ #define KEEPS_JSVAL_ALIGNMENT(T) \ - (JS_ALIGNMENT_OF(jsval) % JS_ALIGNMENT_OF(T) == 0 && \ - sizeof(T) % sizeof(jsval) == 0) + (JS_ALIGNMENT_OF(JS::Value) % JS_ALIGNMENT_OF(T) == 0 && \ + sizeof(T) % sizeof(JS::Value) == 0) #define HAS_JSVAL_ALIGNMENT(T) \ - (JS_ALIGNMENT_OF(jsval) == JS_ALIGNMENT_OF(T) && \ - sizeof(T) == sizeof(jsval)) + (JS_ALIGNMENT_OF(JS::Value) == JS_ALIGNMENT_OF(T) && \ + sizeof(T) == sizeof(JS::Value)) #define NO_PADDING_BETWEEN_ENTRIES(T1, T2) \ (JS_ALIGNMENT_OF(T1) % JS_ALIGNMENT_OF(T2) == 0) @@ -2396,7 +2400,7 @@ js::FreeScriptData(JSRuntime* rt) /* * These assertions ensure that there is no padding between the array headers, * and also that the consts() elements (which follow immediately afterward) are - * jsval-aligned. (There is an assumption that |data| itself is jsval-aligned; + * Value-aligned. (There is an assumption that |data| itself is Value-aligned; * we check this below). */ JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(ConstArray)); @@ -2561,7 +2565,7 @@ JSScript::partiallyInit(ExclusiveContext* cx, HandleScript script, uint32_t ncon } if (nconsts != 0) { - MOZ_ASSERT(reinterpret_cast(cursor) % sizeof(jsval) == 0); + MOZ_ASSERT(reinterpret_cast(cursor) % sizeof(JS::Value) == 0); script->consts()->length = nconsts; script->consts()->vector = (HeapValue*)cursor; cursor += nconsts * sizeof(script->consts()->vector[0]); @@ -3121,7 +3125,9 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri /* Bindings */ Rooted bindings(cx); - if (!Bindings::clone(cx, &bindings, data, src)) + InternalHandle bindingsHandle = + InternalHandle::fromMarkedLocation(bindings.address()); + if (!Bindings::clone(cx, bindingsHandle, data, src)) return false; /* Objects */ @@ -3706,7 +3712,8 @@ js::SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame, * object. Note that 'arguments' may have already been overwritten. */ - BindingIter bi = Bindings::argumentsBinding(cx, script); + InternalBindingsHandle bindings(script, &script->bindings); + BindingIter bi = Bindings::argumentsBinding(cx, bindings); if (script->bindingIsAliased(bi)) { /* diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 37c5060feb23..f3757e1d5503 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -200,18 +200,19 @@ class Binding JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t)); +class Bindings; +typedef InternalHandle InternalBindingsHandle; + /* * Formal parameters and local variables are stored in a shape tree * path encapsulated within this class. This class represents bindings for * both function and top-level scripts (the latter is needed to track names in * strict mode eval code, to give such code its own lexical environment). */ -class Bindings : public JS::StaticTraceable +class Bindings { friend class BindingIter; friend class AliasedFormalIter; - template friend class BindingsOperations; - template friend class MutableBindingsOperations; RelocatablePtrShape callObjShape_; uintptr_t bindingArrayAndFlag_; @@ -249,12 +250,7 @@ class Bindings : public JS::StaticTraceable return reinterpret_cast(bindingArrayAndFlag_ & ~TEMPORARY_STORAGE_BIT); } - Bindings() - : callObjShape_(nullptr), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT), - numArgs_(0), numBlockScoped_(0), - numBodyLevelLexicals_(0), numUnaliasedBodyLevelLexicals_(0), - numVars_(0), numUnaliasedVars_(0) - {} + inline Bindings(); /* * Initialize a Bindings with a pointer into temporary storage. @@ -263,14 +259,11 @@ class Bindings : public JS::StaticTraceable * switchToScriptStorage must be called, providing a pointer into the * Binding array stored in script->data. */ - static bool initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle self, - uint32_t numArgs, - uint32_t numVars, - uint32_t numBodyLevelLexicals, - uint32_t numBlockScoped, - uint32_t numUnaliasedVars, - uint32_t numUnaliasedBodyLevelLexicals, - const Binding* bindingArray); + static bool initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle self, + uint32_t numArgs, uint32_t numVars, + uint32_t numBodyLevelLexicals, uint32_t numBlockScoped, + uint32_t numUnaliasedVars, uint32_t numUnaliasedBodyLevelLexicals, + Binding* bindingArray); // Initialize a trivial Bindings with no slots and an empty callObjShape. bool initTrivial(ExclusiveContext* cx); @@ -299,7 +292,7 @@ class Bindings : public JS::StaticTraceable * Clone srcScript's bindings (as part of js::CloneScript). dstScriptData * is the pointer to what will eventually be dstScript->data. */ - static bool clone(JSContext* cx, MutableHandle self, uint8_t* dstScriptData, + static bool clone(JSContext* cx, InternalBindingsHandle self, uint8_t* dstScriptData, HandleScript srcScript); uint32_t numArgs() const { return numArgs_; } @@ -324,7 +317,7 @@ class Bindings : public JS::StaticTraceable Shape* callObjShape() const { return callObjShape_; } /* Convenience method to get the var index of 'arguments'. */ - static BindingIter argumentsBinding(ExclusiveContext* cx, HandleScript script); + static BindingIter argumentsBinding(ExclusiveContext* cx, InternalBindingsHandle); /* Return whether the binding at bindingIndex is aliased. */ bool bindingIsAliased(uint32_t bindingIndex); @@ -340,122 +333,13 @@ class Bindings : public JS::StaticTraceable Binding* begin() const { return bindingArray(); } Binding* end() const { return bindingArray() + count(); } - static void trace(Bindings* self, JSTracer* trc) { self->trace(trc); } + static js::ThingRootKind rootKind() { return js::THING_ROOT_BINDINGS; } void trace(JSTracer* trc); }; -template -class BindingsOperations -{ - const Bindings& bindings() const { return static_cast(this)->extract(); } - - public: - // Direct data access to the underlying bindings. - const RelocatablePtrShape& callObjShape() const { - return bindings().callObjShape_; - } - uint16_t numArgs() const { - return bindings().numArgs_; - } - uint16_t numBlockScoped() const { - return bindings().numBlockScoped_; - } - uint16_t numBodyLevelLexicals() const { - return bindings().numBodyLevelLexicals_; - } - uint16_t aliasedBodyLevelLexicalBegin() const { - return bindings().aliasedBodyLevelLexicalBegin_; - } - uint16_t numUnaliasedBodyLevelLexicals() const { - return bindings().numUnaliasedBodyLevelLexicals_; - } - uint32_t numVars() const { - return bindings().numVars_; - } - uint32_t numUnaliasedVars() const { - return bindings().numUnaliasedVars_; - } - - // Binding array access. - bool bindingArrayUsingTemporaryStorage() const { - return bindings().bindingArrayUsingTemporaryStorage(); - } - const Binding* bindingArray() const { - return bindings().bindingArray(); - } - uint32_t count() const { - return bindings().count(); - } - - // Helpers. - uint32_t numBodyLevelLocals() const { - return numVars() + numBodyLevelLexicals(); - } - uint32_t numUnaliasedBodyLevelLocals() const { - return numUnaliasedVars() + numUnaliasedBodyLevelLexicals(); - } - uint32_t numAliasedBodyLevelLocals() const { - return numBodyLevelLocals() - numUnaliasedBodyLevelLocals(); - } - uint32_t numLocals() const { - return numVars() + numBodyLevelLexicals() + numBlockScoped(); - } - uint32_t numFixedLocals() const { - return numUnaliasedVars() + numUnaliasedBodyLevelLexicals() + numBlockScoped(); - } - uint32_t lexicalBegin() const { - return numArgs() + numVars(); - } -}; - -template -class MutableBindingsOperations : public BindingsOperations -{ - Bindings& bindings() { return static_cast(this)->extractMutable(); } - - public: - void setCallObjShape(HandleShape shape) { bindings().callObjShape_ = shape; } - void setBindingArray(const Binding* bindingArray, uintptr_t temporaryBit) { - bindings().bindingArrayAndFlag_ = uintptr_t(bindingArray) | temporaryBit; - } - void setNumArgs(uint16_t num) { bindings().numArgs_ = num; } - void setNumVars(uint32_t num) { bindings().numVars_ = num; } - void setNumBodyLevelLexicals(uint16_t num) { bindings().numBodyLevelLexicals_ = num; } - void setNumBlockScoped(uint16_t num) { bindings().numBlockScoped_ = num; } - void setNumUnaliasedVars(uint32_t num) { bindings().numUnaliasedVars_ = num; } - void setNumUnaliasedBodyLevelLexicals(uint16_t num) { - bindings().numUnaliasedBodyLevelLexicals_ = num; - } - void setAliasedBodyLevelLexicalBegin(uint16_t offset) { - bindings().aliasedBodyLevelLexicalBegin_ = offset; - } - uint8_t* switchToScriptStorage(Binding* permanentStorage) { - return bindings().switchToScriptStorage(permanentStorage); - } -}; - template <> -class HandleBase : public BindingsOperations> -{ - friend class BindingsOperations>; - const Bindings& extract() const { - return static_cast*>(this)->get(); - } -}; - -template <> -class MutableHandleBase - : public MutableBindingsOperations> -{ - friend class BindingsOperations>; - const Bindings& extract() const { - return static_cast*>(this)->get(); - } - - friend class MutableBindingsOperations>; - Bindings& extractMutable() { - return static_cast*>(this)->get(); - } +struct GCMethods { + static Bindings initial(); }; class ScriptCounts @@ -1898,7 +1782,7 @@ namespace js { */ class BindingIter { - Handle bindings_; + const InternalBindingsHandle bindings_; uint32_t i_; uint32_t unaliasedLocal_; @@ -1906,16 +1790,12 @@ class BindingIter friend class Bindings; public: - explicit BindingIter(Handle bindings) - : bindings_(bindings), i_(0), unaliasedLocal_(0) - {} - + explicit BindingIter(const InternalBindingsHandle& bindings) + : bindings_(bindings), i_(0), unaliasedLocal_(0) {} explicit BindingIter(const HandleScript& script) - : bindings_(Handle::fromMarkedLocation(&script->bindings)), - i_(0), unaliasedLocal_(0) - {} + : bindings_(script, &script->bindings), i_(0), unaliasedLocal_(0) {} - bool done() const { return i_ == bindings_.count(); } + bool done() const { return i_ == bindings_->count(); } explicit operator bool() const { return !done(); } BindingIter& operator++() { (*this)++; return *this; } @@ -1933,7 +1813,7 @@ class BindingIter // has no stack slot. uint32_t frameIndex() const { MOZ_ASSERT(!done()); - if (i_ < bindings_.numArgs()) + if (i_ < bindings_->numArgs()) return i_; MOZ_ASSERT(!(*this)->aliased()); return unaliasedLocal_; @@ -1944,17 +1824,17 @@ class BindingIter // both unaliased and aliased arguments. uint32_t argIndex() const { MOZ_ASSERT(!done()); - MOZ_ASSERT(i_ < bindings_.numArgs()); + MOZ_ASSERT(i_ < bindings_->numArgs()); return i_; } uint32_t argOrLocalIndex() const { MOZ_ASSERT(!done()); - return i_ < bindings_.numArgs() ? i_ : i_ - bindings_.numArgs(); + return i_ < bindings_->numArgs() ? i_ : i_ - bindings_->numArgs(); } uint32_t localIndex() const { MOZ_ASSERT(!done()); - MOZ_ASSERT(i_ >= bindings_.numArgs()); - return i_ - bindings_.numArgs(); + MOZ_ASSERT(i_ >= bindings_->numArgs()); + return i_ - bindings_->numArgs(); } bool isBodyLevelLexical() const { MOZ_ASSERT(!done()); @@ -1962,8 +1842,8 @@ class BindingIter return binding.kind() != Binding::ARGUMENT; } - const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_.bindingArray()[i_]; } - const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_.bindingArray()[i_]; } + const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_->bindingArray()[i_]; } + const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_->bindingArray()[i_]; } }; /* diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index b3b7867da206..7117878b7f3c 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -20,6 +20,14 @@ namespace js { +inline +Bindings::Bindings() + : callObjShape_(nullptr), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT), + numArgs_(0), numBlockScoped_(0), + numBodyLevelLexicals_(0), numUnaliasedBodyLevelLexicals_(0), + numVars_(0), numUnaliasedVars_(0) +{} + inline AliasedFormalIter::AliasedFormalIter(JSScript* script) : begin_(script->bindingArray()), diff --git a/js/src/perf/jsperf.cpp b/js/src/perf/jsperf.cpp index b28134dcfcbb..8ea79051e03b 100644 --- a/js/src/perf/jsperf.cpp +++ b/js/src/perf/jsperf.cpp @@ -49,7 +49,7 @@ GETTER(eventsMeasured) // Calls static bool -pm_start(JSContext* cx, unsigned argc, jsval* vp) +pm_start(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); PerfMeasurement* p = GetPM(cx, args.thisv(), "start"); @@ -62,7 +62,7 @@ pm_start(JSContext* cx, unsigned argc, jsval* vp) } static bool -pm_stop(JSContext* cx, unsigned argc, jsval* vp) +pm_stop(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); PerfMeasurement* p = GetPM(cx, args.thisv(), "stop"); @@ -75,7 +75,7 @@ pm_stop(JSContext* cx, unsigned argc, jsval* vp) } static bool -pm_reset(JSContext* cx, unsigned argc, jsval* vp) +pm_reset(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); PerfMeasurement* p = GetPM(cx, args.thisv(), "reset"); @@ -88,7 +88,7 @@ pm_reset(JSContext* cx, unsigned argc, jsval* vp) } static bool -pm_canMeasureSomething(JSContext* cx, unsigned argc, jsval* vp) +pm_canMeasureSomething(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); PerfMeasurement* p = GetPM(cx, args.thisv(), "canMeasureSomething"); @@ -158,7 +158,7 @@ static const struct pm_const { #undef CONSTANT -static bool pm_construct(JSContext* cx, unsigned argc, jsval* vp); +static bool pm_construct(JSContext* cx, unsigned argc, Value* vp); static void pm_finalize(JSFreeOp* fop, JSObject* obj); static const JSClass pm_class = { @@ -170,7 +170,7 @@ static const JSClass pm_class = { // Constructor and destructor static bool -pm_construct(JSContext* cx, unsigned argc, jsval* vp) +pm_construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -267,7 +267,7 @@ RegisterPerfMeasurement(JSContext* cx, HandleObject globalArg) } PerfMeasurement* -ExtractPerfMeasurement(jsval wrapper) +ExtractPerfMeasurement(Value wrapper) { if (wrapper.isPrimitive()) return 0; diff --git a/js/src/proxy/ScriptedDirectProxyHandler.h b/js/src/proxy/ScriptedDirectProxyHandler.h index 7c710b68ab44..133c31ab71ff 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.h +++ b/js/src/proxy/ScriptedDirectProxyHandler.h @@ -101,10 +101,10 @@ class ScriptedDirectProxyHandler : public BaseProxyHandler { }; bool -proxy(JSContext* cx, unsigned argc, jsval* vp); +proxy(JSContext* cx, unsigned argc, Value* vp); bool -proxy_revocable(JSContext* cx, unsigned argc, jsval* vp); +proxy_revocable(JSContext* cx, unsigned argc, Value* vp); } /* namespace js */ diff --git a/js/src/shell/OSObject.cpp b/js/src/shell/OSObject.cpp index 53300db36735..0674bf49f9af 100644 --- a/js/src/shell/OSObject.cpp +++ b/js/src/shell/OSObject.cpp @@ -151,7 +151,7 @@ FileAsTypedArray(JSContext* cx, const char* pathname) } static bool -ReadFile(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative) +ReadFile(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) { CallArgs args = CallArgsFromVp(argc, vp); @@ -199,13 +199,13 @@ ReadFile(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative) } static bool -osfile_readFile(JSContext* cx, unsigned argc, jsval* vp) +osfile_readFile(JSContext* cx, unsigned argc, Value* vp) { return ReadFile(cx, argc, vp, false); } static bool -osfile_readRelativeToScript(JSContext* cx, unsigned argc, jsval* vp) +osfile_readRelativeToScript(JSContext* cx, unsigned argc, Value* vp) { return ReadFile(cx, argc, vp, true); } @@ -227,7 +227,7 @@ Redirect(JSContext* cx, FILE* fp, HandleString relFilename) } static bool -osfile_redirect(JSContext* cx, unsigned argc, jsval* vp) +osfile_redirect(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -371,7 +371,7 @@ ReportSysError(JSContext* cx, const char* prefix) } static bool -os_system(JSContext* cx, unsigned argc, jsval* vp) +os_system(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -400,7 +400,7 @@ os_system(JSContext* cx, unsigned argc, jsval* vp) #ifndef XP_WIN static bool -os_spawn(JSContext* cx, unsigned argc, jsval* vp) +os_spawn(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index fc2a2f96ef77..5b62455358ab 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -581,7 +581,7 @@ Process(JSContext* cx, const char* filename, bool forceTTY) } static bool -Version(JSContext* cx, unsigned argc, jsval* vp) +Version(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSVersion origVersion = JS_GetVersion(cx); @@ -691,7 +691,7 @@ CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp) } static bool -Options(JSContext* cx, unsigned argc, jsval* vp) +Options(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -750,7 +750,7 @@ Options(JSContext* cx, unsigned argc, jsval* vp) } static bool -LoadScript(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative) +LoadScript(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) { CallArgs args = CallArgsFromVp(argc, vp); @@ -789,13 +789,13 @@ LoadScript(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative) } static bool -Load(JSContext* cx, unsigned argc, jsval* vp) +Load(JSContext* cx, unsigned argc, Value* vp) { return LoadScript(cx, argc, vp, false); } static bool -LoadScriptRelativeToScript(JSContext* cx, unsigned argc, jsval* vp) +LoadScriptRelativeToScript(JSContext* cx, unsigned argc, Value* vp) { return LoadScript(cx, argc, vp, true); } @@ -1031,7 +1031,7 @@ class AutoSaveFrameChain }; static bool -Evaluate(JSContext* cx, unsigned argc, jsval* vp) +Evaluate(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1329,7 +1329,7 @@ js::shell::FileAsString(JSContext* cx, const char* pathname) * to produce benchmark timings by SunSpider. */ static bool -Run(JSContext* cx, unsigned argc, jsval* vp) +Run(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -1382,7 +1382,7 @@ Run(JSContext* cx, unsigned argc, jsval* vp) * Provides a hook for scripts to read a line from stdin. */ static bool -ReadLine(JSContext* cx, unsigned argc, jsval* vp) +ReadLine(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1456,7 +1456,7 @@ ReadLine(JSContext* cx, unsigned argc, jsval* vp) } static bool -PutStr(JSContext* cx, unsigned argc, jsval* vp) +PutStr(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1477,7 +1477,7 @@ PutStr(JSContext* cx, unsigned argc, jsval* vp) } static bool -Now(JSContext* cx, unsigned argc, jsval* vp) +Now(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); double now = PRMJ_Now() / double(PRMJ_USEC_PER_MSEC); @@ -1507,24 +1507,24 @@ PrintInternal(JSContext* cx, const CallArgs& args, FILE* file) } static bool -Print(JSContext* cx, unsigned argc, jsval* vp) +Print(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return PrintInternal(cx, args, gOutFile); } static bool -PrintErr(JSContext* cx, unsigned argc, jsval* vp) +PrintErr(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); return PrintInternal(cx, args, gErrFile); } static bool -Help(JSContext* cx, unsigned argc, jsval* vp); +Help(JSContext* cx, unsigned argc, Value* vp); static bool -Quit(JSContext* cx, unsigned argc, jsval* vp) +Quit(JSContext* cx, unsigned argc, Value* vp) { #ifdef JS_MORE_DETERMINISTIC // Print a message to stderr in more-deterministic builds to help jsfunfuzz @@ -1553,7 +1553,7 @@ Quit(JSContext* cx, unsigned argc, jsval* vp) } static bool -StartTimingMutator(JSContext* cx, unsigned argc, jsval* vp) +StartTimingMutator(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() > 0) { @@ -1568,7 +1568,7 @@ StartTimingMutator(JSContext* cx, unsigned argc, jsval* vp) } static bool -StopTimingMutator(JSContext* cx, unsigned argc, jsval* vp) +StopTimingMutator(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() > 0) { @@ -1606,7 +1606,7 @@ ToSource(JSContext* cx, MutableHandleValue vp, JSAutoByteString* bytes) } static bool -AssertEq(JSContext* cx, unsigned argc, jsval* vp) +AssertEq(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!(args.length() == 2 || (args.length() == 3 && args[2].isString()))) { @@ -1644,7 +1644,7 @@ AssertEq(JSContext* cx, unsigned argc, jsval* vp) } static JSScript* -ValueToScript(JSContext* cx, jsval vArg, JSFunction** funp = nullptr) +ValueToScript(JSContext* cx, Value vArg, JSFunction** funp = nullptr) { RootedValue v(cx, vArg); RootedFunction fun(cx, JS_ValueToFunction(cx, v)); @@ -1683,13 +1683,13 @@ GetTopScript(JSContext* cx) } static bool -GetScriptAndPCArgs(JSContext* cx, unsigned argc, jsval* argv, MutableHandleScript scriptp, +GetScriptAndPCArgs(JSContext* cx, unsigned argc, Value* argv, MutableHandleScript scriptp, int32_t* ip) { RootedScript script(cx, GetTopScript(cx)); *ip = 0; if (argc != 0) { - jsval v = argv[0]; + Value v = argv[0]; unsigned intarg = 0; if (v.isObject() && JS_GetClass(&v.toObject()) == Jsvalify(&JSFunction::class_)) { @@ -1714,7 +1714,7 @@ GetScriptAndPCArgs(JSContext* cx, unsigned argc, jsval* argv, MutableHandleScrip } static bool -LineToPC(JSContext* cx, unsigned argc, jsval* vp) +LineToPC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1744,7 +1744,7 @@ LineToPC(JSContext* cx, unsigned argc, jsval* vp) } static bool -PCToLine(JSContext* cx, unsigned argc, jsval* vp) +PCToLine(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedScript script(cx); @@ -1893,7 +1893,7 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp) } static bool -Notes(JSContext* cx, unsigned argc, jsval* vp) +Notes(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); Sprinter sprinter(cx); @@ -2016,11 +2016,11 @@ namespace { struct DisassembleOptionParser { unsigned argc; - jsval* argv; + Value* argv; bool lines; bool recursive; - DisassembleOptionParser(unsigned argc, jsval* argv) + DisassembleOptionParser(unsigned argc, Value* argv) : argc(argc), argv(argv), lines(false), recursive(false) {} bool parse(JSContext* cx) { @@ -2045,7 +2045,7 @@ struct DisassembleOptionParser { } /* anonymous namespace */ static bool -DisassembleToSprinter(JSContext* cx, unsigned argc, jsval* vp, Sprinter* sprinter) +DisassembleToSprinter(JSContext* cx, unsigned argc, Value* vp, Sprinter* sprinter) { CallArgs args = CallArgsFromVp(argc, vp); DisassembleOptionParser p(args.length(), args.array()); @@ -2077,7 +2077,7 @@ DisassembleToSprinter(JSContext* cx, unsigned argc, jsval* vp, Sprinter* sprinte } static bool -DisassembleToString(JSContext* cx, unsigned argc, jsval* vp) +DisassembleToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); Sprinter sprinter(cx); @@ -2094,7 +2094,7 @@ DisassembleToString(JSContext* cx, unsigned argc, jsval* vp) } static bool -Disassemble(JSContext* cx, unsigned argc, jsval* vp) +Disassemble(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); Sprinter sprinter(cx); @@ -2109,7 +2109,7 @@ Disassemble(JSContext* cx, unsigned argc, jsval* vp) } static bool -DisassFile(JSContext* cx, unsigned argc, jsval* vp) +DisassFile(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2158,7 +2158,7 @@ DisassFile(JSContext* cx, unsigned argc, jsval* vp) } static bool -DisassWithSrc(JSContext* cx, unsigned argc, jsval* vp) +DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2256,7 +2256,7 @@ DisassWithSrc(JSContext* cx, unsigned argc, jsval* vp) #endif /* DEBUG */ static bool -Intern(JSContext* cx, unsigned argc, jsval* vp) +Intern(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSString* str = JS::ToString(cx, args.get(0)); @@ -2277,7 +2277,7 @@ Intern(JSContext* cx, unsigned argc, jsval* vp) } static bool -Clone(JSContext* cx, unsigned argc, jsval* vp) +Clone(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject parent(cx); @@ -2327,7 +2327,7 @@ Clone(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetSLX(JSContext* cx, unsigned argc, jsval* vp) +GetSLX(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedScript script(cx); @@ -2340,7 +2340,7 @@ GetSLX(JSContext* cx, unsigned argc, jsval* vp) } static bool -ThrowError(JSContext* cx, unsigned argc, jsval* vp) +ThrowError(JSContext* cx, unsigned argc, Value* vp) { JS_ReportError(cx, "This is an error"); return false; @@ -2418,7 +2418,7 @@ NewSandbox(JSContext* cx, bool lazy) } static bool -EvalInContext(JSContext* cx, unsigned argc, jsval* vp) +EvalInContext(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!args.requireAtLeast(cx, "evalcx", 1)) @@ -2567,7 +2567,7 @@ WorkerMain(void* arg) Vector workerThreads; static bool -EvalInWorker(JSContext* cx, unsigned argc, jsval* vp) +EvalInWorker(JSContext* cx, unsigned argc, Value* vp) { if (!CanUseExtraThreads()) { JS_ReportError(cx, "Can't create worker threads with --no-threads"); @@ -2863,7 +2863,7 @@ InterruptIf(JSContext* cx, unsigned argc, Value* vp) } static bool -InvokeInterruptCallbackWrapper(JSContext* cx, unsigned argc, jsval* vp) +InvokeInterruptCallbackWrapper(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -3006,7 +3006,7 @@ StackPointerInfo(JSContext* cx, unsigned argc, Value* vp) static bool -Elapsed(JSContext* cx, unsigned argc, jsval* vp) +Elapsed(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { @@ -3022,7 +3022,7 @@ Elapsed(JSContext* cx, unsigned argc, jsval* vp) } static bool -Compile(JSContext* cx, unsigned argc, jsval* vp) +Compile(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 1) { @@ -3058,7 +3058,7 @@ Compile(JSContext* cx, unsigned argc, jsval* vp) } static bool -Parse(JSContext* cx, unsigned argc, jsval* vp) +Parse(JSContext* cx, unsigned argc, Value* vp) { using namespace js::frontend; @@ -3106,7 +3106,7 @@ Parse(JSContext* cx, unsigned argc, jsval* vp) } static bool -SyntaxParse(JSContext* cx, unsigned argc, jsval* vp) +SyntaxParse(JSContext* cx, unsigned argc, Value* vp) { using namespace js::frontend; @@ -3241,7 +3241,7 @@ OffThreadCompileScriptCallback(void* token, void* callbackData) } static bool -OffThreadCompileScript(JSContext* cx, unsigned argc, jsval* vp) +OffThreadCompileScript(JSContext* cx, unsigned argc, Value* vp) { if (!CanUseExtraThreads()) { JS_ReportError(cx, "Can't use offThreadCompileScript with --no-threads"); @@ -3331,7 +3331,7 @@ OffThreadCompileScript(JSContext* cx, unsigned argc, jsval* vp) } static bool -runOffThreadScript(JSContext* cx, unsigned argc, jsval* vp) +runOffThreadScript(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -3466,7 +3466,7 @@ PropagateFlagToNestedShells(const char* flag) } static bool -NestedShell(JSContext* cx, unsigned argc, jsval* vp) +NestedShell(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -3614,7 +3614,7 @@ ThisFilename(JSContext* cx, unsigned argc, Value* vp) } static bool -WrapWithProto(JSContext* cx, unsigned argc, jsval* vp) +WrapWithProto(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); Value obj = UndefinedValue(), proto = UndefinedValue(); @@ -3640,7 +3640,7 @@ WrapWithProto(JSContext* cx, unsigned argc, jsval* vp) } static bool -NewGlobal(JSContext* cx, unsigned argc, jsval* vp) +NewGlobal(JSContext* cx, unsigned argc, Value* vp) { JSPrincipals* principals = nullptr; JS::CompartmentOptions options; @@ -3688,7 +3688,7 @@ NewGlobal(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetMaxArgs(JSContext* cx, unsigned argc, jsval* vp) +GetMaxArgs(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setInt32(ARGS_LENGTH_MAX); @@ -3696,7 +3696,7 @@ GetMaxArgs(JSContext* cx, unsigned argc, jsval* vp) } static bool -ObjectEmulatingUndefined(JSContext* cx, unsigned argc, jsval* vp) +ObjectEmulatingUndefined(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -3713,7 +3713,7 @@ ObjectEmulatingUndefined(JSContext* cx, unsigned argc, jsval* vp) } static bool -GetSelfHostedValue(JSContext* cx, unsigned argc, jsval* vp) +GetSelfHostedValue(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -3765,7 +3765,7 @@ class ShellSourceHook: public SourceHook { }; static bool -WithSourceHook(JSContext* cx, unsigned argc, jsval* vp) +WithSourceHook(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject callee(cx, &args.callee()); @@ -4907,7 +4907,7 @@ DefineConsole(JSContext* cx, HandleObject global) #undef EXTERNAL_FUNCTION_COUNT static bool -PrintHelpString(JSContext* cx, jsval v) +PrintHelpString(JSContext* cx, Value v) { JSString* str = v.toString(); @@ -4945,7 +4945,7 @@ PrintHelp(JSContext* cx, HandleObject obj) } static bool -Help(JSContext* cx, unsigned argc, jsval* vp) +Help(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); fprintf(gOutFile, "%s\n", JS_GetImplementationVersion()); diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index 93456902c459..d4eab0157f42 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -264,7 +264,7 @@ struct JSStructuredCloneWriter { explicit JSStructuredCloneWriter(JSContext* cx, const JSStructuredCloneCallbacks* cb, void* cbClosure, - jsval tVal) + Value tVal) : out(cx), objs(out.context()), counts(out.context()), entries(out.context()), memory(out.context()), callbacks(cb), closure(cbClosure), @@ -364,7 +364,7 @@ ReportErrorTransferable(JSContext* cx, const JSStructuredCloneCallbacks* callbac bool WriteStructuredClone(JSContext* cx, HandleValue v, uint64_t** bufp, size_t* nbytesp, const JSStructuredCloneCallbacks* cb, void* cbClosure, - jsval transferable) + Value transferable) { JSStructuredCloneWriter w(cx, cb, cbClosure, transferable); return w.init() && w.write(v) && w.extractBuffer(bufp, nbytesp); @@ -618,7 +618,7 @@ SCOutput::writePair(uint32_t tag, uint32_t data) * This is because exponents occupy the last 2 bytes of doubles on the * little-endian platforms we care most about. * - * For example, JSVAL_TRUE is written using writePair(SCTAG_BOOLEAN, 1). + * For example, TrueValue() is written using writePair(SCTAG_BOOLEAN, 1). * PairToUInt64 produces the number 0xFFFF000200000001. * That is written out as the bytes 01 00 00 00 02 00 FF FF. */ diff --git a/js/src/vm/Value.cpp b/js/src/vm/Value.cpp index 4f47d9a57f2e..9bc22aec60d7 100644 --- a/js/src/vm/Value.cpp +++ b/js/src/vm/Value.cpp @@ -6,10 +6,10 @@ #include "js/Value.h" -static const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0)); -static const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false)); -static const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true)); -static const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0)); +static const JS::Value JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0)); +static const JS::Value JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false)); +static const JS::Value JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true)); +static const JS::Value JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0)); namespace JS { diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index f8d3aa1a13b9..c35a597a3cca 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -116,7 +116,7 @@ Dump(JSContext* cx, unsigned argc, Value* vp) } static bool -Debug(JSContext* cx, unsigned argc, jsval* vp) +Debug(JSContext* cx, unsigned argc, Value* vp) { #ifdef DEBUG return Dump(cx, argc, vp); diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index bcbdaf1b8df7..269ba3a12851 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -110,7 +110,7 @@ xpc::NewSandboxConstructor() } static bool -SandboxDump(JSContext* cx, unsigned argc, jsval* vp) +SandboxDump(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -147,7 +147,7 @@ SandboxDump(JSContext* cx, unsigned argc, jsval* vp) } static bool -SandboxDebug(JSContext* cx, unsigned argc, jsval* vp) +SandboxDebug(JSContext* cx, unsigned argc, Value* vp) { #ifdef DEBUG return SandboxDump(cx, argc, vp); @@ -299,7 +299,7 @@ SandboxFetch(JSContext* cx, JS::HandleObject scope, const CallArgs& args) return true; } -static bool SandboxFetchPromise(JSContext* cx, unsigned argc, jsval* vp) +static bool SandboxFetchPromise(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject callee(cx, &args.callee()); @@ -323,7 +323,7 @@ SandboxCreateFetch(JSContext* cx, HandleObject obj) } static bool -SandboxIsProxy(JSContext* cx, unsigned argc, jsval* vp) +SandboxIsProxy(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 1) { @@ -350,7 +350,7 @@ SandboxIsProxy(JSContext* cx, unsigned argc, jsval* vp) * [optional] object options) */ static bool -SandboxExportFunction(JSContext* cx, unsigned argc, jsval* vp) +SandboxExportFunction(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 2) { @@ -363,7 +363,7 @@ SandboxExportFunction(JSContext* cx, unsigned argc, jsval* vp) } static bool -SandboxCreateObjectIn(JSContext* cx, unsigned argc, jsval* vp) +SandboxCreateObjectIn(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 1) { @@ -389,7 +389,7 @@ SandboxCreateObjectIn(JSContext* cx, unsigned argc, jsval* vp) } static bool -SandboxCloneInto(JSContext* cx, unsigned argc, jsval* vp) +SandboxCloneInto(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 2) { diff --git a/js/xpconnect/src/XPCCallContext.cpp b/js/xpconnect/src/XPCCallContext.cpp index 57b891108af1..7dd594900394 100644 --- a/js/xpconnect/src/XPCCallContext.cpp +++ b/js/xpconnect/src/XPCCallContext.cpp @@ -22,8 +22,8 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage, HandleObject funobj /* = nullptr */, HandleId name /* = JSID_VOID */, unsigned argc /* = NO_ARGS */, - jsval* argv /* = nullptr */, - jsval* rval /* = nullptr */) + Value* argv /* = nullptr */, + Value* rval /* = nullptr */) : mAr(cx), mState(INIT_FAILED), mXPC(nsXPConnect::XPConnect()), @@ -166,8 +166,8 @@ XPCCallContext::SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member, void XPCCallContext::SetArgsAndResultPtr(unsigned argc, - jsval* argv, - jsval* rval) + Value* argv, + Value* rval) { CHECK_STATE(HAVE_OBJECT); @@ -287,7 +287,7 @@ XPCCallContext::GetArgc(uint32_t* aArgc) /* readonly attribute JSValPtr ArgvPtr; */ NS_IMETHODIMP -XPCCallContext::GetArgvPtr(jsval * *aArgvPtr) +XPCCallContext::GetArgvPtr(Value** aArgvPtr) { *aArgvPtr = mArgv; return NS_OK; diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index 367602b717f6..8beffbe3b6b1 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -460,7 +460,7 @@ XPCConvert::JSData2Native(void* d, HandleValue s, break; } case nsXPTType::T_JSVAL : - *((jsval*)d) = s; + *((Value*)d) = s; break; case nsXPTType::T_VOID: XPC_LOG_ERROR(("XPCConvert::JSData2Native : void* params not supported")); @@ -969,7 +969,7 @@ XPCConvert::ConstructException(nsresult rv, const char* message, nsISupports* data, nsIException** exceptn, JSContext* cx, - jsval* jsExceptionPtr) + Value* jsExceptionPtr) { MOZ_ASSERT(!cx == !jsExceptionPtr, "Expected cx and jsExceptionPtr to cooccur."); @@ -1159,7 +1159,7 @@ XPCConvert::JSValToXPCException(MutableHandleValue s, nullptr, exceptn, cx, s.address()); else { // XXX all this nsISupportsDouble code seems a little redundant - // now that we're storing the jsval in the exception... + // now that we're storing the Value in the exception... nsISupportsDouble* data; nsCOMPtr cm; if (NS_FAILED(NS_GetComponentManager(getter_AddRefs(cm))) || !cm || diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h index f73db94fa46b..b33eba5146a6 100644 --- a/js/xpconnect/src/XPCInlines.h +++ b/js/xpconnect/src/XPCInlines.h @@ -187,14 +187,14 @@ XPCCallContext::GetArgc() const return mArgc; } -inline jsval* +inline JS::Value* XPCCallContext::GetArgv() const { CHECK_STATE(READY_TO_CALL); return mArgv; } -inline jsval* +inline JS::Value* XPCCallContext::GetRetVal() const { CHECK_STATE(READY_TO_CALL); @@ -202,7 +202,7 @@ XPCCallContext::GetRetVal() const } inline void -XPCCallContext::SetRetVal(jsval val) +XPCCallContext::SetRetVal(JS::Value val) { CHECK_STATE(HAVE_ARGS); if (mRetVal) diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp index fd02323c23fe..61290e0f41b4 100644 --- a/js/xpconnect/src/XPCShellImpl.cpp +++ b/js/xpconnect/src/XPCShellImpl.cpp @@ -211,7 +211,7 @@ GetLine(JSContext* cx, char* bufp, FILE* file, const char* prompt) } static bool -ReadLine(JSContext* cx, unsigned argc, jsval* vp) +ReadLine(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -255,7 +255,7 @@ ReadLine(JSContext* cx, unsigned argc, jsval* vp) } static bool -Print(JSContext* cx, unsigned argc, jsval* vp) +Print(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); @@ -283,7 +283,7 @@ Print(JSContext* cx, unsigned argc, jsval* vp) } static bool -Dump(JSContext* cx, unsigned argc, jsval* vp) +Dump(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); @@ -316,7 +316,7 @@ Dump(JSContext* cx, unsigned argc, jsval* vp) } static bool -Load(JSContext* cx, unsigned argc, jsval* vp) +Load(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -365,7 +365,7 @@ Load(JSContext* cx, unsigned argc, jsval* vp) } static bool -Version(JSContext* cx, unsigned argc, jsval* vp) +Version(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); args.rval().setInt32(JS_GetVersion(cx)); @@ -376,7 +376,7 @@ Version(JSContext* cx, unsigned argc, jsval* vp) } static bool -Quit(JSContext* cx, unsigned argc, jsval* vp) +Quit(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -390,7 +390,7 @@ Quit(JSContext* cx, unsigned argc, jsval* vp) } static bool -DumpXPC(JSContext* cx, unsigned argc, jsval* vp) +DumpXPC(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = CallArgsFromVp(argc, vp); @@ -408,7 +408,7 @@ DumpXPC(JSContext* cx, unsigned argc, jsval* vp) } static bool -GC(JSContext* cx, unsigned argc, jsval* vp) +GC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); JSRuntime* rt = JS_GetRuntime(cx); @@ -422,7 +422,7 @@ GC(JSContext* cx, unsigned argc, jsval* vp) #ifdef JS_GC_ZEAL static bool -GCZeal(JSContext* cx, unsigned argc, jsval* vp) +GCZeal(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); uint32_t zeal; @@ -466,7 +466,7 @@ SendCommand(JSContext* cx, unsigned argc, Value* vp) } static bool -Options(JSContext* cx, unsigned argc, jsval* vp) +Options(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = CallArgsFromVp(argc, vp); RuntimeOptions oldRuntimeOptions = RuntimeOptionsRef(cx); @@ -571,7 +571,7 @@ XPCShellInterruptCallback(JSContext* cx) } static bool -SetInterruptCallback(JSContext* cx, unsigned argc, jsval* vp) +SetInterruptCallback(JSContext* cx, unsigned argc, Value* vp) { MOZ_ASSERT(sScriptedInterruptCallback.initialized()); @@ -600,7 +600,7 @@ SetInterruptCallback(JSContext* cx, unsigned argc, jsval* vp) } static bool -SimulateActivityCallback(JSContext* cx, unsigned argc, jsval* vp) +SimulateActivityCallback(JSContext* cx, unsigned argc, Value* vp) { // Sanity-check args. JS::CallArgs args = JS::CallArgsFromVp(argc, vp); @@ -613,7 +613,7 @@ SimulateActivityCallback(JSContext* cx, unsigned argc, jsval* vp) } static bool -RegisterAppManifest(JSContext* cx, unsigned argc, jsval* vp) +RegisterAppManifest(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); if (args.length() != 1) { diff --git a/js/xpconnect/src/XPCVariant.cpp b/js/xpconnect/src/XPCVariant.cpp index 9e04621035c0..c18400f896d0 100644 --- a/js/xpconnect/src/XPCVariant.cpp +++ b/js/xpconnect/src/XPCVariant.cpp @@ -29,7 +29,7 @@ NS_IMPL_CI_INTERFACE_GETTER(XPCVariant, XPCVariant, nsIVariant) NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant) NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant) -XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal) +XPCVariant::XPCVariant(JSContext* cx, Value aJSVal) : mJSVal(aJSVal), mCCGeneration(0) { nsVariant::Initialize(&mData); @@ -55,7 +55,7 @@ XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal) XPCTraceableVariant::~XPCTraceableVariant() { - jsval val = GetJSValPreserveColor(); + Value val = GetJSValPreserveColor(); MOZ_ASSERT(val.isGCThing(), "Must be traceable or unlinked"); @@ -97,7 +97,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END // static already_AddRefed -XPCVariant::newVariant(JSContext* cx, jsval aJSVal) +XPCVariant::newVariant(JSContext* cx, Value aJSVal) { nsRefPtr variant; diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp index 1619108c4cbe..572a0e7e33f7 100644 --- a/js/xpconnect/src/XPCWrappedJSClass.cpp +++ b/js/xpconnect/src/XPCWrappedJSClass.cpp @@ -322,7 +322,7 @@ nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx, if (!scriptEval.StartEvaluating(aJSObj)) return NS_ERROR_FAILURE; - // Wrap the string in a jsval after the AutoScriptEvaluate, so that the + // Wrap the string in a Value after the AutoScriptEvaluate, so that the // resulting value ends up in the correct compartment. nsStringBuffer* buf; RootedValue value(cx); @@ -943,8 +943,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex, const XPTMethodDescriptor* info_, nsXPTCMiniVariant* nativeParams) { - jsval* sp = nullptr; - jsval* argv = nullptr; + Value* sp = nullptr; + Value* argv = nullptr; uint8_t i; nsresult retval = NS_ERROR_FAILURE; bool success; diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index e96eb385abd6..a7420b55f177 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -1299,7 +1299,7 @@ class MOZ_STACK_CLASS CallMethodHelper uint8_t mJSContextIndex; // TODO make const uint8_t mOptArgcIndex; // TODO make const - jsval* const mArgv; + Value* const mArgv; const uint32_t mArgc; MOZ_ALWAYS_INLINE bool @@ -1559,7 +1559,7 @@ CallMethodHelper::GetOutParamSource(uint8_t paramIndex, MutableHandleValue srcp) if (paramInfo.IsOut() && !paramInfo.IsRetval()) { MOZ_ASSERT(paramIndex < mArgc || paramInfo.IsOptional(), "Expected either enough arguments or an optional argument"); - jsval arg = paramIndex < mArgc ? mArgv[paramIndex] : JS::NullValue(); + Value arg = paramIndex < mArgc ? mArgv[paramIndex] : JS::NullValue(); if (paramIndex < mArgc) { RootedObject obj(mCallContext); if (!arg.isPrimitive()) @@ -2040,7 +2040,7 @@ CallMethodHelper::CleanupParam(nsXPTCMiniVariant& param, nsXPTType& type) switch (type.TagPart()) { case nsXPTType::T_JSVAL: - js::RemoveRawValueRoot(mCallContext, (jsval*)¶m.val); + js::RemoveRawValueRoot(mCallContext, (Value*)¶m.val); break; case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE_IS: diff --git a/js/xpconnect/src/XPCWrappedNativeInfo.cpp b/js/xpconnect/src/XPCWrappedNativeInfo.cpp index 79170f90cb59..48816435fae8 100644 --- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp +++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp @@ -27,7 +27,7 @@ XPCNativeMember::GetCallInfo(JSObject* funobj, XPCNativeMember** pMember) { funobj = js::UncheckedUnwrap(funobj); - jsval memberVal = + Value memberVal = js::GetFunctionNativeReserved(funobj, XPC_FUNCTION_NATIVE_MEMBER_SLOT); @@ -40,7 +40,7 @@ XPCNativeMember::GetCallInfo(JSObject* funobj, bool XPCNativeMember::NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface, HandleObject parent, - jsval* pval) + Value* pval) { MOZ_ASSERT(!IsConstant(), "Only call this if you're sure this is not a constant!"); @@ -49,7 +49,7 @@ XPCNativeMember::NewFunctionObject(XPCCallContext& ccx, bool XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface, - HandleObject parent, jsval* vp) + HandleObject parent, Value* vp) { MOZ_ASSERT(iface == GetInterface()); if (IsConstant()) { diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index a3f62b34098c..80ce3202347d 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -68,7 +68,7 @@ ToStringGuts(XPCCallContext& ccx) /***************************************************************************/ static bool -XPC_WN_Shared_ToString(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_Shared_ToString(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); @@ -84,7 +84,7 @@ XPC_WN_Shared_ToString(JSContext* cx, unsigned argc, jsval* vp) } static bool -XPC_WN_Shared_ToSource(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_Shared_ToSource(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); static const char empty[] = "({})"; @@ -136,7 +136,7 @@ GetDoubleWrappedJSObject(XPCCallContext& ccx, XPCWrappedNative* wrapper) // double wrapped JSObjects. static bool -XPC_WN_DoubleWrappedGetter(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_DoubleWrappedGetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -778,7 +778,7 @@ XPC_WN_Helper_SetProperty(JSContext* cx, HandleObject obj, HandleId id, } static bool -XPC_WN_Helper_Call(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_Helper_Call(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // N.B. we want obj to be the callee, not JS_THIS(cx, vp) @@ -795,7 +795,7 @@ XPC_WN_Helper_Call(JSContext* cx, unsigned argc, jsval* vp) } static bool -XPC_WN_Helper_Construct(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_Helper_Construct(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); RootedObject obj(cx, &args.callee()); @@ -1119,7 +1119,7 @@ FixUpThisIfBroken(JSObject* obj, JSObject* funobj) } bool -XPC_WN_CallMethod(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_CallMethod(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); MOZ_ASSERT(JS_TypeOfValue(cx, args.calleev()) == JSTYPE_FUNCTION, "bad function"); @@ -1145,7 +1145,7 @@ XPC_WN_CallMethod(JSContext* cx, unsigned argc, jsval* vp) } bool -XPC_WN_GetterSetter(JSContext* cx, unsigned argc, jsval* vp) +XPC_WN_GetterSetter(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); MOZ_ASSERT(JS_TypeOfValue(cx, args.calleev()) == JSTYPE_FUNCTION, "bad function"); diff --git a/js/xpconnect/src/XPCWrapper.cpp b/js/xpconnect/src/XPCWrapper.cpp index 1c8b41944427..a6b331017fb0 100644 --- a/js/xpconnect/src/XPCWrapper.cpp +++ b/js/xpconnect/src/XPCWrapper.cpp @@ -11,6 +11,7 @@ using namespace xpc; using namespace mozilla; +using namespace JS; namespace XPCNativeWrapper { @@ -24,7 +25,7 @@ ThrowException(nsresult ex, JSContext* cx) } static bool -UnwrapNW(JSContext* cx, unsigned argc, jsval* vp) +UnwrapNW(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); if (args.length() != 1) { @@ -45,7 +46,7 @@ UnwrapNW(JSContext* cx, unsigned argc, jsval* vp) } static bool -XrayWrapperConstructor(JSContext* cx, unsigned argc, jsval* vp) +XrayWrapperConstructor(JSContext* cx, unsigned argc, Value* vp) { JS::CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 904d3d02cd9d..70205ee0dead 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -635,7 +635,7 @@ private: static const char* const mStrings[IDX_TOTAL_COUNT]; jsid mStrIDs[IDX_TOTAL_COUNT]; - jsval mStrJSVals[IDX_TOTAL_COUNT]; + JS::Value mStrJSVals[IDX_TOTAL_COUNT]; XPCJSContextStack* mJSContextStack; XPCCallContext* mCallContext; @@ -798,7 +798,7 @@ public: NS_IMETHOD GetCalleeMethodIndex(uint16_t* aResult); NS_IMETHOD GetJSContext(JSContext** aResult); NS_IMETHOD GetArgc(uint32_t* aResult); - NS_IMETHOD GetArgvPtr(jsval** aResult); + NS_IMETHOD GetArgvPtr(JS::Value** aResult); NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo** aResult); NS_IMETHOD GetCalleeClassInfo(nsIClassInfo** aResult); NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext** aResult); @@ -814,8 +814,8 @@ public: JS::HandleObject funobj = nullptr, JS::HandleId id = JSID_VOIDHANDLE, unsigned argc = NO_ARGS, - jsval* argv = nullptr, - jsval* rval = nullptr); + JS::Value* argv = nullptr, + JS::Value* rval = nullptr); virtual ~XPCCallContext(); @@ -847,8 +847,8 @@ public: inline jsid GetName() const ; inline bool GetStaticMemberIsLocal() const ; inline unsigned GetArgc() const ; - inline jsval* GetArgv() const ; - inline jsval* GetRetVal() const ; + inline JS::Value* GetArgv() const ; + inline JS::Value* GetRetVal() const ; inline uint16_t GetMethodIndex() const ; inline void SetMethodIndex(uint16_t index) ; @@ -859,10 +859,10 @@ public: inline XPCWrappedNative* GetResolvingWrapper() const; inline XPCWrappedNative* SetResolvingWrapper(XPCWrappedNative* w); - inline void SetRetVal(jsval val); + inline void SetRetVal(JS::Value val); void SetName(jsid name); - void SetArgsAndResultPtr(unsigned argc, jsval* argv, jsval* rval); + void SetArgsAndResultPtr(unsigned argc, JS::Value* argv, JS::Value* rval); void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member, bool isSetter); @@ -927,8 +927,8 @@ private: bool mStaticMemberIsLocal; unsigned mArgc; - jsval* mArgv; - jsval* mRetVal; + JS::Value* mArgv; + JS::Value* mRetVal; uint16_t mMethodIndex; }; @@ -956,10 +956,10 @@ extern const js::Class XPC_WN_Tearoff_JSClass; extern const js::Class XPC_WN_NoHelper_Proto_JSClass; extern bool -XPC_WN_CallMethod(JSContext* cx, unsigned argc, jsval* vp); +XPC_WN_CallMethod(JSContext* cx, unsigned argc, JS::Value* vp); extern bool -XPC_WN_GetterSetter(JSContext* cx, unsigned argc, jsval* vp); +XPC_WN_GetterSetter(JSContext* cx, unsigned argc, JS::Value* vp); extern JSObject* XPC_WN_JSOp_ThisObject(JSContext* cx, JS::HandleObject obj); @@ -1290,13 +1290,13 @@ public: uint16_t GetIndex() const {return mIndex;} bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface, - jsval* pval) + JS::Value* pval) {MOZ_ASSERT(IsConstant(), "Only call this if you're sure this is a constant!"); return Resolve(ccx, iface, nullptr, pval);} bool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface, - JS::HandleObject parent, jsval* pval); + JS::HandleObject parent, JS::Value* pval); bool IsMethod() const {return 0 != (mFlags & METHOD);} @@ -1342,7 +1342,7 @@ public: private: bool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface, - JS::HandleObject parent, jsval* vp); + JS::HandleObject parent, JS::Value* vp); enum { METHOD = 0x01, @@ -2583,9 +2583,9 @@ public: static bool IsMethodReflectable(const XPTMethodDescriptor& info); /** - * Convert a native object into a jsval. + * Convert a native object into a JS::Value. * - * @param d [out] the resulting jsval + * @param d [out] the resulting JS::Value * @param s the native object we're working with * @param type the type of object that s is * @param iid the interface of s that we want @@ -2639,9 +2639,9 @@ public: static bool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface); /** - * Convert a native array into a jsval. + * Convert a native array into a JS::Value. * - * @param d [out] the resulting jsval + * @param d [out] the resulting JS::Value * @param s the native array we're working with * @param type the type of objects in the array * @param iid the interface of each object in the array that we want @@ -2689,7 +2689,7 @@ public: nsISupports* data, nsIException** exception, JSContext* cx, - jsval* jsExceptionPtr); + JS::Value* jsExceptionPtr); private: XPCConvert(); // not implemented @@ -3285,21 +3285,21 @@ public: // if a given nsIVariant is in fact an XPCVariant. NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID) - static already_AddRefed newVariant(JSContext* cx, jsval aJSVal); + static already_AddRefed newVariant(JSContext* cx, JS::Value aJSVal); /** - * This getter clears the gray bit before handing out the jsval if the jsval + * This getter clears the gray bit before handing out the Value if the Value * represents a JSObject. That means that the object is guaranteed to be * kept alive past the next CC. */ - jsval GetJSVal() const { + JS::Value GetJSVal() const { if (!mJSVal.isPrimitive()) JS::ExposeObjectToActiveJS(&mJSVal.toObject()); return mJSVal; } /** - * This getter does not change the color of the jsval (if it represents a + * This getter does not change the color of the Value (if it represents a * JSObject) meaning that the value returned is not guaranteed to be kept * alive past the next CC. * @@ -3307,12 +3307,12 @@ public: * be passed into a JS API function and that it won't be stored without * being rooted (or otherwise signaling the stored value to the CC). */ - jsval GetJSValPreserveColor() const {return mJSVal;} + JS::Value GetJSValPreserveColor() const {return mJSVal;} - XPCVariant(JSContext* cx, jsval aJSVal); + XPCVariant(JSContext* cx, JS::Value aJSVal); /** - * Convert a variant into a jsval. + * Convert a variant into a JS::Value. * * @param ccx the context for the whole procedure * @param variant the variant to convert @@ -3357,7 +3357,7 @@ class XPCTraceableVariant: public XPCVariant, public XPCRootSetElem { public: - XPCTraceableVariant(JSContext* cx, jsval aJSVal) + XPCTraceableVariant(JSContext* cx, JS::Value aJSVal) : XPCVariant(cx, aJSVal) { nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this); @@ -3390,10 +3390,10 @@ NewAddonId(JSContext* cx, const nsACString& id); // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes. bool -Atob(JSContext* cx, unsigned argc, jsval* vp); +Atob(JSContext* cx, unsigned argc, JS::Value* vp); bool -Btoa(JSContext* cx, unsigned argc, jsval* vp); +Btoa(JSContext* cx, unsigned argc, JS::Value* vp); // Helper function that creates a JSFunction that wraps a native function that // forwards the call to the original 'callable'. diff --git a/layout/base/ActiveLayerTracker.cpp b/layout/base/ActiveLayerTracker.cpp index eaefc102a901..9e6a30961ec0 100644 --- a/layout/base/ActiveLayerTracker.cpp +++ b/layout/base/ActiveLayerTracker.cpp @@ -5,6 +5,7 @@ #include "ActiveLayerTracker.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/gfx/Matrix.h" #include "nsExpirationTracker.h" #include "nsContainerFrame.h" #include "nsIContent.h" @@ -12,11 +13,14 @@ #include "nsPIDOMWindow.h" #include "nsIDocument.h" #include "nsAnimationManager.h" +#include "nsStyleTransformMatrix.h" #include "nsTransitionManager.h" #include "nsDisplayList.h" namespace mozilla { +using namespace gfx; + /** * This tracks the state of a frame that may need active layers due to * ongoing content changes or style changes that indicate animation. @@ -34,6 +38,7 @@ public: , mContent(nullptr) , mOpacityRestyleCount(0) , mTransformRestyleCount(0) + , mScaleRestyleCount(0) , mLeftRestyleCount(0) , mTopRestyleCount(0) , mRightRestyleCount(0) @@ -71,9 +76,14 @@ public: nsIContent* mContent; nsExpirationState mState; + + // Previous scale due to the CSS transform property. + Maybe mPreviousTransformScale; + // Number of restyle operations detected uint8_t mOpacityRestyleCount; uint8_t mTransformRestyleCount; + uint8_t mScaleRestyleCount; uint8_t mLeftRestyleCount; uint8_t mTopRestyleCount; uint8_t mRightRestyleCount; @@ -206,12 +216,54 @@ ActiveLayerTracker::TransferActivityToFrame(nsIContent* aContent, nsIFrame* aFra aFrame->Properties().Set(LayerActivityProperty(), layerActivity); } +static void +IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity) +{ + const nsStyleDisplay* display = aFrame->StyleDisplay(); + if (!display->mSpecifiedTransform) { + // The transform was removed. + aActivity->mPreviousTransformScale = Nothing(); + IncrementMutationCount(&aActivity->mScaleRestyleCount); + return; + } + + // Compute the new scale due to the CSS transform property. + nsPresContext* presContext = aFrame->PresContext(); + RuleNodeCacheConditions dummy; + nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame); + Matrix4x4 transform = ToMatrix4x4( + nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead, + aFrame->StyleContext(), + presContext, + dummy, refBox, + presContext->AppUnitsPerCSSPixel())); + Matrix transform2D; + if (!transform.Is2D(&transform2D)) { + // We don't attempt to handle 3D transforms; just assume the scale changed. + aActivity->mPreviousTransformScale = Nothing(); + IncrementMutationCount(&aActivity->mScaleRestyleCount); + return; + } + + gfxSize scale = ThebesMatrix(transform2D).ScaleFactors(true); + if (aActivity->mPreviousTransformScale == Some(scale)) { + return; // Nothing changed. + } + + aActivity->mPreviousTransformScale = Some(scale); + IncrementMutationCount(&aActivity->mScaleRestyleCount); +} + /* static */ void ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty) { LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame); uint8_t& mutationCount = layerActivity->RestyleCountForProperty(aProperty); IncrementMutationCount(&mutationCount); + + if (aProperty == eCSSProperty_transform) { + IncrementScaleRestyleCountIfNeeded(aFrame, layerActivity); + } } /* static */ void @@ -313,6 +365,76 @@ ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame) return false; } +// A helper function for IsScaleSubjectToAnimation which returns true if the +// given AnimationCollection contains a current effect that animates scale. +static bool +ContainsAnimatedScale(AnimationCollection* aCollection, nsIFrame* aFrame) +{ + if (!aCollection) { + return false; + } + + for (dom::Animation* anim : aCollection->mAnimations) { + if (!anim->HasCurrentEffect()) { + continue; + } + KeyframeEffectReadOnly* effect = anim->GetEffect(); + for (const AnimationProperty& prop : effect->Properties()) { + if (prop.mProperty != eCSSProperty_transform) { + continue; + } + for (AnimationPropertySegment segment : prop.mSegments) { + gfxSize from = segment.mFromValue.GetScaleValue(aFrame); + if (from != gfxSize(1.0f, 1.0f)) { + return true; + } + gfxSize to = segment.mToValue.GetScaleValue(aFrame); + if (to != gfxSize(1.0f, 1.0f)) { + return true; + } + } + } + } + + return false; +} + +/* static */ bool +ActiveLayerTracker::IsScaleSubjectToAnimation(nsIFrame* aFrame) +{ + // Check whether JavaScript is animating this frame's scale. + LayerActivity* layerActivity = GetLayerActivity(aFrame); + if (layerActivity && layerActivity->mScaleRestyleCount >= 2) { + return true; + } + + nsIContent* content = aFrame->GetContent(); + if (!content || !content->IsElement()) { + return false; + } + + nsCSSPseudoElements::Type pseudoType = + aFrame->StyleContext()->GetPseudoType(); + + // Check if any transitions associated with this frame may animate its scale. + AnimationCollection* transitions = + aFrame->PresContext()->TransitionManager()->GetAnimations( + content->AsElement(), pseudoType, false /* don't create */); + if (ContainsAnimatedScale(transitions, aFrame)) { + return true; + } + + // Check if any animations associated with this frame may animate its scale. + AnimationCollection* animations = + aFrame->PresContext()->AnimationManager()->GetAnimations( + content->AsElement(), pseudoType, false /* don't create */); + if (ContainsAnimatedScale(animations, aFrame)) { + return true; + } + + return false; +} + /* static */ void ActiveLayerTracker::NotifyContentChange(nsIFrame* aFrame) { diff --git a/layout/base/ActiveLayerTracker.h b/layout/base/ActiveLayerTracker.h index 7ac336faa91e..92d2736611e1 100644 --- a/layout/base/ActiveLayerTracker.h +++ b/layout/base/ActiveLayerTracker.h @@ -72,6 +72,14 @@ public: * as being animated for constructing active layers. */ static bool IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame); + + /** + * Return true if aFrame either has an animated scale now, or is likely to + * have one in the future because it has a CSS animation or transition + * (which may not be playing right now) that affects its scale. + */ + static bool IsScaleSubjectToAnimation(nsIFrame* aFrame); + /** * Transfer the LayerActivity property to the frame's content node when the * frame is about to be destroyed so that layer activity can be tracked diff --git a/layout/base/Units.h b/layout/base/Units.h index 93410d2579ca..d40ad4bbb3bc 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -373,6 +373,10 @@ struct RenderTargetPixel { * generally be represented in ScreenPixel units. */ struct ScreenPixel { + static nsIntSize ToUntyped(const ScreenIntSize& aSize) { + return nsIntSize(aSize.width, aSize.height); + } + static ScreenIntPoint FromUntyped(const nsIntPoint& aPoint) { return ScreenIntPoint(aPoint.x, aPoint.y); } diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index a5662e7ce95a..555a28033aa4 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -2502,10 +2502,11 @@ nsDocumentViewer::FindContainerView() static_cast(subdocFrame)->EnsureInnerView(); containerView = innerView; } else { - NS_WARNING("Subdocument container has non-subdocument frame"); + NS_WARN_IF_FALSE(!subdocFrame->GetType(), + "Subdocument container has non-subdocument frame"); } } else { - // XXX Silenced by default in bug 117528 + // XXX Silenced by default in bug 1175289 LAYOUT_WARNING("Subdocument container has no frame"); } } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 97b9c8cf56c3..2c3614ef90f3 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -443,38 +443,6 @@ nsLayoutUtils::HasCurrentAnimationsForProperties(const nsIFrame* aFrame, return false; } -static gfxSize -GetScaleForValue(const StyleAnimationValue& aValue, const nsIFrame* aFrame) -{ - if (!aFrame) { - NS_WARNING("No frame."); - return gfxSize(); - } - if (aValue.GetUnit() != StyleAnimationValue::eUnit_Transform) { - NS_WARNING("Expected a transform."); - return gfxSize(); - } - - nsCSSValueSharedList* list = aValue.GetCSSValueSharedListValue(); - MOZ_ASSERT(list->mHead); - - RuleNodeCacheConditions dontCare; - TransformReferenceBox refBox(aFrame); - gfx3DMatrix transform = nsStyleTransformMatrix::ReadTransforms( - list->mHead, - aFrame->StyleContext(), - aFrame->PresContext(), dontCare, refBox, - aFrame->PresContext()->AppUnitsPerDevPixel()); - - gfxMatrix transform2d; - bool canDraw2D = transform.CanDraw2D(&transform2d); - if (!canDraw2D) { - return gfxSize(); - } - - return transform2d.ScaleFactors(true); -} - static float GetSuitableScale(float aMaxScale, float aMinScale, nscoord aVisibleDimension, nscoord aDisplayDimension) @@ -505,12 +473,12 @@ GetMinAndMaxScaleForAnimationProperty(const nsIFrame* aFrame, if (prop.mProperty == eCSSProperty_transform) { for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) { AnimationPropertySegment& segment = prop.mSegments[segIdx]; - gfxSize from = GetScaleForValue(segment.mFromValue, aFrame); + gfxSize from = segment.mFromValue.GetScaleValue(aFrame); aMaxScale.width = std::max(aMaxScale.width, from.width); aMaxScale.height = std::max(aMaxScale.height, from.height); aMinScale.width = std::min(aMinScale.width, from.width); aMinScale.height = std::min(aMinScale.height, from.height); - gfxSize to = GetScaleForValue(segment.mToValue, aFrame); + gfxSize to = segment.mToValue.GetScaleValue(aFrame); aMaxScale.width = std::max(aMaxScale.width, to.width); aMaxScale.height = std::max(aMaxScale.height, to.height); aMinScale.width = std::min(aMinScale.width, to.width); @@ -2406,6 +2374,42 @@ nsLayoutUtils::GetTransformToAncestorScale(nsIFrame* aFrame) return gfxSize(1, 1); } +static Matrix4x4 +GetTransformToAncestorExcludingAnimated(nsIFrame* aFrame, + const nsIFrame* aAncestor) +{ + nsIFrame* parent; + Matrix4x4 ctm; + if (aFrame == aAncestor) { + return ctm; + } + if (ActiveLayerTracker::IsScaleSubjectToAnimation(aFrame)) { + return ctm; + } + ctm = aFrame->GetTransformMatrix(aAncestor, &parent); + while (parent && parent != aAncestor) { + if (ActiveLayerTracker::IsScaleSubjectToAnimation(parent)) { + return Matrix4x4(); + } + if (!parent->Preserves3DChildren()) { + ctm.ProjectTo2D(); + } + ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent); + } + return ctm; +} + +gfxSize +nsLayoutUtils::GetTransformToAncestorScaleExcludingAnimated(nsIFrame* aFrame) +{ + Matrix4x4 transform = GetTransformToAncestorExcludingAnimated(aFrame, + nsLayoutUtils::GetDisplayRootFrame(aFrame)); + Matrix transform2D; + if (transform.Is2D(&transform2D)) { + return ThebesMatrix(transform2D).ScaleFactors(true); + } + return gfxSize(1, 1); +} nsIFrame* nsLayoutUtils::FindNearestCommonAncestorFrame(nsIFrame* aFrame1, nsIFrame* aFrame2) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 45d04a13a908..3391d66d2cce 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -808,6 +808,14 @@ public: */ static gfxSize GetTransformToAncestorScale(nsIFrame* aFrame); + /** + * Gets the scale factors of the transform for aFrame relative to the root + * frame if this transform is 2D, or the identity scale factors otherwise. + * If some frame on the path from aFrame to the display root frame may have an + * animated scale, returns the identity scale factors. + */ + static gfxSize GetTransformToAncestorScaleExcludingAnimated(nsIFrame* aFrame); + /** * Find the nearest common ancestor frame for aFrame1 and aFrame2. The * ancestor frame could be cross-doc. diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index a5cc1eda4e0c..0c577eddc2b2 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -7809,7 +7809,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus) // ESC key released while in DOM fullscreen mode. // Fully exit all browser windows and documents from // fullscreen mode. - nsIDocument::ExitFullscreen(nullptr, /* async */ true); + nsIDocument::AsyncExitFullscreen(nullptr); } } nsCOMPtr pointerLockedDoc = diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index d8df0809e515..a720d422888d 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -577,6 +577,10 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); } + } else { + // We've already gotten the initial reflow, and our size hasn't changed, + // so we're ready to request a decode. + MaybeDecodeForPredictedSize(); } } @@ -682,12 +686,93 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest, presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); } + } else { + // We've already gotten the initial reflow, and our size hasn't changed, + // so we're ready to request a decode. + MaybeDecodeForPredictedSize(); } // Update border+content to account for image change InvalidateFrame(); } } +void +nsImageFrame::MaybeDecodeForPredictedSize() +{ + // Check that we're ready to decode. + if (!mImage) { + return; // Nothing to do yet. + } + + if (mComputedSize.IsEmpty()) { + return; // We won't draw anything, so no point in decoding. + } + + nsCOMPtr imageLoader = do_QueryInterface(mContent); + MOZ_ASSERT(imageLoader); + if (imageLoader->GetVisibleCount() == 0) { + return; // We're not visible, so don't decode. + } + + // OK, we're ready to decode. Compute the scale to the screen... + nsIPresShell* presShell = PresContext()->GetPresShell(); + LayoutDeviceToScreenScale2D resolutionToScreen( + presShell->GetCumulativeResolution() + * nsLayoutUtils::GetTransformToAncestorScaleExcludingAnimated(this)); + + // ...and this frame's content box... + const nsPoint offset = + GetOffsetToCrossDoc(nsLayoutUtils::GetReferenceFrame(this)); + const nsRect frameContentBox = GetInnerArea() + offset; + + // ...and our predicted dest rect... + const int32_t factor = PresContext()->AppUnitsPerDevPixel(); + const LayoutDeviceRect destRect = + LayoutDeviceRect::FromAppUnits(PredictedDestRect(frameContentBox), factor); + + // ...and use them to compute our predicted size in screen pixels. + const ScreenSize predictedScreenSize = destRect.Size() * resolutionToScreen; + const ScreenIntSize predictedScreenIntSize = RoundedToInt(predictedScreenSize); + if (predictedScreenIntSize.IsEmpty()) { + return; + } + + // Determine the optimal image size to use. + uint32_t flags = imgIContainer::FLAG_HIGH_QUALITY_SCALING + | imgIContainer::FLAG_ASYNC_NOTIFY; + GraphicsFilter filter = nsLayoutUtils::GetGraphicsFilterForFrame(this); + gfxSize gfxPredictedScreenSize = gfxSize(predictedScreenIntSize.width, + predictedScreenIntSize.height); + nsIntSize predictedImageSize = + mImage->OptimalImageSizeForDest(gfxPredictedScreenSize, + imgIContainer::FRAME_CURRENT, + filter, flags); + + // Request a decode. + mImage->RequestDecodeForSize(predictedImageSize, flags); +} + +nsRect +nsImageFrame::PredictedDestRect(const nsRect& aFrameContentBox) +{ + // What is the rect painted by the image? It's the image's "dest rect" (the + // rect where a full copy of the image is mapped), clipped to the container's + // content box. So, we intersect those rects. + + // Note: To get the "dest rect", we have to provide the "constraint rect" + // (which is the content-box, with the effects of fragmentation undone). + nsRect constraintRect(aFrameContentBox.TopLeft(), mComputedSize); + constraintRect.y -= GetContinuationOffset(); + + const nsRect destRect = + nsLayoutUtils::ComputeObjectDestRect(constraintRect, + mIntrinsicSize, + mIntrinsicRatio, + StylePosition()); + + return destRect.Intersect(aFrameContentBox); +} + void nsImageFrame::EnsureIntrinsicSizeAndRatio() { @@ -935,6 +1020,10 @@ nsImageFrame::Reflow(nsPresContext* aPresContext, static_assert(eOverflowType_LENGTH == 2, "Unknown overflow types?"); nsRect& visualOverflow = aMetrics.VisualOverflow(); visualOverflow.UnionRect(visualOverflow, altFeedbackSize); + } else { + // We've just reflowed and we should have an accurate size, so we're ready + // to request a decode. + MaybeDecodeForPredictedSize(); } FinishAndStoreOverflow(&aMetrics); @@ -1475,30 +1564,14 @@ nsDisplayImage::GetContainer(LayerManager* aManager, nsRect nsDisplayImage::GetDestRect(bool* aSnap) { - // OK, we want to return the entire region painted by the image. But what is - // that region? It's the image's "dest rect" (the rect where a full copy of - // the image is mapped), clipped to the container's content box (which is what - // GetBounds() returns). So, we grab those rects and intersect them. bool snap = true; const nsRect frameContentBox = GetBounds(&snap); if (aSnap) { *aSnap = snap; } - // Note: To get the "dest rect", we have to provide the "constraint rect" - // (which is the content-box, with the effects of fragmentation undone). nsImageFrame* imageFrame = static_cast(mFrame); - nsRect constraintRect(frameContentBox.TopLeft(), - imageFrame->mComputedSize); - constraintRect.y -= imageFrame->GetContinuationOffset(); - - const nsRect destRect = - nsLayoutUtils::ComputeObjectDestRect(constraintRect, - imageFrame->mIntrinsicSize, - imageFrame->mIntrinsicRatio, - imageFrame->StylePosition()); - - return destRect.Intersect(frameContentBox); + return imageFrame->PredictedDestRect(frameContentBox); } LayerState diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index a3ce60f940f1..155e7669d667 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -219,6 +219,14 @@ protected: const nsRect& aDirtyRect, imgIContainer* aImage, uint32_t aFlags); + /** + * If we're ready to decode - that is, if our current request's image is + * available and our decoding heuristics are satisfied - then trigger a decode + * for our image at the size we predict it will be drawn next time it's + * painted. + */ + void MaybeDecodeForPredictedSize(); + protected: friend class nsImageListener; friend class nsImageLoadingContent; @@ -235,6 +243,13 @@ protected: /// Always sync decode our image when painting if @aForce is true. void SetForceSyncDecoding(bool aForce) { mForceSyncDecoding = aForce; } + /** + * Computes the predicted dest rect that we'll draw into, in app units, based + * upon the provided frame content box. (The content box is what + * nsDisplayImage::GetBounds() returns.) + */ + nsRect PredictedDestRect(const nsRect& aFrameContentBox); + private: // random helpers inline void SpecToURI(const nsAString& aSpec, nsIIOService *aIOService, diff --git a/layout/reftests/writing-mode/tables/reftest.list b/layout/reftests/writing-mode/tables/reftest.list index 35555b1b48f3..5fc2cdddcc90 100644 --- a/layout/reftests/writing-mode/tables/reftest.list +++ b/layout/reftests/writing-mode/tables/reftest.list @@ -88,3 +88,6 @@ fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1b.html border-collapse-b fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1c.html border-collapse-bevels-1-ref.html fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1d.html border-collapse-bevels-1-ref.html fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1e.html border-collapse-bevels-1-ref.html + +== vertical-rl-row-progression-1a.html vertical-rl-row-progression-1-ref.html +== vertical-rl-row-progression-1b.html vertical-rl-row-progression-1-ref.html diff --git a/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1-ref.html b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1-ref.html new file mode 100644 index 000000000000..60afb00d9bc9 --- /dev/null +++ b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1-ref.html @@ -0,0 +1,50 @@ + +CSS Reference: vertical-rl Table Row/Rowgroup/Cell Ordering + + + + + + + + + + +
+ + + +
+ + + + +
+ + +
+ +
diff --git a/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1a.html b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1a.html new file mode 100644 index 000000000000..6b0929495f3e --- /dev/null +++ b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1a.html @@ -0,0 +1,57 @@ + +CSS Test: vertical-rl Table Row/Rowgroup/Cell Ordering + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ +
+
+ +
diff --git a/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1b.html b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1b.html new file mode 100644 index 000000000000..69f4f52e6ce3 --- /dev/null +++ b/layout/reftests/writing-mode/tables/vertical-rl-row-progression-1b.html @@ -0,0 +1,57 @@ + +CSS Test: vertical-rl Table Row/Rowgroup/Cell Ordering + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ +
+
+ +
diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index c50cdf1a518f..3a68c4054e4c 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -25,6 +25,7 @@ #include "gfxMatrix.h" #include "gfxQuaternion.h" #include "nsIDocument.h" +#include "nsIFrame.h" #include "gfx2DGlue.h" using namespace mozilla; @@ -3526,6 +3527,32 @@ StyleAnimationValue::ExtractComputedValue(nsCSSProperty aProperty, return false; } +gfxSize +StyleAnimationValue::GetScaleValue(const nsIFrame* aForFrame) const +{ + MOZ_ASSERT(aForFrame); + MOZ_ASSERT(GetUnit() == StyleAnimationValue::eUnit_Transform); + + nsCSSValueSharedList* list = GetCSSValueSharedListValue(); + MOZ_ASSERT(list->mHead); + + RuleNodeCacheConditions dontCare; + nsStyleTransformMatrix::TransformReferenceBox refBox(aForFrame); + gfx3DMatrix transform = nsStyleTransformMatrix::ReadTransforms( + list->mHead, + aForFrame->StyleContext(), + aForFrame->PresContext(), dontCare, refBox, + aForFrame->PresContext()->AppUnitsPerDevPixel()); + + gfxMatrix transform2d; + bool canDraw2D = transform.CanDraw2D(&transform2d); + if (!canDraw2D) { + return gfxSize(); + } + + return transform2d.ScaleFactors(true); +} + StyleAnimationValue::StyleAnimationValue(int32_t aInt, Unit aUnit, IntegerConstructorType) { diff --git a/layout/style/StyleAnimationValue.h b/layout/style/StyleAnimationValue.h index e95f802e3fa8..d232b38779b0 100644 --- a/layout/style/StyleAnimationValue.h +++ b/layout/style/StyleAnimationValue.h @@ -15,6 +15,7 @@ #include "nsColor.h" #include "nsCSSValue.h" +class nsIFrame; class nsStyleContext; class gfx3DMatrix; @@ -317,6 +318,9 @@ public: mValue.mString->ToString(len, aBuffer); } + /// @return the scale for this value, calculated with reference to @aForFrame. + gfxSize GetScaleValue(const nsIFrame* aForFrame) const; + explicit StyleAnimationValue(Unit aUnit = eUnit_Null) : mUnit(aUnit) { NS_ASSERTION(aUnit == eUnit_Null || aUnit == eUnit_Normal || aUnit == eUnit_Auto || aUnit == eUnit_None, diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 01907966f2db..f55b38d2ce42 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -15,6 +15,7 @@ #include "nsIViewSourceChannel.h" #include "nsContentUtils.h" #include "nsProxyRelease.h" +#include "nsContentSecurityManager.h" #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" @@ -861,6 +862,15 @@ nsJARChannel::Open(nsIInputStream **stream) return NS_OK; } +NS_IMETHODIMP +nsJARChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + bool nsJARChannel::ShouldIntercept() { @@ -977,6 +987,20 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx) return ContinueAsyncOpen(); } +NS_IMETHODIMP +nsJARChannel::AsyncOpen2(nsIStreamListener *aListener) +{ + if (!mLoadInfo) { + MOZ_ASSERT(mLoadInfo, "can not enforce security without loadInfo"); + return NS_ERROR_UNEXPECTED; + } + // setting the flag on the loadInfo indicates that the underlying + // channel will be openend using AsyncOpen2() and hence performs + // the necessary security checks. + mLoadInfo->SetEnforceSecurity(true); + return AsyncOpen(aListener, nullptr); +} + nsresult nsJARChannel::ContinueAsyncOpen() { @@ -995,8 +1019,6 @@ nsJARChannel::ContinueAsyncOpen() // Not a local file... // kick off an async download of the base URI... nsCOMPtr downloader = new MemoryDownloader(this); - // Since we might not have a loadinfo on all channels yet - // we have to provide default arguments in case mLoadInfo is null; uint32_t loadFlags = mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS); rv = NS_NewChannelInternal(getter_AddRefs(channel), @@ -1011,7 +1033,12 @@ nsJARChannel::ContinueAsyncOpen() mListener = nullptr; return rv; } - rv = channel->AsyncOpen(downloader, nullptr); + if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) { + rv = channel->AsyncOpen2(downloader); + } + else { + rv = channel->AsyncOpen(downloader, nullptr); + } } else if (mOpeningRemote) { // nothing to do: already asked parent to open file. } else { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 0a0684ca92ea..0011dbe539ad 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -290,6 +290,7 @@ pref("media.decoder.heuristic.dormant.timeout", 60000); #ifdef MOZ_WMF pref("media.windows-media-foundation.enabled", true); +pref("media.wmf.decoder.thread-count", -1); #endif #ifdef MOZ_DIRECTSHOW pref("media.directshow.enabled", true); diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 11107b266d4c..c4465a07fd9d 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -7,6 +7,7 @@ #include "mozilla/LoadInfo.h" #include "mozilla/Assertions.h" +#include "mozilla/dom/ToJSValue.h" #include "nsFrameLoader.h" #include "nsIDocShell.h" #include "nsIDocument.h" @@ -36,6 +37,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(0) , mOuterWindowID(0) , mParentOuterWindowID(0) + , mEnforceSecurity(false) + , mInitialSecurityCheckDone(false) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -89,7 +92,10 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, bool aUpgradeInsecureRequests, uint64_t aInnerWindowID, uint64_t aOuterWindowID, - uint64_t aParentOuterWindowID) + uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, + nsTArray>& aRedirectChain) : mLoadingPrincipal(aLoadingPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal) , mSecurityFlags(aSecurityFlags) @@ -98,9 +104,13 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(aInnerWindowID) , mOuterWindowID(aOuterWindowID) , mParentOuterWindowID(aParentOuterWindowID) + , mEnforceSecurity(aEnforceSecurity) + , mInitialSecurityCheckDone(aInitialSecurityCheckDone) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); + + mRedirectChain.SwapElements(aRedirectChain); } LoadInfo::~LoadInfo() @@ -160,6 +170,26 @@ LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetSecurityMode(uint32_t *aFlags) +{ + *aFlags = (mSecurityFlags & + (nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL | + nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)); + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetRequireCorsWithCredentials(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetForceInheritPrincipal(bool* aInheritPrincipal) { @@ -175,6 +205,14 @@ LoadInfo::GetLoadingSandboxed(bool* aLoadingSandboxed) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetAboutBlankInherits(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_ABOUT_BLANK_INHERITS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetContentPolicyType(nsContentPolicyType* aResult) { @@ -230,4 +268,64 @@ LoadInfo::GetParentOuterWindowID(uint64_t* aResult) return NS_OK; } +NS_IMETHODIMP +LoadInfo::SetEnforceSecurity(bool aEnforceSecurity) +{ + // Indicates whether the channel was openend using AsyncOpen2. Once set + // to true, it must remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aEnforceSecurity, "aEnforceSecurity must be true"); + mEnforceSecurity = mEnforceSecurity || aEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetEnforceSecurity(bool* aResult) +{ + *aResult = mEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::SetInitialSecurityCheckDone(bool aInitialSecurityCheckDone) +{ + // Indicates whether the channel was ever evaluated by the + // ContentSecurityManager. Once set to true, this flag must + // remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aInitialSecurityCheckDone, "aInitialSecurityCheckDone must be true"); + mInitialSecurityCheckDone = mInitialSecurityCheckDone || aInitialSecurityCheckDone; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetInitialSecurityCheckDone(bool* aResult) +{ + *aResult = mInitialSecurityCheckDone; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::AppendRedirectedPrincipal(nsIPrincipal* aPrincipal) +{ + NS_ENSURE_ARG(aPrincipal); + mRedirectChain.AppendElement(aPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetRedirectChain(JSContext* aCx, JS::MutableHandle aChain) +{ + if (!ToJSValue(aCx, mRedirectChain, aChain)) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +const nsTArray>& +LoadInfo::RedirectChain() +{ + return mRedirectChain; +} + } // namespace mozilla diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 11540469a91a..23f096245f7e 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -12,6 +12,7 @@ #include "nsIPrincipal.h" #include "nsIWeakReferenceUtils.h" // for nsWeakPtr #include "nsIURI.h" +#include "nsTArray.h" class nsINode; @@ -54,6 +55,7 @@ private: // private constructor that is only allowed to be called from within // HttpChannelParent and FTPChannelParent declared as friends undeneath. // In e10s we can not serialize nsINode, hence we store the innerWindowID. + // Please note that aRedirectChain uses swapElements. LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags, @@ -61,7 +63,10 @@ private: bool aUpgradeInsecureRequests, uint64_t aInnerWindowID, uint64_t aOuterWindowID, - uint64_t aParentOuterWindowID); + uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, + nsTArray>& aRedirectChain); friend nsresult mozilla::ipc::LoadInfoArgsToLoadInfo( @@ -70,16 +75,19 @@ private: ~LoadInfo(); - nsCOMPtr mLoadingPrincipal; - nsCOMPtr mTriggeringPrincipal; - nsWeakPtr mLoadingContext; - nsSecurityFlags mSecurityFlags; - nsContentPolicyType mContentPolicyType; - nsCOMPtr mBaseURI; - bool mUpgradeInsecureRequests; - uint64_t mInnerWindowID; - uint64_t mOuterWindowID; - uint64_t mParentOuterWindowID; + nsCOMPtr mLoadingPrincipal; + nsCOMPtr mTriggeringPrincipal; + nsWeakPtr mLoadingContext; + nsSecurityFlags mSecurityFlags; + nsContentPolicyType mContentPolicyType; + nsCOMPtr mBaseURI; + bool mUpgradeInsecureRequests; + uint64_t mInnerWindowID; + uint64_t mOuterWindowID; + uint64_t mParentOuterWindowID; + bool mEnforceSecurity; + bool mInitialSecurityCheckDone; + nsTArray> mRedirectChain; }; } // namespace mozilla diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index 3c9f829728cb..fa452156888d 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -86,7 +86,6 @@ XPIDL_SOURCES += [ 'nsIProxyInfo.idl', 'nsIRandomGenerator.idl', 'nsIRedirectChannelRegistrar.idl', - 'nsIRedirectHistory.idl', 'nsIRedirectResultListener.idl', 'nsIRequest.idl', 'nsIRequestObserver.idl', diff --git a/netwerk/base/nsBaseChannel.cpp b/netwerk/base/nsBaseChannel.cpp index 3f8a49d9e23c..cde055f4be0b 100644 --- a/netwerk/base/nsBaseChannel.cpp +++ b/netwerk/base/nsBaseChannel.cpp @@ -5,10 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsBaseChannel.h" +#include "nsContentUtils.h" #include "nsURLHelper.h" #include "nsNetCID.h" #include "nsMimeTypes.h" #include "nsIContentSniffer.h" +#include "nsIScriptSecurityManager.h" #include "nsMimeTypes.h" #include "nsIHttpEventSink.h" #include "nsIHttpChannel.h" @@ -18,6 +20,7 @@ #include "nsAsyncRedirectVerifyHelper.h" #include "nsProxyRelease.h" #include "nsXULAppAPI.h" +#include "nsContentSecurityManager.h" static PLDHashOperator CopyProperties(const nsAString &key, nsIVariant *data, void *closure) @@ -151,9 +154,23 @@ nsBaseChannel::ContinueRedirect() // with the redirect. if (mOpenRedirectChannel) { - nsresult rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext); - if (NS_FAILED(rv)) - return rv; + nsresult rv = NS_OK; + if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) { + MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!"); + rv = mRedirectChannel->AsyncOpen2(mListener); + } + else { + rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext); + } + NS_ENSURE_SUCCESS(rv, rv); + // Append the initial uri of the channel to the redirectChain + // after the channel got openend successfully. + if (mLoadInfo) { + nsCOMPtr uriPrincipal; + nsIScriptSecurityManager *sm = nsContentUtils::GetSecurityManager(); + sm->GetChannelURIPrincipal(this, getter_AddRefs(uriPrincipal)); + mLoadInfo->AppendRedirectedPrincipal(uriPrincipal); + } } mRedirectChannel = nullptr; @@ -597,6 +614,15 @@ nsBaseChannel::Open(nsIInputStream **result) return rv; } +NS_IMETHODIMP +nsBaseChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + NS_IMETHODIMP nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { @@ -644,6 +670,15 @@ nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) return NS_OK; } +NS_IMETHODIMP +nsBaseChannel::AsyncOpen2(nsIStreamListener *aListener) +{ + nsCOMPtr listener = aListener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return AsyncOpen(listener, nullptr); +} + //----------------------------------------------------------------------------- // nsBaseChannel::nsITransportEventSink diff --git a/netwerk/base/nsIChannel.idl b/netwerk/base/nsIChannel.idl index 63b951df7ea0..cc9486f77764 100644 --- a/netwerk/base/nsIChannel.idl +++ b/netwerk/base/nsIChannel.idl @@ -29,7 +29,7 @@ interface nsIStreamListener; * * This interface must be used only from the XPCOM main thread. */ -[scriptable, uuid(1bc48693-c45d-45f4-8ab1-46e323037fe1)] +[scriptable, uuid(cc3bff29-324e-4704-9eeb-1b8a62c4a9dc)] interface nsIChannel : nsIRequest { /** @@ -146,6 +146,11 @@ interface nsIChannel : nsIRequest */ nsIInputStream open(); + /** + * Performs content security check and calls open() + */ + nsIInputStream open2(); + /** * Asynchronously open this channel. Data is fed to the specified stream * listener as it becomes available. The stream listener's methods are @@ -179,6 +184,11 @@ interface nsIChannel : nsIRequest */ void asyncOpen(in nsIStreamListener aListener, in nsISupports aContext); + /** + * Performs content security check and calls asyncOpen(). + */ + void asyncOpen2(in nsIStreamListener aListener); + /************************************************************************** * Channel specific load flags: * diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 9b9d5f98349d..66efc5a85b0b 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -12,12 +12,18 @@ interface nsINode; interface nsIPrincipal; interface nsIURI; +%{C++ +#include "nsTArray.h" +%} + +[ref] native const_nsIPrincipalArray(const nsTArray>); + typedef unsigned long nsSecurityFlags; /** * An nsILoadOwner represents per-load information about who started the load. */ -[scriptable, builtinclass, uuid(6b7f8798-3c28-44fc-8b1a-cd613eb826c5)] +[scriptable, builtinclass, uuid(cc51498e-f8f8-469d-85ba-6dcba17027e4)] interface nsILoadInfo : nsISupports { /** @@ -25,6 +31,64 @@ interface nsILoadInfo : nsISupports */ const unsigned long SEC_NORMAL = 0; + /** + * The following five flags determine the security mode and hence what kind of + * security checks should be performed throughout the lifetime of the channel. + * + * * SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS + * * SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED + * * SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS + * * SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL + * * SEC_REQUIRE_CORS_DATA_INHERITS + * + * Exactly one of these flags are required to be set in order to allow + * the channel to perform the correct security checks (SOP, CORS, ...) and + * return the correct result principal. If none or more than one of these + * flags are set AsyncOpen2 will fail. + */ + + /* + * Enforce the same origin policy where data: loads inherit + * the principal. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS = (1<<0); + + /* + * Enforce the same origin policy but data: loads are blocked. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED = (1<<1); + + /** + * Allow loads from other origins. Loads from data: will inherit + * the principal of the origin that triggered the load. + * Commonly used by plain ,