зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
43f915785d
|
@ -80,7 +80,31 @@ ShowError(DWORD aError = ::GetLastError())
|
|||
::LocalFree(rawMsgBuf);
|
||||
}
|
||||
|
||||
static wchar_t gAbsPath[MAX_PATH];
|
||||
static bool
|
||||
SetArgv0ToFullBinaryPath(wchar_t* aArgv[])
|
||||
{
|
||||
DWORD bufLen = MAX_PATH;
|
||||
mozilla::UniquePtr<wchar_t[]> buf;
|
||||
|
||||
while (true) {
|
||||
buf = mozilla::MakeUnique<wchar_t[]>(bufLen);
|
||||
DWORD retLen = ::GetModuleFileNameW(nullptr, buf.get(), bufLen);
|
||||
if (!retLen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retLen == bufLen && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
bufLen *= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// We intentionally leak buf into argv[0]
|
||||
aArgv[0] = buf.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -112,18 +136,11 @@ LauncherMain(int argc, wchar_t* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
// Convert argv[0] to an absolute path if necessary
|
||||
DWORD absPathLen = ::SearchPathW(nullptr, argv[0], L".exe",
|
||||
ArrayLength(gAbsPath), gAbsPath, nullptr);
|
||||
if (!absPathLen) {
|
||||
if (!SetArgv0ToFullBinaryPath(argv)) {
|
||||
ShowError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (absPathLen < ArrayLength(gAbsPath)) {
|
||||
argv[0] = gAbsPath;
|
||||
}
|
||||
|
||||
// If we're elevated, we should relaunch ourselves as a normal user
|
||||
Maybe<bool> isElevated = IsElevated();
|
||||
if (!isElevated) {
|
||||
|
|
|
@ -25,6 +25,7 @@ skip-if = !e10s # Pref and test only relevant for e10s.
|
|||
[browser_newwindow_tabstrip_overflow.js]
|
||||
[browser_opened_file_tab_navigated_to_web.js]
|
||||
[browser_new_tab_insert_position.js]
|
||||
skip-if = (debug && os == 'linux' && bits == 32) #Bug 1455882, disabled on Linux32 for almost permafailing
|
||||
support-files = file_new_tab_page.html
|
||||
[browser_overflowScroll.js]
|
||||
[browser_pinnedTabs.js]
|
||||
|
|
|
@ -283,5 +283,48 @@ DocumentOrShadowRoot::ElementsFromPointHelper(float aX, float aY,
|
|||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
DocumentOrShadowRoot::AddIDTargetObserver(nsAtom* aID,
|
||||
IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage)
|
||||
{
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aID);
|
||||
NS_ENSURE_TRUE(entry, nullptr);
|
||||
|
||||
entry->AddContentChangeCallback(aObserver, aData, aForImage);
|
||||
return aForImage ? entry->GetImageIdElement() : entry->GetIdElement();
|
||||
}
|
||||
|
||||
void
|
||||
DocumentOrShadowRoot::RemoveIDTargetObserver(nsAtom* aID,
|
||||
IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage)
|
||||
{
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aID);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
entry->RemoveContentChangeCallback(aObserver, aData, aForImage);
|
||||
}
|
||||
|
||||
void
|
||||
DocumentOrShadowRoot::ReportEmptyGetElementByIdArg()
|
||||
{
|
||||
nsContentUtils::ReportEmptyGetElementByIdArg(AsNode().OwnerDoc());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,54 @@ public:
|
|||
void ElementsFromPointHelper(float aX, float aY, uint32_t aFlags,
|
||||
nsTArray<RefPtr<mozilla::dom::Element>>& aElements);
|
||||
|
||||
/**
|
||||
* This gets fired when the element that an id refers to changes.
|
||||
* This fires at difficult times. It is generally not safe to do anything
|
||||
* which could modify the DOM in any way. Use
|
||||
* nsContentUtils::AddScriptRunner.
|
||||
* @return true to keep the callback in the callback set, false
|
||||
* to remove it.
|
||||
*/
|
||||
typedef bool (* IDTargetObserver)(Element* aOldElement,
|
||||
Element* aNewelement, void* aData);
|
||||
|
||||
/**
|
||||
* Add an IDTargetObserver for a specific ID. The IDTargetObserver
|
||||
* will be fired whenever the content associated with the ID changes
|
||||
* in the future. If aForImage is true, mozSetImageElement can override
|
||||
* what content is associated with the ID. In that case the IDTargetObserver
|
||||
* will be notified at those times when the result of LookupImageElement
|
||||
* changes.
|
||||
* At most one (aObserver, aData, aForImage) triple can be
|
||||
* registered for each ID.
|
||||
* @return the content currently associated with the ID.
|
||||
*/
|
||||
Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage);
|
||||
|
||||
/**
|
||||
* Remove the (aObserver, aData, aForImage) triple for a specific ID, if
|
||||
* registered.
|
||||
*/
|
||||
void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage);
|
||||
|
||||
/**
|
||||
* Check that aId is not empty and log a message to the console
|
||||
* service if it is.
|
||||
* @returns true if aId looks correct, false otherwise.
|
||||
*/
|
||||
inline bool CheckGetElementByIdArg(const nsAString& aId)
|
||||
{
|
||||
if (aId.IsEmpty()) {
|
||||
ReportEmptyGetElementByIdArg();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReportEmptyGetElementByIdArg();
|
||||
|
||||
protected:
|
||||
nsIContent* Retarget(nsIContent* aContent) const;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "AnimationCommon.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Attr.h"
|
||||
#include "mozilla/dom/Flex.h"
|
||||
|
@ -1247,6 +1248,10 @@ Element::AttachShadow(const ShadowRootInit& aInit, ErrorResult& aError)
|
|||
|
||||
shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
|
||||
|
||||
if (StaticPrefs::dom_webcomponents_shadowdom_report_usage()) {
|
||||
OwnerDoc()->ReportShadowDOMUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 5. Set context object’s shadow root to shadow.
|
||||
*/
|
||||
|
|
|
@ -1456,6 +1456,7 @@ nsIDocument::nsIDocument()
|
|||
mWidthStrEmpty(false),
|
||||
mParserAborted(false),
|
||||
mReportedUseCounters(false),
|
||||
mHasReportedShadowDOMUsage(false),
|
||||
#ifdef DEBUG
|
||||
mWillReparent(false),
|
||||
#endif
|
||||
|
@ -5091,45 +5092,6 @@ nsDocument::BeginLoad()
|
|||
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginLoad, (this));
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::ReportEmptyGetElementByIdArg()
|
||||
{
|
||||
nsContentUtils::ReportEmptyGetElementByIdArg(this);
|
||||
}
|
||||
|
||||
Element*
|
||||
nsIDocument::AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage)
|
||||
{
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id))
|
||||
return nullptr;
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aID);
|
||||
NS_ENSURE_TRUE(entry, nullptr);
|
||||
|
||||
entry->AddContentChangeCallback(aObserver, aData, aForImage);
|
||||
return aForImage ? entry->GetImageIdElement() : entry->GetIdElement();
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage)
|
||||
{
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id))
|
||||
return;
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aID);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
entry->RemoveContentChangeCallback(aObserver, aData, aForImage);
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::MozSetImageElement(const nsAString& aImageElementId,
|
||||
Element* aElement)
|
||||
|
@ -13259,3 +13221,27 @@ nsIDocument::ModuleScriptsEnabled()
|
|||
|
||||
return nsContentUtils::IsChromeDoc(this) || sEnabledForContent;
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::ReportShadowDOMUsage()
|
||||
{
|
||||
if (mHasReportedShadowDOMUsage) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* topLevel = GetTopLevelContentDocument();
|
||||
if (topLevel && !topLevel->mHasReportedShadowDOMUsage) {
|
||||
topLevel->mHasReportedShadowDOMUsage = true;
|
||||
nsString uri;
|
||||
Unused << topLevel->GetDocumentURI(uri);
|
||||
if (!uri.IsEmpty()) {
|
||||
nsAutoString msg = NS_LITERAL_STRING("Shadow DOM used in [") + uri +
|
||||
NS_LITERAL_STRING("] or in some of its subdocuments.");
|
||||
nsContentUtils::ReportToConsoleNonLocalized(msg, nsIScriptError::infoFlag,
|
||||
NS_LITERAL_CSTRING("DOM"),
|
||||
topLevel);
|
||||
}
|
||||
}
|
||||
|
||||
mHasReportedShadowDOMUsage = true;
|
||||
}
|
||||
|
|
|
@ -799,53 +799,6 @@ public:
|
|||
mCharacterSetSource = aCharsetSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets fired when the element that an id refers to changes.
|
||||
* This fires at difficult times. It is generally not safe to do anything
|
||||
* which could modify the DOM in any way. Use
|
||||
* nsContentUtils::AddScriptRunner.
|
||||
* @return true to keep the callback in the callback set, false
|
||||
* to remove it.
|
||||
*/
|
||||
typedef bool (* IDTargetObserver)(Element* aOldElement,
|
||||
Element* aNewelement, void* aData);
|
||||
|
||||
/**
|
||||
* Add an IDTargetObserver for a specific ID. The IDTargetObserver
|
||||
* will be fired whenever the content associated with the ID changes
|
||||
* in the future. If aForImage is true, mozSetImageElement can override
|
||||
* what content is associated with the ID. In that case the IDTargetObserver
|
||||
* will be notified at those times when the result of LookupImageElement
|
||||
* changes.
|
||||
* At most one (aObserver, aData, aForImage) triple can be
|
||||
* registered for each ID.
|
||||
* @return the content currently associated with the ID.
|
||||
*/
|
||||
Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage);
|
||||
/**
|
||||
* Remove the (aObserver, aData, aForImage) triple for a specific ID, if
|
||||
* registered.
|
||||
*/
|
||||
void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData, bool aForImage);
|
||||
|
||||
/**
|
||||
* Check that aId is not empty and log a message to the console
|
||||
* service if it is.
|
||||
* @returns true if aId looks correct, false otherwise.
|
||||
*/
|
||||
inline bool CheckGetElementByIdArg(const nsAString& aId)
|
||||
{
|
||||
if (aId.IsEmpty()) {
|
||||
ReportEmptyGetElementByIdArg();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReportEmptyGetElementByIdArg();
|
||||
|
||||
/**
|
||||
* Get the Content-Type of this document.
|
||||
*/
|
||||
|
@ -3583,6 +3536,8 @@ public:
|
|||
*/
|
||||
nsIContent* GetContentInThisDocument(nsIFrame* aFrame) const;
|
||||
|
||||
void ReportShadowDOMUsage();
|
||||
|
||||
protected:
|
||||
already_AddRefed<nsIPrincipal> MaybeDowngradePrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
|
@ -4099,6 +4054,8 @@ protected:
|
|||
// that we only report them once for the document.
|
||||
bool mReportedUseCounters: 1;
|
||||
|
||||
bool mHasReportedShadowDOMUsage: 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
public:
|
||||
bool mWillReparent: 1;
|
||||
|
|
|
@ -2268,10 +2268,9 @@ nsPluginHost::UpdatePluginBlocklistState(nsPluginTag* aPluginTag, bool aShouldSo
|
|||
return;
|
||||
}
|
||||
// Asynchronously get the blocklist state.
|
||||
nsCOMPtr<nsISupports> result;
|
||||
RefPtr<Promise> promise;
|
||||
blocklist->GetPluginBlocklistState(aPluginTag, EmptyString(),
|
||||
EmptyString(), getter_AddRefs(result));
|
||||
RefPtr<Promise> promise = do_QueryObject(result);
|
||||
EmptyString(), getter_AddRefs(promise));
|
||||
MOZ_ASSERT(promise, "Should always get a promise for plugin blocklist state.");
|
||||
if (promise) {
|
||||
promise->AppendNativeHandler(new mozilla::plugins::BlocklistPromiseHandler(aPluginTag, aShouldSoftblock));
|
||||
|
|
|
@ -541,14 +541,13 @@ PresentationService::HandleSessionRequest(nsIPresentationSessionRequest* aReques
|
|||
ctrlChannel->Disconnect(NS_ERROR_DOM_OPERATION_ERR);
|
||||
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
RefPtr<Promise> promise;
|
||||
rv = glue->SendRequest(url, sessionId, device, getter_AddRefs(promise));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
ctrlChannel->Disconnect(rv);
|
||||
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
nsCOMPtr<Promise> realPromise = do_QueryInterface(promise);
|
||||
static_cast<PresentationPresentingInfo*>(info.get())->SetPromise(realPromise);
|
||||
static_cast<PresentationPresentingInfo*>(info.get())->SetPromise(promise);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ interface nsIPresentationRequestUIGlue : nsISupports
|
|||
*
|
||||
* @return A promise that resolves to the opening frame.
|
||||
*/
|
||||
nsISupports sendRequest(in DOMString url,
|
||||
in DOMString sessionId,
|
||||
in nsIPresentationDevice device);
|
||||
Promise sendRequest(in DOMString url,
|
||||
in DOMString sessionId,
|
||||
in nsIPresentationDevice device);
|
||||
};
|
||||
|
|
|
@ -63,13 +63,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Promise)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPromiseObj);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Promise)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Promise)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(Promise)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Promise, AddRef);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Promise, Release);
|
||||
|
||||
Promise::Promise(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal)
|
||||
|
|
|
@ -32,21 +32,15 @@ class PromiseInit;
|
|||
class PromiseNativeHandler;
|
||||
class PromiseDebugging;
|
||||
|
||||
#define NS_PROMISE_IID \
|
||||
{ 0x1b8d6215, 0x3e67, 0x43ba, \
|
||||
{ 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
|
||||
|
||||
class Promise : public nsISupports,
|
||||
public SupportsWeakPtr<Promise>
|
||||
class Promise : public SupportsWeakPtr<Promise>
|
||||
{
|
||||
friend class PromiseTask;
|
||||
friend class PromiseWorkerProxy;
|
||||
friend class PromiseWorkerProxyRunnable;
|
||||
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Promise)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Promise)
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
|
||||
|
||||
// Promise creation tries to create a JS reflector for the Promise, so is
|
||||
|
@ -204,8 +198,6 @@ private:
|
|||
JS::Heap<JSObject*> mPromiseObj;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -1244,8 +1244,6 @@ var interfaceNamesInGlobalScope =
|
|||
{name: "XMLHttpRequestUpload", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XMLSerializer", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XMLStylesheetProcessingInstruction", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XPathEvaluator", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -4,12 +4,17 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/TR/2012/WD-dom-20120105/
|
||||
* https://dom.spec.whatwg.org/#interface-processinginstruction
|
||||
* https://drafts.csswg.org/cssom/#requirements-on-user-agents-implementing-the-xml-stylesheet-processing-instruction
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-processinginstruction
|
||||
interface ProcessingInstruction : CharacterData {
|
||||
readonly attribute DOMString target;
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/cssom/#requirements-on-user-agents-implementing-the-xml-stylesheet-processing-instruction
|
||||
ProcessingInstruction implements LinkStyle;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/* -*- Mode: IDL; 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/.
|
||||
*/
|
||||
|
||||
interface XMLStylesheetProcessingInstruction : ProcessingInstruction {
|
||||
readonly attribute StyleSheet? sheet;
|
||||
};
|
|
@ -941,7 +941,6 @@ WEBIDL_FILES = [
|
|||
'XMLHttpRequestEventTarget.webidl',
|
||||
'XMLHttpRequestUpload.webidl',
|
||||
'XMLSerializer.webidl',
|
||||
'XMLStylesheetProcessingInstruction.webidl',
|
||||
'XPathEvaluator.webidl',
|
||||
'XPathExpression.webidl',
|
||||
'XPathNSResolver.webidl',
|
||||
|
|
|
@ -62,6 +62,8 @@ ProcessingInstruction::~ProcessingInstruction()
|
|||
{
|
||||
}
|
||||
|
||||
// If you add nsIStyleSheetLinkingElement here, make sure we actually
|
||||
// implement the nsStyleLinkElement methods.
|
||||
NS_IMPL_ISUPPORTS_INHERITED(ProcessingInstruction, CharacterData, nsIDOMNode)
|
||||
|
||||
JSObject*
|
||||
|
@ -89,6 +91,16 @@ ProcessingInstruction::CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
|
|||
return do_AddRef(new ProcessingInstruction(ni.forget(), data));
|
||||
}
|
||||
|
||||
Maybe<nsStyleLinkElement::SheetInfo>
|
||||
ProcessingInstruction::GetStyleSheetInfo()
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("XMLStylesheetProcessingInstruction should override "
|
||||
"this and we don't try to do stylesheet stuff. In "
|
||||
"particular, we do not implement "
|
||||
"nsIStyleSheetLinkingElement");
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
ProcessingInstruction::List(FILE* out, int32_t aIndent) const
|
||||
|
|
|
@ -11,12 +11,17 @@
|
|||
#include "mozilla/dom/CharacterData.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsStyleLinkElement.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ProcessingInstruction : public CharacterData,
|
||||
public nsIDOMNode
|
||||
class ProcessingInstruction : public CharacterData
|
||||
, public nsStyleLinkElement
|
||||
, public nsIDOMNode
|
||||
{
|
||||
public:
|
||||
ProcessingInstruction(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
|
@ -60,6 +65,9 @@ protected:
|
|||
bool GetAttrValue(nsAtom *aName, nsAString& aValue);
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// nsStyleLinkElement overrides, because we can't leave them pure virtual.
|
||||
Maybe<SheetInfo> GetStyleSheetInfo() override;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "XMLStylesheetProcessingInstruction.h"
|
||||
#include "mozilla/dom/XMLStylesheetProcessingInstructionBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
|
@ -36,12 +35,6 @@ XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction()
|
|||
{
|
||||
}
|
||||
|
||||
JSObject*
|
||||
XMLStylesheetProcessingInstruction::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return XMLStylesheetProcessingInstructionBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
// nsIContent
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -17,8 +17,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class XMLStylesheetProcessingInstruction final
|
||||
: public ProcessingInstruction
|
||||
, public nsStyleLinkElement
|
||||
: public ProcessingInstruction
|
||||
{
|
||||
public:
|
||||
XMLStylesheetProcessingInstruction(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
|
@ -37,8 +36,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "CrashReporterHost.h"
|
||||
#include "CrashReporterMetadataShmem.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
|
@ -275,7 +276,7 @@ CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
RefPtr<Promise> promise;
|
||||
crashService->AddCrash(processType, crashType, aChildDumpID, getter_AddRefs(promise));
|
||||
Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, telemetryKey, 1);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "js/TraceKind.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
struct JSStringFinalizer;
|
||||
|
||||
/* These values are private to the JS engine. */
|
||||
namespace js {
|
||||
|
||||
|
@ -201,6 +203,47 @@ struct Zone
|
|||
}
|
||||
};
|
||||
|
||||
struct String
|
||||
{
|
||||
static const uint32_t NON_ATOM_BIT = JS_BIT(0);
|
||||
static const uint32_t LINEAR_BIT = JS_BIT(1);
|
||||
static const uint32_t INLINE_CHARS_BIT = JS_BIT(3);
|
||||
static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
|
||||
static const uint32_t EXTERNAL_FLAGS = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5);
|
||||
static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1;
|
||||
static const uint32_t PERMANENT_ATOM_MASK = NON_ATOM_BIT | JS_BIT(5);
|
||||
static const uint32_t PERMANENT_ATOM_FLAGS = JS_BIT(5);
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t length;
|
||||
union {
|
||||
const JS::Latin1Char* nonInlineCharsLatin1;
|
||||
const char16_t* nonInlineCharsTwoByte;
|
||||
JS::Latin1Char inlineStorageLatin1[1];
|
||||
char16_t inlineStorageTwoByte[1];
|
||||
};
|
||||
const JSStringFinalizer* externalFinalizer;
|
||||
|
||||
static bool nurseryCellIsString(const js::gc::Cell* cell) {
|
||||
MOZ_ASSERT(IsInsideNursery(cell));
|
||||
return reinterpret_cast<const String*>(cell)->flags & NON_ATOM_BIT;
|
||||
}
|
||||
|
||||
static bool isPermanentAtom(const js::gc::Cell* cell) {
|
||||
uint32_t flags = reinterpret_cast<const String*>(cell)->flags;
|
||||
return (flags & PERMANENT_ATOM_MASK) == PERMANENT_ATOM_FLAGS;
|
||||
}
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
uint32_t code_;
|
||||
static const uint32_t WellKnownAPILimit = 0x80000000;
|
||||
|
||||
static bool isWellKnownSymbol(const js::gc::Cell* cell) {
|
||||
return reinterpret_cast<const Symbol*>(cell)->code_ < WellKnownAPILimit;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace shadow */
|
||||
|
||||
/**
|
||||
|
@ -272,9 +315,12 @@ class JS_FRIEND_API(GCCellPtr)
|
|||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool mayBeOwnedByOtherRuntime() const {
|
||||
if (is<JSString>() || is<JS::Symbol>())
|
||||
return mayBeOwnedByOtherRuntimeSlow();
|
||||
return false;
|
||||
if (!is<JSString>() && !is<JS::Symbol>())
|
||||
return false;
|
||||
if (is<JSString>())
|
||||
return JS::shadow::String::isPermanentAtom(asCell());
|
||||
MOZ_ASSERT(is<JS::Symbol>());
|
||||
return JS::shadow::Symbol::isWellKnownSymbol(asCell());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -42,7 +42,7 @@ install:: $(LIBRARY_NAME).pc
|
|||
$(SYSINSTALL) $(JS_LIBRARY_NAME).pc $(DESTDIR)$(libdir)/pkgconfig
|
||||
|
||||
install:: ../js-config.h
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(includedir)
|
||||
$(SYSINSTALL) $^ $(DESTDIR)$(includedir)/$(JS_LIBRARY_NAME)
|
||||
|
||||
######################################################
|
||||
# BEGIN SpiderMonkey header installation
|
||||
|
@ -56,7 +56,7 @@ install:: ../js-config.h
|
|||
# The overall directory structure of the installed headers looks like so:
|
||||
#
|
||||
# $(includedir)/
|
||||
# $(LIBRARY_NAME)/
|
||||
# $(JS_LIBRARY_NAME)/
|
||||
# jsapi.h, jspubtd.h, etc. (all of EXPORTS)
|
||||
# js/
|
||||
# js/public/* headers (all are public)
|
||||
|
@ -69,7 +69,7 @@ install:: ../js-config.h
|
|||
#
|
||||
|
||||
install::
|
||||
$(call py_action,process_install_manifest,--track install_dist_include.track --no-symlinks $(DESTDIR)$(includedir) $(DEPTH)/_build_manifests/install/dist_include)
|
||||
$(call py_action,process_install_manifest,--track install_dist_include.track --no-symlinks $(DESTDIR)$(includedir)/$(JS_LIBRARY_NAME) $(DEPTH)/_build_manifests/install/dist_include)
|
||||
|
||||
#
|
||||
# END SpiderMonkey header installation
|
||||
|
|
|
@ -255,7 +255,7 @@ Cell::getTraceKind() const
|
|||
{
|
||||
if (isTenured())
|
||||
return asTenured().getTraceKind();
|
||||
if (js::shadow::String::nurseryCellIsString(this))
|
||||
if (JS::shadow::String::nurseryCellIsString(this))
|
||||
return JS::TraceKind::String;
|
||||
return JS::TraceKind::Object;
|
||||
}
|
||||
|
|
|
@ -8448,14 +8448,6 @@ JS::GCCellPtr::outOfLineKind() const
|
|||
return MapAllocToTraceKind(asCell()->asTenured().getAllocKind());
|
||||
}
|
||||
|
||||
bool
|
||||
JS::GCCellPtr::mayBeOwnedByOtherRuntimeSlow() const
|
||||
{
|
||||
if (is<JSString>())
|
||||
return as<JSString>().isPermanentAtom();
|
||||
return as<Symbol>().isWellKnownSymbol();
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void
|
||||
js::gc::CheckHashTablesAfterMovingGC(JSRuntime* rt)
|
||||
|
|
|
@ -111,7 +111,8 @@ IterateHeapUnbarrieredForZone(JSContext* cx, JS::Zone* zone, void* data,
|
|||
extern void
|
||||
IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback);
|
||||
|
||||
typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* script);
|
||||
typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* script,
|
||||
const JS::AutoRequireNoGC& nogc);
|
||||
|
||||
/*
|
||||
* Invoke scriptCallback on every in-use script for
|
||||
|
|
|
@ -86,17 +86,18 @@ js::IterateScripts(JSContext* cx, JSCompartment* compartment,
|
|||
MOZ_ASSERT(!cx->suppressGC);
|
||||
AutoEmptyNursery empty(cx);
|
||||
AutoPrepareForTracing prep(cx);
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
|
||||
if (compartment) {
|
||||
Zone* zone = compartment->zone();
|
||||
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next()) {
|
||||
if (script->compartment() == compartment)
|
||||
scriptCallback(cx->runtime(), data, script);
|
||||
scriptCallback(cx->runtime(), data, script, nogc);
|
||||
}
|
||||
} else {
|
||||
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next())
|
||||
scriptCallback(cx->runtime(), data, script);
|
||||
scriptCallback(cx->runtime(), data, script, nogc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,121 @@
|
|||
if (!wasmBulkMemSupported())
|
||||
quit(0);
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
//---------------------------------------------------------------------//
|
||||
// Validation tests
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Test helpers. Copied and simplified from binary.js.
|
||||
|
||||
load(libdir + "wasm-binary.js");
|
||||
|
||||
function toU8(array) {
|
||||
for (let b of array)
|
||||
assertEq(b < 256, true);
|
||||
return Uint8Array.from(array);
|
||||
}
|
||||
|
||||
function varU32(u32) {
|
||||
assertEq(u32 >= 0, true);
|
||||
assertEq(u32 < Math.pow(2,32), true);
|
||||
var bytes = [];
|
||||
do {
|
||||
var byte = u32 & 0x7f;
|
||||
u32 >>>= 7;
|
||||
if (u32 != 0)
|
||||
byte |= 0x80;
|
||||
bytes.push(byte);
|
||||
} while (u32 != 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function moduleHeaderThen(...rest) {
|
||||
return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest];
|
||||
}
|
||||
|
||||
function moduleWithSections(sectionArray) {
|
||||
var bytes = moduleHeaderThen();
|
||||
for (let section of sectionArray) {
|
||||
bytes.push(section.name);
|
||||
bytes.push(...varU32(section.body.length));
|
||||
bytes.push(...section.body);
|
||||
}
|
||||
return toU8(bytes);
|
||||
}
|
||||
|
||||
function sigSection(sigs) {
|
||||
var body = [];
|
||||
body.push(...varU32(sigs.length));
|
||||
for (let sig of sigs) {
|
||||
body.push(...varU32(FuncCode));
|
||||
body.push(...varU32(sig.args.length));
|
||||
for (let arg of sig.args)
|
||||
body.push(...varU32(arg));
|
||||
body.push(...varU32(sig.ret == VoidCode ? 0 : 1));
|
||||
if (sig.ret != VoidCode)
|
||||
body.push(...varU32(sig.ret));
|
||||
}
|
||||
return { name: typeId, body };
|
||||
}
|
||||
|
||||
function declSection(decls) {
|
||||
var body = [];
|
||||
body.push(...varU32(decls.length));
|
||||
for (let decl of decls)
|
||||
body.push(...varU32(decl));
|
||||
return { name: functionId, body };
|
||||
}
|
||||
|
||||
function funcBody(func) {
|
||||
var body = varU32(func.locals.length);
|
||||
for (let local of func.locals)
|
||||
body.push(...varU32(local));
|
||||
body = body.concat(...func.body);
|
||||
body.push(EndCode);
|
||||
body.splice(0, 0, ...varU32(body.length));
|
||||
return body;
|
||||
}
|
||||
|
||||
function bodySection(bodies) {
|
||||
var body = varU32(bodies.length).concat(...bodies);
|
||||
return { name: codeId, body };
|
||||
}
|
||||
|
||||
const v2vSig = {args:[], ret:VoidCode};
|
||||
const v2vSigSection = sigSection([v2vSig]);
|
||||
|
||||
// Prefixed opcodes
|
||||
|
||||
function checkMiscPrefixed(opcode, expect_failure) {
|
||||
let binary = moduleWithSections(
|
||||
[v2vSigSection, declSection([0]),
|
||||
bodySection(
|
||||
[funcBody(
|
||||
{locals:[],
|
||||
body:[0x41, 0x0, 0x41, 0x0, 0x41, 0x0, // 3 x const.i32 0
|
||||
MiscPrefix, opcode]})])]);
|
||||
if (expect_failure) {
|
||||
assertErrorMessage(() => new WebAssembly.Module(binary),
|
||||
WebAssembly.CompileError, /unrecognized opcode/);
|
||||
} else {
|
||||
assertEq(true, WebAssembly.validate(binary));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Verification cases for memory.copy/fill
|
||||
|
||||
checkMiscPrefixed(0x3f, true); // unassigned
|
||||
checkMiscPrefixed(0x40, false); // memory.copy
|
||||
checkMiscPrefixed(0x41, false); // memory.fill
|
||||
checkMiscPrefixed(0x42, true); // unassigned
|
||||
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
//---------------------------------------------------------------------//
|
||||
// Run tests
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Test helpers
|
||||
function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
using namespace JS;
|
||||
|
||||
static void
|
||||
ScriptCallback(JSRuntime* rt, void* data, JSScript* script)
|
||||
ScriptCallback(JSRuntime* rt, void* data, JSScript* script, const JS::AutoRequireNoGC& nogc)
|
||||
{
|
||||
unsigned& count = *static_cast<unsigned*>(data);
|
||||
if (script->hasIonScript())
|
||||
|
|
|
@ -5043,6 +5043,7 @@ enum class SymbolCode : uint32_t {
|
|||
JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM) // SymbolCode::iterator, etc.
|
||||
#undef JS_DEFINE_SYMBOL_ENUM
|
||||
Limit,
|
||||
WellKnownAPILimit = 0x80000000, // matches JS::shadow::Symbol::WellKnownAPILimit for inline use
|
||||
InSymbolRegistry = 0xfffffffe, // created by Symbol.for() or JS::GetSymbolFor()
|
||||
UniqueSymbol = 0xffffffff // created by Symbol() or JS::NewSymbol()
|
||||
};
|
||||
|
|
|
@ -624,30 +624,6 @@ struct Function {
|
|||
void* _1;
|
||||
};
|
||||
|
||||
struct String
|
||||
{
|
||||
static const uint32_t NON_ATOM_BIT = JS_BIT(0);
|
||||
static const uint32_t LINEAR_BIT = JS_BIT(1);
|
||||
static const uint32_t INLINE_CHARS_BIT = JS_BIT(3);
|
||||
static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
|
||||
static const uint32_t EXTERNAL_FLAGS = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5);
|
||||
static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1;
|
||||
uint32_t flags;
|
||||
uint32_t length;
|
||||
union {
|
||||
const JS::Latin1Char* nonInlineCharsLatin1;
|
||||
const char16_t* nonInlineCharsTwoByte;
|
||||
JS::Latin1Char inlineStorageLatin1[1];
|
||||
char16_t inlineStorageTwoByte[1];
|
||||
};
|
||||
const JSStringFinalizer* externalFinalizer;
|
||||
|
||||
static bool nurseryCellIsString(const js::gc::Cell* cell) {
|
||||
MOZ_ASSERT(IsInsideNursery(cell));
|
||||
return reinterpret_cast<const String*>(cell)->flags & NON_ATOM_BIT;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace shadow */
|
||||
|
||||
// This is equal to |&JSObject::class_|. Use it in places where you don't want
|
||||
|
@ -806,7 +782,7 @@ GetObjectSlot(JSObject* obj, size_t slot)
|
|||
MOZ_ALWAYS_INLINE size_t
|
||||
GetAtomLength(JSAtom* atom)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(atom)->length;
|
||||
return reinterpret_cast<JS::shadow::String*>(atom)->length;
|
||||
}
|
||||
|
||||
static const uint32_t MaxStringLength = (1 << 28) - 1;
|
||||
|
@ -814,37 +790,37 @@ static const uint32_t MaxStringLength = (1 << 28) - 1;
|
|||
MOZ_ALWAYS_INLINE size_t
|
||||
GetStringLength(JSString* s)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(s)->length;
|
||||
return reinterpret_cast<JS::shadow::String*>(s)->length;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
GetFlatStringLength(JSFlatString* s)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(s)->length;
|
||||
return reinterpret_cast<JS::shadow::String*>(s)->length;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
GetLinearStringLength(JSLinearString* s)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(s)->length;
|
||||
return reinterpret_cast<JS::shadow::String*>(s)->length;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
LinearStringHasLatin1Chars(JSLinearString* s)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(s)->flags & shadow::String::LATIN1_CHARS_BIT;
|
||||
return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
AtomHasLatin1Chars(JSAtom* atom)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(atom)->flags & shadow::String::LATIN1_CHARS_BIT;
|
||||
return reinterpret_cast<JS::shadow::String*>(atom)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
StringHasLatin1Chars(JSString* s)
|
||||
{
|
||||
return reinterpret_cast<shadow::String*>(s)->flags & shadow::String::LATIN1_CHARS_BIT;
|
||||
return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE const JS::Latin1Char*
|
||||
|
@ -852,7 +828,7 @@ GetLatin1LinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* line
|
|||
{
|
||||
MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
|
||||
|
||||
using shadow::String;
|
||||
using JS::shadow::String;
|
||||
String* s = reinterpret_cast<String*>(linear);
|
||||
if (s->flags & String::INLINE_CHARS_BIT)
|
||||
return s->inlineStorageLatin1;
|
||||
|
@ -864,7 +840,7 @@ GetTwoByteLinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* lin
|
|||
{
|
||||
MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
|
||||
|
||||
using shadow::String;
|
||||
using JS::shadow::String;
|
||||
String* s = reinterpret_cast<String*>(linear);
|
||||
if (s->flags & String::INLINE_CHARS_BIT)
|
||||
return s->inlineStorageTwoByte;
|
||||
|
@ -904,7 +880,7 @@ GetTwoByteAtomChars(const JS::AutoRequireNoGC& nogc, JSAtom* atom)
|
|||
MOZ_ALWAYS_INLINE bool
|
||||
IsExternalString(JSString* str, const JSStringFinalizer** fin, const char16_t** chars)
|
||||
{
|
||||
using shadow::String;
|
||||
using JS::shadow::String;
|
||||
String* s = reinterpret_cast<String*>(str);
|
||||
|
||||
if ((s->flags & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS)
|
||||
|
@ -922,7 +898,7 @@ StringToLinearStringSlow(JSContext* cx, JSString* str);
|
|||
MOZ_ALWAYS_INLINE JSLinearString*
|
||||
StringToLinearString(JSContext* cx, JSString* str)
|
||||
{
|
||||
using shadow::String;
|
||||
using JS::shadow::String;
|
||||
String* s = reinterpret_cast<String*>(str);
|
||||
if (MOZ_UNLIKELY(!(s->flags & String::LINEAR_BIT)))
|
||||
return StringToLinearStringSlow(cx, str);
|
||||
|
|
|
@ -4589,9 +4589,10 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
|
|||
return true;
|
||||
}
|
||||
|
||||
static void considerScript(JSRuntime* rt, void* data, JSScript* script) {
|
||||
static void considerScript(JSRuntime* rt, void* data, JSScript* script,
|
||||
const JS::AutoRequireNoGC& nogc) {
|
||||
ScriptQuery* self = static_cast<ScriptQuery*>(data);
|
||||
self->consider(script);
|
||||
self->consider(script, nogc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4599,7 +4600,7 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
|
|||
* |innermostForCompartment|, as appropriate. Set |oom| if an out of memory
|
||||
* condition occurred.
|
||||
*/
|
||||
void consider(JSScript* script) {
|
||||
void consider(JSScript* script, const JS::AutoRequireNoGC& nogc) {
|
||||
// We check for presence of script->code() because it is possible that
|
||||
// the script was created and thus exposed to GC, but *not* fully
|
||||
// initialized from fullyInit{FromEmitter,Trivial} due to errors.
|
||||
|
|
|
@ -316,7 +316,7 @@ class JSString : public js::gc::Cell
|
|||
"Inline char16_t chars must fit in a JSString");
|
||||
|
||||
/* Ensure js::shadow::String has the same layout. */
|
||||
using js::shadow::String;
|
||||
using JS::shadow::String;
|
||||
static_assert(offsetof(JSString, d.u1.length) == offsetof(String, length),
|
||||
"shadow::String length offset must match JSString");
|
||||
static_assert(offsetof(JSString, d.u1.flags) == offsetof(String, flags),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "gc/Tracer.h"
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h"
|
||||
|
@ -50,6 +51,8 @@ class Symbol : public js::gc::TenuredCell
|
|||
{
|
||||
// Silence warnings about unused_ being... unused.
|
||||
(void)unused_;
|
||||
static_assert(uint32_t(SymbolCode::WellKnownAPILimit) == JS::shadow::Symbol::WellKnownAPILimit,
|
||||
"JS::shadow::Symbol::WellKnownAPILimit must match SymbolCode::WellKnownAPILimit");
|
||||
}
|
||||
|
||||
Symbol(const Symbol&) = delete;
|
||||
|
|
|
@ -9200,7 +9200,7 @@ BaseCompiler::emitMemCopy()
|
|||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
|
||||
Nothing nothing;
|
||||
if (!iter_.readMemCopy(ValType::I32, ¬hing, ¬hing, ¬hing))
|
||||
if (!iter_.readMemCopy(¬hing, ¬hing, ¬hing))
|
||||
return false;
|
||||
|
||||
if (deadCode_)
|
||||
|
@ -9222,7 +9222,7 @@ BaseCompiler::emitMemFill()
|
|||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
|
||||
Nothing nothing;
|
||||
if (!iter_.readMemFill(ValType::I32, ¬hing, ¬hing, ¬hing))
|
||||
if (!iter_.readMemFill(¬hing, ¬hing, ¬hing))
|
||||
return false;
|
||||
|
||||
if (deadCode_)
|
||||
|
|
|
@ -1253,7 +1253,7 @@ AstDecodeWake(AstDecodeContext& c)
|
|||
static bool
|
||||
AstDecodeMemCopy(AstDecodeContext& c)
|
||||
{
|
||||
if (!c.iter().readMemCopy(ValType::I32, nullptr, nullptr, nullptr))
|
||||
if (!c.iter().readMemCopy(nullptr, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
AstDecodeStackItem dest = c.popCopy();
|
||||
|
@ -1274,7 +1274,7 @@ AstDecodeMemCopy(AstDecodeContext& c)
|
|||
static bool
|
||||
AstDecodeMemFill(AstDecodeContext& c)
|
||||
{
|
||||
if (!c.iter().readMemFill(ValType::I32, nullptr, nullptr, nullptr))
|
||||
if (!c.iter().readMemFill(nullptr, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
AstDecodeStackItem len = c.popCopy();
|
||||
|
|
|
@ -3603,7 +3603,7 @@ static bool
|
|||
EmitMemCopy(FunctionCompiler& f)
|
||||
{
|
||||
MDefinition *dest, *src, *len;
|
||||
if (!f.iter().readMemCopy(ValType::I32, &dest, &src, &len))
|
||||
if (!f.iter().readMemCopy(&dest, &src, &len))
|
||||
return false;
|
||||
|
||||
if (f.inDeadCode())
|
||||
|
@ -3642,7 +3642,7 @@ static bool
|
|||
EmitMemFill(FunctionCompiler& f)
|
||||
{
|
||||
MDefinition *start, *val, *len;
|
||||
if (!f.iter().readMemFill(ValType::I32, &start, &val, &len))
|
||||
if (!f.iter().readMemFill(&start, &val, &len))
|
||||
return false;
|
||||
|
||||
if (f.inDeadCode())
|
||||
|
|
|
@ -658,8 +658,8 @@ class MOZ_STACK_CLASS OpIter : private Policy
|
|||
Value* condition);
|
||||
MOZ_MUST_USE bool readSimdCtor(ValType elementType, uint32_t numElements, ValType simdType,
|
||||
ValueVector* argValues);
|
||||
MOZ_MUST_USE bool readMemCopy(ValType argType, Value* dest, Value* src, Value* len);
|
||||
MOZ_MUST_USE bool readMemFill(ValType argType, Value* start, Value* val, Value* len);
|
||||
MOZ_MUST_USE bool readMemCopy(Value* dest, Value* src, Value* len);
|
||||
MOZ_MUST_USE bool readMemFill(Value* start, Value* val, Value* len);
|
||||
|
||||
// At a location where readOp is allowed, peek at the next opcode
|
||||
// without consuming it or updating any internal state.
|
||||
|
@ -2239,18 +2239,17 @@ OpIter<Policy>::readSimdCtor(ValType elementType, uint32_t numElements, ValType
|
|||
|
||||
template <typename Policy>
|
||||
inline bool
|
||||
OpIter<Policy>::readMemCopy(ValType argType,
|
||||
Value* dest, Value* src, Value* len)
|
||||
OpIter<Policy>::readMemCopy(Value* dest, Value* src, Value* len)
|
||||
{
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::MemCopy);
|
||||
|
||||
if (!popWithType(argType, len))
|
||||
if (!popWithType(ValType::I32, len))
|
||||
return false;
|
||||
|
||||
if (!popWithType(argType, src))
|
||||
if (!popWithType(ValType::I32, src))
|
||||
return false;
|
||||
|
||||
if (!popWithType(argType, dest))
|
||||
if (!popWithType(ValType::I32, dest))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -2258,18 +2257,17 @@ OpIter<Policy>::readMemCopy(ValType argType,
|
|||
|
||||
template <typename Policy>
|
||||
inline bool
|
||||
OpIter<Policy>::readMemFill(ValType argType,
|
||||
Value* start, Value* val, Value* len)
|
||||
OpIter<Policy>::readMemFill(Value* start, Value* val, Value* len)
|
||||
{
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::MemFill);
|
||||
|
||||
if (!popWithType(argType, len))
|
||||
if (!popWithType(ValType::I32, len))
|
||||
return false;
|
||||
|
||||
if (!popWithType(argType, val))
|
||||
if (!popWithType(ValType::I32, val))
|
||||
return false;
|
||||
|
||||
if (!popWithType(argType, start))
|
||||
if (!popWithType(ValType::I32, start))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -816,6 +816,12 @@ DecodeFunctionBodyExprs(const ModuleEnvironment& env, const Sig& sig, const ValT
|
|||
case uint16_t(MiscOp::I64TruncSSatF64):
|
||||
case uint16_t(MiscOp::I64TruncUSatF64):
|
||||
CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing));
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case uint16_t(MiscOp::MemCopy):
|
||||
CHECK(iter.readMemCopy(¬hing, ¬hing, ¬hing));
|
||||
case uint16_t(MiscOp::MemFill):
|
||||
CHECK(iter.readMemFill(¬hing, ¬hing, ¬hing));
|
||||
#endif
|
||||
default:
|
||||
return iter.unrecognizedOpcode(&op);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -522,4 +522,20 @@ void ThrowBadResult(nsresult result, XPCCallContext& ccx)
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
inline void
|
||||
xpc::CleanupValue(const nsXPTType& aType,
|
||||
void* aValue,
|
||||
uint32_t aArrayLen)
|
||||
{
|
||||
// Check if we can do a cheap early return, and only perform the inner call
|
||||
// if we can't. We never have to clean up null pointer types or arithmetic
|
||||
// types.
|
||||
if (aType.IsArithmetic() || (aType.HasPointerRepr() && !*(void**)aValue)) {
|
||||
return;
|
||||
}
|
||||
xpc::InnerCleanupValue(aType, aValue, aArrayLen);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#endif /* xpcinlines_h___ */
|
||||
|
|
|
@ -218,28 +218,28 @@ XPCArrayHomogenizer::GetTypeForArray(JSContext* cx, HandleObject array,
|
|||
|
||||
switch (state) {
|
||||
case tInt :
|
||||
*resultType = TD_INT32;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::INT32);
|
||||
break;
|
||||
case tDbl :
|
||||
*resultType = TD_DOUBLE;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::DOUBLE);
|
||||
break;
|
||||
case tBool:
|
||||
*resultType = TD_BOOL;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::BOOL);
|
||||
break;
|
||||
case tStr :
|
||||
*resultType = TD_PWSTRING;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::PWSTRING);
|
||||
break;
|
||||
case tID :
|
||||
*resultType = TD_PNSIID;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::PNSIID);
|
||||
break;
|
||||
case tISup:
|
||||
*resultType = TD_INTERFACE_IS_TYPE;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::INTERFACE_IS_TYPE);
|
||||
*resultID = NS_GET_IID(nsISupports);
|
||||
break;
|
||||
case tNull:
|
||||
// FALL THROUGH
|
||||
case tVar :
|
||||
*resultType = TD_INTERFACE_IS_TYPE;
|
||||
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::INTERFACE_IS_TYPE);
|
||||
*resultID = NS_GET_IID(nsIVariant);
|
||||
break;
|
||||
case tArr :
|
||||
|
@ -339,15 +339,16 @@ bool XPCVariant::InitializeData(JSContext* cx)
|
|||
if (!XPCArrayHomogenizer::GetTypeForArray(cx, jsobj, len, &type, &id))
|
||||
return false;
|
||||
|
||||
if (!XPCConvert::JSArray2Native(&mData.u.array.mArrayValue,
|
||||
val, len, type, &id, nullptr))
|
||||
if (!XPCConvert::JSData2Native(&mData.u.array.mArrayValue,
|
||||
val, type, &id, len, nullptr))
|
||||
return false;
|
||||
|
||||
const nsXPTType& elty = type.ArrayElementType();
|
||||
mData.mType = nsIDataType::VTYPE_ARRAY;
|
||||
if (type.IsInterfacePointer())
|
||||
if (elty.IsInterfacePointer())
|
||||
mData.u.array.mArrayInterfaceID = id;
|
||||
mData.u.array.mArrayCount = len;
|
||||
mData.u.array.mArrayType = type.TagPart();
|
||||
mData.u.array.mArrayType = elty.Tag();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -453,56 +454,49 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
char c;
|
||||
if (NS_FAILED(variant->GetAsChar(&c)))
|
||||
return false;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&c, { TD_CHAR }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&c, { TD_CHAR }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_WCHAR:
|
||||
{
|
||||
char16_t wc;
|
||||
if (NS_FAILED(variant->GetAsWChar(&wc)))
|
||||
return false;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&wc, { TD_WCHAR }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&wc, { TD_WCHAR }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_ID:
|
||||
{
|
||||
if (NS_FAILED(variant->GetAsID(&iid)))
|
||||
return false;
|
||||
nsID* v = &iid;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, { TD_PNSIID }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, { TD_PNSIID }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_ASTRING:
|
||||
{
|
||||
nsAutoString astring;
|
||||
if (NS_FAILED(variant->GetAsAString(astring)))
|
||||
return false;
|
||||
nsAutoString* v = &astring;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, { TD_ASTRING }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, &astring, { TD_ASTRING }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_DOMSTRING:
|
||||
{
|
||||
nsAutoString astring;
|
||||
if (NS_FAILED(variant->GetAsAString(astring)))
|
||||
return false;
|
||||
nsAutoString* v = &astring;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
|
||||
{ TD_DOMSTRING }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, &astring, { TD_DOMSTRING }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_CSTRING:
|
||||
{
|
||||
nsAutoCString cString;
|
||||
if (NS_FAILED(variant->GetAsACString(cString)))
|
||||
return false;
|
||||
nsAutoCString* v = &cString;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
|
||||
{ TD_CSTRING }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, &cString, { TD_CSTRING }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_UTF8STRING:
|
||||
{
|
||||
nsUTF8String utf8String;
|
||||
if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
|
||||
return false;
|
||||
nsUTF8String* v = &utf8String;
|
||||
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
|
||||
{ TD_UTF8STRING }, &iid, pErr);
|
||||
return XPCConvert::NativeData2JS(pJSVal, &utf8String, { TD_UTF8STRING }, &iid, 0, pErr);
|
||||
}
|
||||
case nsIDataType::VTYPE_CHAR_STR:
|
||||
{
|
||||
|
@ -510,7 +504,7 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
if (NS_FAILED(variant->GetAsString(&pc)))
|
||||
return false;
|
||||
bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pc,
|
||||
{ TD_PSTRING }, &iid, pErr);
|
||||
{ TD_PSTRING }, &iid, 0, pErr);
|
||||
free(pc);
|
||||
return success;
|
||||
}
|
||||
|
@ -520,8 +514,9 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
uint32_t size;
|
||||
if (NS_FAILED(variant->GetAsStringWithSize(&size, &pc)))
|
||||
return false;
|
||||
bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pc,
|
||||
{ TD_PSTRING_SIZE_IS }, size, pErr);
|
||||
bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pc,
|
||||
{ TD_PSTRING_SIZE_IS },
|
||||
&iid, size, pErr);
|
||||
free(pc);
|
||||
return success;
|
||||
}
|
||||
|
@ -531,7 +526,7 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
if (NS_FAILED(variant->GetAsWString(&pwc)))
|
||||
return false;
|
||||
bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pwc,
|
||||
{ TD_PSTRING }, &iid, pErr);
|
||||
{ TD_PSTRING }, &iid, 0, pErr);
|
||||
free(pwc);
|
||||
return success;
|
||||
}
|
||||
|
@ -541,8 +536,9 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
uint32_t size;
|
||||
if (NS_FAILED(variant->GetAsWStringWithSize(&size, &pwc)))
|
||||
return false;
|
||||
bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pwc,
|
||||
{ TD_PWSTRING_SIZE_IS }, size, pErr);
|
||||
bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pwc,
|
||||
{ TD_PWSTRING_SIZE_IS },
|
||||
&iid, size, pErr);
|
||||
free(pwc);
|
||||
return success;
|
||||
}
|
||||
|
@ -558,7 +554,8 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
free((char*)piid);
|
||||
|
||||
bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pi,
|
||||
{ TD_INTERFACE_IS_TYPE }, &iid, pErr);
|
||||
{ TD_INTERFACE_IS_TYPE },
|
||||
&iid, 0, pErr);
|
||||
if (pi)
|
||||
pi->Release();
|
||||
return success;
|
||||
|
@ -578,41 +575,66 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
// must exit via VARIANT_DONE from here on...
|
||||
du.mType = nsIDataType::VTYPE_ARRAY;
|
||||
|
||||
nsXPTType conversionType;
|
||||
uint16_t elementType = du.u.array.mArrayType;
|
||||
const nsID* pid = nullptr;
|
||||
|
||||
nsXPTType::Idx xptIndex;
|
||||
switch (elementType) {
|
||||
case nsIDataType::VTYPE_INT8:
|
||||
xptIndex = nsXPTType::Idx::INT8;
|
||||
break;
|
||||
case nsIDataType::VTYPE_INT16:
|
||||
xptIndex = nsXPTType::Idx::INT16;
|
||||
break;
|
||||
case nsIDataType::VTYPE_INT32:
|
||||
xptIndex = nsXPTType::Idx::INT32;
|
||||
break;
|
||||
case nsIDataType::VTYPE_INT64:
|
||||
xptIndex = nsXPTType::Idx::INT64;
|
||||
break;
|
||||
case nsIDataType::VTYPE_UINT8:
|
||||
xptIndex = nsXPTType::Idx::UINT8;
|
||||
break;
|
||||
case nsIDataType::VTYPE_UINT16:
|
||||
xptIndex = nsXPTType::Idx::UINT16;
|
||||
break;
|
||||
case nsIDataType::VTYPE_UINT32:
|
||||
xptIndex = nsXPTType::Idx::UINT32;
|
||||
break;
|
||||
case nsIDataType::VTYPE_UINT64:
|
||||
xptIndex = nsXPTType::Idx::UINT64;
|
||||
break;
|
||||
case nsIDataType::VTYPE_FLOAT:
|
||||
xptIndex = nsXPTType::Idx::FLOAT;
|
||||
break;
|
||||
case nsIDataType::VTYPE_DOUBLE:
|
||||
xptIndex = nsXPTType::Idx::DOUBLE;
|
||||
break;
|
||||
case nsIDataType::VTYPE_BOOL:
|
||||
xptIndex = nsXPTType::Idx::BOOL;
|
||||
break;
|
||||
case nsIDataType::VTYPE_CHAR:
|
||||
xptIndex = nsXPTType::Idx::CHAR;
|
||||
break;
|
||||
case nsIDataType::VTYPE_WCHAR:
|
||||
conversionType = (uint8_t)elementType;
|
||||
xptIndex = nsXPTType::Idx::WCHAR;
|
||||
break;
|
||||
|
||||
case nsIDataType::VTYPE_ID:
|
||||
case nsIDataType::VTYPE_CHAR_STR:
|
||||
case nsIDataType::VTYPE_WCHAR_STR:
|
||||
conversionType = (uint8_t)elementType;
|
||||
xptIndex = nsXPTType::Idx::PNSIID;
|
||||
break;
|
||||
case nsIDataType::VTYPE_CHAR_STR:
|
||||
xptIndex = nsXPTType::Idx::PSTRING;
|
||||
break;
|
||||
case nsIDataType::VTYPE_WCHAR_STR:
|
||||
xptIndex = nsXPTType::Idx::PWSTRING;
|
||||
break;
|
||||
|
||||
case nsIDataType::VTYPE_INTERFACE:
|
||||
pid = &NS_GET_IID(nsISupports);
|
||||
conversionType = (uint8_t)elementType;
|
||||
xptIndex = nsXPTType::Idx::INTERFACE_IS_TYPE;
|
||||
break;
|
||||
|
||||
case nsIDataType::VTYPE_INTERFACE_IS:
|
||||
pid = &du.u.array.mArrayInterfaceID;
|
||||
conversionType = (uint8_t)elementType;
|
||||
xptIndex = nsXPTType::Idx::INTERFACE_IS_TYPE;
|
||||
break;
|
||||
|
||||
// The rest are illegal.
|
||||
|
@ -632,10 +654,9 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
|
|||
}
|
||||
|
||||
bool success =
|
||||
XPCConvert::NativeArray2JS(pJSVal,
|
||||
(const void**)&du.u.array.mArrayValue,
|
||||
conversionType, pid,
|
||||
du.u.array.mArrayCount, pErr);
|
||||
XPCConvert::NativeData2JS(pJSVal, (const void*)&du.u.array.mArrayValue,
|
||||
nsXPTType::MkArrayType(xptIndex), pid,
|
||||
du.u.array.mArrayCount, pErr);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ GetNamedPropertyAsVariantRaw(XPCCallContext& ccx,
|
|||
|
||||
return JS_GetPropertyById(ccx, aJSObj, aName, &val) &&
|
||||
XPCConvert::JSData2Native(aResult, val, type,
|
||||
&NS_GET_IID(nsIVariant), pErr);
|
||||
&NS_GET_IID(nsIVariant), 0, pErr);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -492,10 +492,10 @@ GetFunctionName(JSContext* cx, HandleObject obj)
|
|||
|
||||
nsCString displayName("anonymous");
|
||||
if (funName) {
|
||||
nsCString* displayNamePtr = &displayName;
|
||||
RootedValue funNameVal(cx, StringValue(funName));
|
||||
if (!XPCConvert::JSData2Native(&displayNamePtr, funNameVal, { nsXPTType::T_UTF8STRING },
|
||||
nullptr, nullptr))
|
||||
if (!XPCConvert::JSData2Native(&displayName, funNameVal,
|
||||
{ nsXPTType::T_UTF8STRING },
|
||||
nullptr, 0, nullptr))
|
||||
{
|
||||
JS_ClearPendingException(cx);
|
||||
return nsCString("anonymous");
|
||||
|
@ -663,162 +663,108 @@ nsXPCWrappedJSClass::GetRootJSObject(JSContext* cx, JSObject* aJSObjArg)
|
|||
}
|
||||
|
||||
bool
|
||||
nsXPCWrappedJSClass::GetArraySizeFromParam(JSContext* cx,
|
||||
const nsXPTMethodInfo* method,
|
||||
const nsXPTParamInfo& param,
|
||||
uint16_t methodIndex,
|
||||
uint8_t paramIndex,
|
||||
nsXPCWrappedJSClass::GetArraySizeFromParam(const nsXPTMethodInfo* method,
|
||||
const nsXPTType& type,
|
||||
nsXPTCMiniVariant* nativeParams,
|
||||
uint32_t* result) const
|
||||
{
|
||||
uint8_t argnum;
|
||||
nsresult rv;
|
||||
if (type.Tag() != nsXPTType::T_ARRAY &&
|
||||
type.Tag() != nsXPTType::T_PSTRING_SIZE_IS &&
|
||||
type.Tag() != nsXPTType::T_PWSTRING_SIZE_IS) {
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
rv = mInfo->GetSizeIsArgNumberForParam(methodIndex, ¶m, 0, &argnum);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
const nsXPTParamInfo& arg_param = method->GetParam(argnum);
|
||||
uint8_t argnum = type.ArgNum();
|
||||
const nsXPTParamInfo& param = method->Param(argnum);
|
||||
|
||||
// This should be enforced by the xpidl compiler, but it's not.
|
||||
// See bug 695235.
|
||||
MOZ_ASSERT(arg_param.GetType().TagPart() == nsXPTType::T_U32,
|
||||
"size_is references parameter of invalid type.");
|
||||
if (param.Type().Tag() != nsXPTType::T_U32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arg_param.IsIndirect())
|
||||
// If the length is passed indirectly (as an outparam), dereference by an
|
||||
// extra level.
|
||||
if (param.IsIndirect()) {
|
||||
*result = *(uint32_t*)nativeParams[argnum].val.p;
|
||||
else
|
||||
} else {
|
||||
*result = nativeParams[argnum].val.u32;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXPCWrappedJSClass::GetInterfaceTypeFromParam(JSContext* cx,
|
||||
const nsXPTMethodInfo* method,
|
||||
const nsXPTParamInfo& param,
|
||||
uint16_t methodIndex,
|
||||
nsXPCWrappedJSClass::GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
|
||||
const nsXPTType& type,
|
||||
nsXPTCMiniVariant* nativeParams,
|
||||
nsID* result) const
|
||||
{
|
||||
uint8_t type_tag = type.TagPart();
|
||||
result->Clear();
|
||||
|
||||
if (type_tag == nsXPTType::T_INTERFACE) {
|
||||
if (NS_SUCCEEDED(GetInterfaceInfo()->
|
||||
GetIIDForParamNoAlloc(methodIndex, ¶m, result))) {
|
||||
return true;
|
||||
}
|
||||
} else if (type_tag == nsXPTType::T_INTERFACE_IS) {
|
||||
uint8_t argnum;
|
||||
nsresult rv;
|
||||
rv = mInfo->GetInterfaceIsArgNumberForParam(methodIndex,
|
||||
¶m, &argnum);
|
||||
if (NS_FAILED(rv))
|
||||
const nsXPTType& inner = type.InnermostType();
|
||||
if (inner.Tag() == nsXPTType::T_INTERFACE) {
|
||||
// Directly get IID from nsXPTInterfaceInfo.
|
||||
if (!inner.GetInterface()) {
|
||||
return false;
|
||||
|
||||
const nsXPTParamInfo& arg_param = method->GetParam(argnum);
|
||||
const nsXPTType& arg_type = arg_param.GetType();
|
||||
|
||||
if (arg_type.TagPart() == nsXPTType::T_IID) {
|
||||
if (arg_param.IsIndirect()) {
|
||||
nsID** p = (nsID**) nativeParams[argnum].val.p;
|
||||
if (!p || !*p)
|
||||
return false;
|
||||
*result = **p;
|
||||
} else {
|
||||
nsID* p = (nsID*) nativeParams[argnum].val.p;
|
||||
if (!p)
|
||||
return false;
|
||||
*result = *p;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsXPCWrappedJSClass::CleanupPointerArray(const nsXPTType& datum_type,
|
||||
uint32_t array_count,
|
||||
void** arrayp)
|
||||
{
|
||||
if (datum_type.IsInterfacePointer()) {
|
||||
nsISupports** pp = (nsISupports**) arrayp;
|
||||
for (uint32_t k = 0; k < array_count; k++) {
|
||||
nsISupports* p = pp[k];
|
||||
NS_IF_RELEASE(p);
|
||||
*result = inner.GetInterface()->IID();
|
||||
} else if (inner.Tag() == nsXPTType::T_INTERFACE_IS) {
|
||||
// Get IID from a passed parameter.
|
||||
const nsXPTParamInfo& param = method->Param(inner.ArgNum());
|
||||
if (param.Type().Tag() != nsXPTType::T_IID) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
void** pp = (void**) arrayp;
|
||||
for (uint32_t k = 0; k < array_count; k++) {
|
||||
void* p = pp[k];
|
||||
if (p) free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsXPCWrappedJSClass::CleanupPointerTypeObject(const nsXPTType& type,
|
||||
void** pp)
|
||||
{
|
||||
MOZ_ASSERT(pp,"null pointer");
|
||||
if (type.IsInterfacePointer()) {
|
||||
nsISupports* p = *((nsISupports**)pp);
|
||||
if (p) p->Release();
|
||||
} else {
|
||||
void* p = *((void**)pp);
|
||||
if (p) free(p);
|
||||
void* ptr = nativeParams[inner.ArgNum()].val.p;
|
||||
|
||||
// If the IID is passed indirectly (as an outparam), dereference by an
|
||||
// extra level.
|
||||
if (ptr && param.IsIndirect()) {
|
||||
ptr = *(nsID**) ptr;
|
||||
}
|
||||
|
||||
if (!ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = *(nsID*) ptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsXPCWrappedJSClass::CleanupOutparams(JSContext* cx, uint16_t methodIndex,
|
||||
const nsXPTMethodInfo* info, nsXPTCMiniVariant* nativeParams,
|
||||
bool inOutOnly, uint8_t n) const
|
||||
nsXPCWrappedJSClass::CleanupOutparams(const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* nativeParams,
|
||||
bool inOutOnly, uint8_t count) const
|
||||
{
|
||||
// clean up any 'out' params handed in
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
if (!param.IsOut())
|
||||
continue;
|
||||
|
||||
const nsXPTType& type = param.GetType();
|
||||
if (!type.deprecated_IsPointer())
|
||||
continue;
|
||||
void* p = nativeParams[i].val.p;
|
||||
if (!p)
|
||||
// Extract the array length so we can use it in CleanupValue.
|
||||
uint32_t arrayLen = 0;
|
||||
if (!GetArraySizeFromParam(info, param.Type(), nativeParams, &arrayLen))
|
||||
continue;
|
||||
|
||||
// The inOutOnly flag was introduced when consolidating two very
|
||||
// similar code paths in CallMethod in bug 1175513. I don't know
|
||||
// if and why the difference is necessary.
|
||||
MOZ_ASSERT(param.IsIndirect(), "Outparams are always indirect");
|
||||
|
||||
// The inOutOnly flag is necessary because full outparams may contain
|
||||
// uninitialized junk before the call is made, and we don't want to try
|
||||
// to clean up uninitialized junk.
|
||||
if (!inOutOnly || param.IsIn()) {
|
||||
if (type.IsArray()) {
|
||||
void** pp = *static_cast<void***>(p);
|
||||
if (pp) {
|
||||
// we need to get the array length and iterate the items
|
||||
uint32_t array_count;
|
||||
nsXPTType datum_type;
|
||||
|
||||
if (NS_SUCCEEDED(mInfo->GetTypeForParam(methodIndex, ¶m,
|
||||
1, &datum_type)) &&
|
||||
datum_type.deprecated_IsPointer() &&
|
||||
GetArraySizeFromParam(cx, info, param, methodIndex,
|
||||
i, nativeParams, &array_count) &&
|
||||
array_count) {
|
||||
|
||||
CleanupPointerArray(datum_type, array_count, pp);
|
||||
}
|
||||
|
||||
// always release the array if it is inout
|
||||
free(pp);
|
||||
}
|
||||
} else {
|
||||
CleanupPointerTypeObject(type, static_cast<void**>(p));
|
||||
}
|
||||
xpc::CleanupValue(param.Type(), nativeParams[i].val.p, arrayLen);
|
||||
}
|
||||
|
||||
// Even if we didn't call CleanupValue, null out any pointers. This is
|
||||
// just to protect C++ callers which may read garbage if they forget to
|
||||
// check the error value.
|
||||
if (param.Type().HasPointerRepr()) {
|
||||
*(void**)nativeParams[i].val.p = nullptr;
|
||||
}
|
||||
*static_cast<void**>(p) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1102,14 +1048,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
|||
for (i = 0; i < argc; i++) {
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
const nsXPTType& type = param.GetType();
|
||||
nsXPTType datum_type;
|
||||
uint32_t array_count;
|
||||
bool isArray = type.IsArray();
|
||||
RootedValue val(cx, NullValue());
|
||||
bool isSizedString = isArray ?
|
||||
false :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
|
||||
// verify that null was not passed for 'out' param
|
||||
|
@ -1118,53 +1058,24 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
|||
goto pre_call_clean_up;
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
if (NS_FAILED(mInfo->GetTypeForParam(methodIndex, ¶m, 1,
|
||||
&datum_type)))
|
||||
goto pre_call_clean_up;
|
||||
} else
|
||||
datum_type = type;
|
||||
|
||||
if (param.IsIn()) {
|
||||
nsXPTCMiniVariant* pv;
|
||||
|
||||
const void* pv;
|
||||
if (param.IsIndirect())
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
pv = nativeParams[i].val.p;
|
||||
else
|
||||
pv = &nativeParams[i];
|
||||
|
||||
if (datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(cx, info, param, methodIndex,
|
||||
datum_type, nativeParams,
|
||||
¶m_iid))
|
||||
if (!GetInterfaceTypeFromParam(info, type, nativeParams, ¶m_iid) ||
|
||||
!GetArraySizeFromParam(info, type, nativeParams, &array_count))
|
||||
goto pre_call_clean_up;
|
||||
|
||||
if (isArray || isSizedString) {
|
||||
if (!GetArraySizeFromParam(cx, info, param, methodIndex,
|
||||
i, nativeParams, &array_count))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
if (!XPCConvert::NativeArray2JS(&val,
|
||||
(const void**)&pv->val,
|
||||
datum_type, ¶m_iid,
|
||||
array_count, nullptr))
|
||||
goto pre_call_clean_up;
|
||||
} else if (isSizedString) {
|
||||
if (!XPCConvert::NativeStringWithSize2JS(&val,
|
||||
(const void*)&pv->val,
|
||||
datum_type,
|
||||
array_count, nullptr))
|
||||
goto pre_call_clean_up;
|
||||
} else {
|
||||
if (!XPCConvert::NativeData2JS(&val, &pv->val, type,
|
||||
¶m_iid, nullptr))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
if (!XPCConvert::NativeData2JS(&val, pv, type,
|
||||
¶m_iid, array_count,
|
||||
nullptr))
|
||||
goto pre_call_clean_up;
|
||||
}
|
||||
|
||||
if (param.IsOut() || param.IsDipper()) {
|
||||
if (param.IsOut()) {
|
||||
// create an 'out' object
|
||||
RootedObject out_obj(cx, NewOutObject(cx));
|
||||
if (!out_obj) {
|
||||
|
@ -1188,7 +1099,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
|||
|
||||
pre_call_clean_up:
|
||||
// clean up any 'out' params handed in
|
||||
CleanupOutparams(cx, methodIndex, info, nativeParams, /* inOutOnly = */ true, paramCount);
|
||||
CleanupOutparams(info, nativeParams, /* inOutOnly = */ true, paramCount);
|
||||
|
||||
// Make sure "this" doesn't get deleted during this call.
|
||||
nsCOMPtr<nsIXPCWrappedJSClass> kungFuDeathGrip(this);
|
||||
|
@ -1247,7 +1158,7 @@ pre_call_clean_up:
|
|||
for (i = 0; i < paramCount; i++) {
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
MOZ_ASSERT(!param.IsShared(), "[shared] implies [noscript]!");
|
||||
if (!param.IsOut() && !param.IsDipper())
|
||||
if (!param.IsOut())
|
||||
continue;
|
||||
|
||||
const nsXPTType& type = param.GetType();
|
||||
|
@ -1257,13 +1168,6 @@ pre_call_clean_up:
|
|||
}
|
||||
|
||||
RootedValue val(cx);
|
||||
uint8_t type_tag = type.TagPart();
|
||||
nsXPTCMiniVariant* pv;
|
||||
|
||||
if (param.IsDipper())
|
||||
pv = (nsXPTCMiniVariant*) &nativeParams[i].val.p;
|
||||
else
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
|
||||
if (¶m == info->GetRetval())
|
||||
val = rval;
|
||||
|
@ -1279,15 +1183,16 @@ pre_call_clean_up:
|
|||
|
||||
// setup allocator and/or iid
|
||||
|
||||
if (type_tag == nsXPTType::T_INTERFACE) {
|
||||
if (NS_FAILED(GetInterfaceInfo()->
|
||||
GetIIDForParamNoAlloc(methodIndex, ¶m,
|
||||
¶m_iid)))
|
||||
const nsXPTType& inner = type.InnermostType();
|
||||
if (inner.Tag() == nsXPTType::T_INTERFACE) {
|
||||
if (!inner.GetInterface())
|
||||
break;
|
||||
param_iid = inner.GetInterface()->IID();
|
||||
}
|
||||
|
||||
if (!XPCConvert::JSData2Native(&pv->val, val, type,
|
||||
¶m_iid, nullptr))
|
||||
MOZ_ASSERT(param.IsIndirect(), "outparams are always indirect");
|
||||
if (!XPCConvert::JSData2Native(nativeParams[i].val.p, val, type,
|
||||
¶m_iid, 0, nullptr))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1303,16 +1208,7 @@ pre_call_clean_up:
|
|||
continue;
|
||||
|
||||
RootedValue val(cx);
|
||||
nsXPTCMiniVariant* pv;
|
||||
nsXPTType datum_type;
|
||||
uint32_t array_count;
|
||||
bool isArray = type.IsArray();
|
||||
bool isSizedString = isArray ?
|
||||
false :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
pv = (nsXPTCMiniVariant*) nativeParams[i].val.p;
|
||||
|
||||
if (¶m == info->GetRetval())
|
||||
val = rval;
|
||||
|
@ -1326,50 +1222,21 @@ pre_call_clean_up:
|
|||
|
||||
// setup allocator and/or iid
|
||||
|
||||
if (isArray) {
|
||||
if (NS_FAILED(mInfo->GetTypeForParam(methodIndex, ¶m, 1,
|
||||
&datum_type)))
|
||||
break;
|
||||
} else
|
||||
datum_type = type;
|
||||
if (!GetInterfaceTypeFromParam(info, type, nativeParams, ¶m_iid) ||
|
||||
!GetArraySizeFromParam(info, type, nativeParams, &array_count))
|
||||
break;
|
||||
|
||||
if (datum_type.IsInterfacePointer()) {
|
||||
if (!GetInterfaceTypeFromParam(cx, info, param, methodIndex,
|
||||
datum_type, nativeParams,
|
||||
¶m_iid))
|
||||
break;
|
||||
}
|
||||
|
||||
if (isArray || isSizedString) {
|
||||
if (!GetArraySizeFromParam(cx, info, param, methodIndex,
|
||||
i, nativeParams, &array_count))
|
||||
break;
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
if (array_count &&
|
||||
!XPCConvert::JSArray2Native((void**)&pv->val, val,
|
||||
array_count, datum_type,
|
||||
¶m_iid, nullptr))
|
||||
break;
|
||||
} else if (isSizedString) {
|
||||
if (!XPCConvert::JSStringWithSize2Native((void*)&pv->val, val,
|
||||
array_count, datum_type,
|
||||
nullptr))
|
||||
break;
|
||||
} else {
|
||||
if (!XPCConvert::JSData2Native(&pv->val, val, type,
|
||||
¶m_iid,
|
||||
nullptr))
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(param.IsIndirect(), "outparams are always indirect");
|
||||
if (!XPCConvert::JSData2Native(nativeParams[i].val.p, val, type,
|
||||
¶m_iid, array_count, nullptr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != paramCount) {
|
||||
// We didn't manage all the result conversions!
|
||||
// We have to cleanup any junk that *did* get converted.
|
||||
CleanupOutparams(cx, methodIndex, info, nativeParams, /* inOutOnly = */ false, i);
|
||||
CleanupOutparams(info, nativeParams, /* inOutOnly = */ false, i);
|
||||
} else {
|
||||
// set to whatever the JS code might have set as the result
|
||||
retval = xpccx->GetPendingResult();
|
||||
|
|
|
@ -1133,7 +1133,7 @@ static bool Throw(nsresult errNum, XPCCallContext& ccx)
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
class MOZ_STACK_CLASS CallMethodHelper
|
||||
class MOZ_STACK_CLASS CallMethodHelper final
|
||||
{
|
||||
XPCCallContext& mCallContext;
|
||||
nsresult mInvokeResult;
|
||||
|
@ -1151,12 +1151,10 @@ class MOZ_STACK_CLASS CallMethodHelper
|
|||
const uint32_t mArgc;
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
GetArraySizeFromParam(uint8_t paramIndex, HandleValue maybeArray, uint32_t* result);
|
||||
GetArraySizeFromParam(const nsXPTType& type, HandleValue maybeArray, uint32_t* result);
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
GetInterfaceTypeFromParam(uint8_t paramIndex,
|
||||
const nsXPTType& datum_type,
|
||||
nsID* result) const;
|
||||
GetInterfaceTypeFromParam(const nsXPTType& type, nsID* result) const;
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
GetOutParamSource(uint8_t paramIndex, MutableHandleValue srcp) const;
|
||||
|
@ -1189,11 +1187,6 @@ class MOZ_STACK_CLASS CallMethodHelper
|
|||
MOZ_ALWAYS_INLINE bool ConvertDependentParams();
|
||||
MOZ_ALWAYS_INLINE bool ConvertDependentParam(uint8_t i);
|
||||
|
||||
MOZ_ALWAYS_INLINE void CleanupParam(nsXPTCMiniVariant& param, nsXPTType& type);
|
||||
|
||||
MOZ_ALWAYS_INLINE bool AllocateStringClass(nsXPTCVariant* dp,
|
||||
const nsXPTParamInfo& paramInfo);
|
||||
|
||||
MOZ_ALWAYS_INLINE nsresult Invoke();
|
||||
|
||||
public:
|
||||
|
@ -1220,6 +1213,9 @@ public:
|
|||
|
||||
MOZ_ALWAYS_INLINE bool Call();
|
||||
|
||||
// Trace implementation so we can put our CallMethodHelper in a Rooted<T>.
|
||||
void trace(JSTracer* aTrc);
|
||||
|
||||
};
|
||||
|
||||
// static
|
||||
|
@ -1232,7 +1228,8 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
|||
return Throw(rv, ccx);
|
||||
}
|
||||
|
||||
return CallMethodHelper(ccx).Call();
|
||||
JS::Rooted<CallMethodHelper> helper(ccx, /* init = */ ccx);
|
||||
return helper.get().Call();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1281,82 +1278,51 @@ CallMethodHelper::Call()
|
|||
|
||||
CallMethodHelper::~CallMethodHelper()
|
||||
{
|
||||
uint8_t paramCount = mMethodInfo->GetParamCount();
|
||||
if (mDispatchParams.Length()) {
|
||||
for (uint8_t i = 0; i < paramCount; i++) {
|
||||
nsXPTCVariant* dp = GetDispatchParam(i);
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
|
||||
for (nsXPTCVariant& param : mDispatchParams) {
|
||||
// Only clean up values which need cleanup.
|
||||
if (!param.DoesValNeedCleanup())
|
||||
continue;
|
||||
|
||||
if (paramInfo.GetType().IsArray()) {
|
||||
void* p = dp->val.p;
|
||||
if (!p)
|
||||
continue;
|
||||
uint32_t arraylen = 0;
|
||||
if (!GetArraySizeFromParam(param.type, UndefinedHandleValue, &arraylen))
|
||||
continue;
|
||||
|
||||
// Clean up the array contents if necessary.
|
||||
if (dp->DoesValNeedCleanup()) {
|
||||
// We need some basic information to properly destroy the array.
|
||||
uint32_t array_count = 0;
|
||||
nsXPTType datum_type;
|
||||
if (!GetArraySizeFromParam(i, UndefinedHandleValue, &array_count) ||
|
||||
!NS_SUCCEEDED(mIFaceInfo->GetTypeForParam(mVTableIndex,
|
||||
¶mInfo,
|
||||
1, &datum_type))) {
|
||||
// XXXbholley - I'm not convinced that the above calls will
|
||||
// ever fail.
|
||||
NS_ERROR("failed to get array information, we'll leak here");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Loop over the array contents. For each one, we create a
|
||||
// dummy 'val' and pass it to the cleanup helper.
|
||||
for (uint32_t k = 0; k < array_count; k++) {
|
||||
nsXPTCMiniVariant v;
|
||||
v.val.p = static_cast<void**>(p)[k];
|
||||
CleanupParam(v, datum_type);
|
||||
}
|
||||
}
|
||||
|
||||
// always free the array itself
|
||||
free(p);
|
||||
} else {
|
||||
// Clean up single parameters (if requested).
|
||||
if (dp->DoesValNeedCleanup())
|
||||
CleanupParam(*dp, dp->type);
|
||||
}
|
||||
}
|
||||
xpc::CleanupValue(param.type, ¶m.val, arraylen);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CallMethodHelper::GetArraySizeFromParam(uint8_t paramIndex,
|
||||
CallMethodHelper::GetArraySizeFromParam(const nsXPTType& type,
|
||||
HandleValue maybeArray,
|
||||
uint32_t* result)
|
||||
{
|
||||
nsresult rv;
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(paramIndex);
|
||||
if (type.Tag() != nsXPTType::T_ARRAY &&
|
||||
type.Tag() != nsXPTType::T_PSTRING_SIZE_IS &&
|
||||
type.Tag() != nsXPTType::T_PWSTRING_SIZE_IS) {
|
||||
*result = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t argnum = type.ArgNum();
|
||||
uint32_t* lengthp = &GetDispatchParam(argnum)->val.u32;
|
||||
|
||||
// TODO fixup the various exceptions that are thrown
|
||||
|
||||
rv = mIFaceInfo->GetSizeIsArgNumberForParam(mVTableIndex, ¶mInfo, 0, ¶mIndex);
|
||||
if (NS_FAILED(rv))
|
||||
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
|
||||
// If the array length wasn't passed, it might have been listed as optional.
|
||||
// When converting arguments from JS to C++, we pass the array as |maybeArray|,
|
||||
// and give ourselves the chance to infer the length. Once we have it, we stick
|
||||
// it in the right slot so that we can find it again when cleaning up the params.
|
||||
// from the array.
|
||||
if (paramIndex >= mArgc && maybeArray.isObject()) {
|
||||
MOZ_ASSERT(mMethodInfo->GetParam(paramIndex).IsOptional());
|
||||
RootedObject arrayOrNull(mCallContext, maybeArray.isObject() ? &maybeArray.toObject()
|
||||
: nullptr);
|
||||
if (argnum >= mArgc && maybeArray.isObject()) {
|
||||
MOZ_ASSERT(mMethodInfo->Param(argnum).IsOptional());
|
||||
RootedObject arrayOrNull(mCallContext, &maybeArray.toObject());
|
||||
|
||||
bool isArray;
|
||||
bool ok = false;
|
||||
if (JS_IsArrayObject(mCallContext, maybeArray, &isArray) && isArray) {
|
||||
ok = JS_GetArrayLength(mCallContext, arrayOrNull, &GetDispatchParam(paramIndex)->val.u32);
|
||||
ok = JS_GetArrayLength(mCallContext, arrayOrNull, lengthp);
|
||||
} else if (JS_IsTypedArrayObject(&maybeArray.toObject())) {
|
||||
GetDispatchParam(paramIndex)->val.u32 = JS_GetTypedArrayLength(&maybeArray.toObject());
|
||||
*lengthp = JS_GetTypedArrayLength(&maybeArray.toObject());
|
||||
ok = true;
|
||||
}
|
||||
|
||||
|
@ -1365,38 +1331,31 @@ CallMethodHelper::GetArraySizeFromParam(uint8_t paramIndex,
|
|||
}
|
||||
}
|
||||
|
||||
*result = GetDispatchParam(paramIndex)->val.u32;
|
||||
|
||||
*result = *lengthp;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CallMethodHelper::GetInterfaceTypeFromParam(uint8_t paramIndex,
|
||||
const nsXPTType& datum_type,
|
||||
CallMethodHelper::GetInterfaceTypeFromParam(const nsXPTType& type,
|
||||
nsID* result) const
|
||||
{
|
||||
nsresult rv;
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(paramIndex);
|
||||
uint8_t tag = datum_type.TagPart();
|
||||
result->Clear();
|
||||
|
||||
// TODO fixup the various exceptions that are thrown
|
||||
const nsXPTType& inner = type.InnermostType();
|
||||
if (inner.Tag() == nsXPTType::T_INTERFACE) {
|
||||
if (!inner.GetInterface()) {
|
||||
return Throw(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, mCallContext);
|
||||
}
|
||||
|
||||
if (tag == nsXPTType::T_INTERFACE) {
|
||||
rv = mIFaceInfo->GetIIDForParamNoAlloc(mVTableIndex, ¶mInfo, result);
|
||||
if (NS_FAILED(rv))
|
||||
*result = inner.GetInterface()->IID();
|
||||
} else if (inner.Tag() == nsXPTType::T_INTERFACE_IS) {
|
||||
nsID* id = (nsID*) GetDispatchParam(inner.ArgNum())->val.p;
|
||||
if (!id) {
|
||||
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
|
||||
paramIndex, mCallContext);
|
||||
} else if (tag == nsXPTType::T_INTERFACE_IS) {
|
||||
rv = mIFaceInfo->GetInterfaceIsArgNumberForParam(mVTableIndex, ¶mInfo,
|
||||
¶mIndex);
|
||||
if (NS_FAILED(rv))
|
||||
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
inner.ArgNum(), mCallContext);
|
||||
}
|
||||
|
||||
nsID* p = (nsID*) GetDispatchParam(paramIndex)->val.p;
|
||||
if (!p)
|
||||
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
|
||||
paramIndex, mCallContext);
|
||||
*result = *p;
|
||||
*result = *id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1407,7 +1366,6 @@ CallMethodHelper::GetOutParamSource(uint8_t paramIndex, MutableHandleValue srcp)
|
|||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(paramIndex);
|
||||
bool isRetval = ¶mInfo == mMethodInfo->GetRetval();
|
||||
|
||||
MOZ_ASSERT(!paramInfo.IsDipper(), "Dipper params are handled separately");
|
||||
if (paramInfo.IsOut() && !isRetval) {
|
||||
MOZ_ASSERT(paramIndex < mArgc || paramInfo.IsOptional(),
|
||||
"Expected either enough arguments or an optional argument");
|
||||
|
@ -1437,62 +1395,24 @@ CallMethodHelper::GatherAndConvertResults()
|
|||
uint8_t paramCount = mMethodInfo->GetParamCount();
|
||||
for (uint8_t i = 0; i < paramCount; i++) {
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
|
||||
if (!paramInfo.IsOut() && !paramInfo.IsDipper())
|
||||
if (!paramInfo.IsOut())
|
||||
continue;
|
||||
|
||||
const nsXPTType& type = paramInfo.GetType();
|
||||
nsXPTCVariant* dp = GetDispatchParam(i);
|
||||
RootedValue v(mCallContext, NullValue());
|
||||
|
||||
uint32_t array_count = 0;
|
||||
nsXPTType datum_type;
|
||||
bool isArray = type.IsArray();
|
||||
bool isSizedString = isArray ?
|
||||
false :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
if (isArray) {
|
||||
if (NS_FAILED(mIFaceInfo->GetTypeForParam(mVTableIndex, ¶mInfo, 1,
|
||||
&datum_type))) {
|
||||
Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
datum_type = type;
|
||||
|
||||
if (isArray || isSizedString) {
|
||||
if (!GetArraySizeFromParam(i, UndefinedHandleValue, &array_count))
|
||||
return false;
|
||||
}
|
||||
|
||||
nsID param_iid;
|
||||
if (datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(i, datum_type, ¶m_iid))
|
||||
if (!GetInterfaceTypeFromParam(type, ¶m_iid) ||
|
||||
!GetArraySizeFromParam(type, UndefinedHandleValue, &array_count))
|
||||
return false;
|
||||
|
||||
nsresult err;
|
||||
if (isArray) {
|
||||
if (!XPCConvert::NativeArray2JS(&v, (const void**)&dp->val,
|
||||
datum_type, ¶m_iid,
|
||||
array_count, &err)) {
|
||||
// XXX need exception scheme for arrays to indicate bad element
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
} else if (isSizedString) {
|
||||
if (!XPCConvert::NativeStringWithSize2JS(&v,
|
||||
(const void*)&dp->val,
|
||||
datum_type,
|
||||
array_count, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!XPCConvert::NativeData2JS(&v, &dp->val, datum_type,
|
||||
¶m_iid, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
if (!XPCConvert::NativeData2JS(&v, &dp->val, type,
|
||||
¶m_iid, array_count, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (¶mInfo == mMethodInfo->GetRetval()) {
|
||||
|
@ -1549,7 +1469,7 @@ CallMethodHelper::QueryInterfaceFastPath()
|
|||
bool success =
|
||||
XPCConvert::NativeData2JS(&v, &qiresult,
|
||||
{ nsXPTType::T_INTERFACE_IS },
|
||||
iid, &err);
|
||||
iid, 0, &err);
|
||||
NS_IF_RELEASE(qiresult);
|
||||
|
||||
if (!success) {
|
||||
|
@ -1647,48 +1567,34 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i)
|
|||
{
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
|
||||
const nsXPTType& type = paramInfo.GetType();
|
||||
uint8_t type_tag = type.TagPart();
|
||||
nsXPTCVariant* dp = GetDispatchParam(i);
|
||||
dp->type = type;
|
||||
MOZ_ASSERT(!paramInfo.IsShared(), "[shared] implies [noscript]!");
|
||||
|
||||
// String classes are always "in" - those that are marked "out" are converted
|
||||
// by the XPIDL compiler to "in+dipper". See the note above IsDipper() in
|
||||
// xptinfo.h.
|
||||
//
|
||||
// Also note that the fact that we bail out early for dipper parameters means
|
||||
// that "inout" dipper parameters don't work - see bug 687612.
|
||||
if (paramInfo.IsStringClass()) {
|
||||
if (!AllocateStringClass(dp, paramInfo))
|
||||
return false;
|
||||
if (paramInfo.IsDipper()) {
|
||||
// We've allocated our string class explicitly, so we don't need
|
||||
// to do any conversions on the incoming argument. However, we still
|
||||
// need to verify that it's an object, so that we don't get surprised
|
||||
// later on when trying to assign the result to .value.
|
||||
if (i < mArgc && !mArgv[i].isObject()) {
|
||||
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Specify the correct storage/calling semantics.
|
||||
if (paramInfo.IsIndirect())
|
||||
dp->SetIndirect();
|
||||
|
||||
// The JSVal proper is always stored within the 'val' union and passed
|
||||
// indirectly, regardless of in/out-ness.
|
||||
if (type_tag == nsXPTType::T_JSVAL) {
|
||||
// Root the value.
|
||||
new (&dp->val.j) JS::Value();
|
||||
MOZ_ASSERT(dp->val.j.isUndefined());
|
||||
if (!js::AddRawValueRoot(mCallContext, &dp->val.j,
|
||||
"XPCWrappedNative::CallMethod param"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Some types are always stored within the nsXPTCVariant, and passed
|
||||
// indirectly, regardless of in/out-ness. These types are stored in the
|
||||
// nsXPTCVariant's extended value.
|
||||
switch (type.Tag()) {
|
||||
// Ensure that the jsval has a valid value.
|
||||
case nsXPTType::T_JSVAL:
|
||||
new (&dp->ext.jsval) JS::Value();
|
||||
MOZ_ASSERT(dp->ext.jsval.isUndefined());
|
||||
break;
|
||||
|
||||
// Initialize our temporary string class values so they can be assigned
|
||||
// to by the XPCConvert logic.
|
||||
case nsXPTType::T_ASTRING:
|
||||
case nsXPTType::T_DOMSTRING:
|
||||
new (&dp->ext.nsstr) nsString();
|
||||
break;
|
||||
case nsXPTType::T_CSTRING:
|
||||
case nsXPTType::T_UTF8STRING:
|
||||
new (&dp->ext.nscstr) nsCString();
|
||||
break;
|
||||
}
|
||||
|
||||
// Flag cleanup for anything that isn't self-contained.
|
||||
|
@ -1719,25 +1625,27 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i)
|
|||
"Expected either enough arguments or an optional argument");
|
||||
if (i < mArgc)
|
||||
src = mArgv[i];
|
||||
else if (type_tag == nsXPTType::T_JSVAL)
|
||||
else if (type.Tag() == nsXPTType::T_JSVAL)
|
||||
src.setUndefined();
|
||||
else
|
||||
src.setNull();
|
||||
}
|
||||
|
||||
nsID param_iid;
|
||||
if (type_tag == nsXPTType::T_INTERFACE &&
|
||||
NS_FAILED(mIFaceInfo->GetIIDForParamNoAlloc(mVTableIndex, ¶mInfo,
|
||||
¶m_iid))) {
|
||||
ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, i, mCallContext);
|
||||
return false;
|
||||
nsID param_iid = { 0 };
|
||||
const nsXPTType& inner = type.InnermostType();
|
||||
if (inner.Tag() == nsXPTType::T_INTERFACE) {
|
||||
if (!inner.GetInterface()) {
|
||||
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
|
||||
i, mCallContext);
|
||||
}
|
||||
param_iid = inner.GetInterface()->IID();
|
||||
}
|
||||
|
||||
// Don't allow CPOWs to be passed to native code (in case they try to cast
|
||||
// to a concrete type).
|
||||
if (src.isObject() &&
|
||||
jsipc::IsWrappedCPOW(&src.toObject()) &&
|
||||
type_tag == nsXPTType::T_INTERFACE &&
|
||||
type.Tag() == nsXPTType::T_INTERFACE &&
|
||||
!param_iid.Equals(NS_GET_IID(nsISupports)))
|
||||
{
|
||||
// Allow passing CPOWs to XPCWrappedJS.
|
||||
|
@ -1749,7 +1657,7 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i)
|
|||
}
|
||||
|
||||
nsresult err;
|
||||
if (!XPCConvert::JSData2Native(&dp->val, src, type, ¶m_iid, &err)) {
|
||||
if (!XPCConvert::JSData2Native(&dp->val, src, type, ¶m_iid, 0, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
|
@ -1778,41 +1686,17 @@ CallMethodHelper::ConvertDependentParam(uint8_t i)
|
|||
{
|
||||
const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
|
||||
const nsXPTType& type = paramInfo.GetType();
|
||||
nsXPTType datum_type;
|
||||
uint32_t array_count = 0;
|
||||
bool isArray = type.IsArray();
|
||||
|
||||
bool isSizedString = isArray ?
|
||||
false :
|
||||
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
|
||||
type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
|
||||
|
||||
nsXPTCVariant* dp = GetDispatchParam(i);
|
||||
dp->type = type;
|
||||
|
||||
if (isArray) {
|
||||
if (NS_FAILED(mIFaceInfo->GetTypeForParam(mVTableIndex, ¶mInfo, 1,
|
||||
&datum_type))) {
|
||||
Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(datum_type.TagPart() != nsXPTType::T_JSVAL,
|
||||
"Arrays of JSVals not currently supported - see bug 693337.");
|
||||
} else {
|
||||
datum_type = type;
|
||||
}
|
||||
|
||||
// Specify the correct storage/calling semantics.
|
||||
if (paramInfo.IsIndirect())
|
||||
dp->SetIndirect();
|
||||
|
||||
// We have 3 possible type of dependent parameters: Arrays, Sized Strings,
|
||||
// and iid_is Interface pointers. The latter two always need cleanup, and
|
||||
// arrays need cleanup for all non-arithmetic types. Since the latter two
|
||||
// cases also happen to be non-arithmetic, we can just inspect datum_type
|
||||
// here.
|
||||
if (!datum_type.IsArithmetic())
|
||||
dp->SetValNeedsCleanup();
|
||||
// Make sure we clean up all of our dependent types. All of them require
|
||||
// allocations of some kind.
|
||||
dp->SetValNeedsCleanup();
|
||||
|
||||
// Even if there's nothing to convert, we still need to examine the
|
||||
// JSObject container for out-params. If it's null or otherwise invalid,
|
||||
|
@ -1840,116 +1724,19 @@ CallMethodHelper::ConvertDependentParam(uint8_t i)
|
|||
}
|
||||
|
||||
nsID param_iid;
|
||||
if (datum_type.IsInterfacePointer() &&
|
||||
!GetInterfaceTypeFromParam(i, datum_type, ¶m_iid))
|
||||
uint32_t array_count;
|
||||
if (!GetInterfaceTypeFromParam(type, ¶m_iid) ||
|
||||
!GetArraySizeFromParam(type, src, &array_count))
|
||||
return false;
|
||||
|
||||
nsresult err;
|
||||
|
||||
if (isArray || isSizedString) {
|
||||
if (!GetArraySizeFromParam(i, src, &array_count))
|
||||
return false;
|
||||
|
||||
if (isArray) {
|
||||
if (array_count &&
|
||||
!XPCConvert::JSArray2Native((void**)&dp->val, src,
|
||||
array_count, datum_type, ¶m_iid,
|
||||
&err)) {
|
||||
// XXX need exception scheme for arrays to indicate bad element
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
} else // if (isSizedString)
|
||||
{
|
||||
if (!XPCConvert::JSStringWithSize2Native((void*)&dp->val,
|
||||
src, array_count,
|
||||
datum_type, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!XPCConvert::JSData2Native(&dp->val, src, type,
|
||||
¶m_iid, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Performs all necessary teardown on a parameter after method invocation.
|
||||
//
|
||||
// This method should only be called if the value in question was flagged
|
||||
// for cleanup (ie, if dp->DoesValNeedCleanup()).
|
||||
void
|
||||
CallMethodHelper::CleanupParam(nsXPTCMiniVariant& param, nsXPTType& type)
|
||||
{
|
||||
// We handle array elements, but not the arrays themselves.
|
||||
MOZ_ASSERT(type.TagPart() != nsXPTType::T_ARRAY, "Can't handle arrays.");
|
||||
|
||||
// Pointers may sometimes be null even if cleanup was requested. Combine
|
||||
// the null checking for all the different types into one check here.
|
||||
if (type.TagPart() != nsXPTType::T_JSVAL && param.val.p == nullptr)
|
||||
return;
|
||||
|
||||
switch (type.TagPart()) {
|
||||
case nsXPTType::T_JSVAL:
|
||||
js::RemoveRawValueRoot(mCallContext, ¶m.val.j);
|
||||
break;
|
||||
case nsXPTType::T_INTERFACE:
|
||||
case nsXPTType::T_INTERFACE_IS:
|
||||
((nsISupports*)param.val.p)->Release();
|
||||
break;
|
||||
case nsXPTType::T_DOMOBJECT:
|
||||
type.GetDOMObjectInfo().Cleanup(param.val.p);
|
||||
break;
|
||||
case nsXPTType::T_ASTRING:
|
||||
case nsXPTType::T_DOMSTRING:
|
||||
mCallContext.GetContext()->mScratchStrings.Destroy((nsString*)param.val.p);
|
||||
break;
|
||||
case nsXPTType::T_UTF8STRING:
|
||||
case nsXPTType::T_CSTRING:
|
||||
mCallContext.GetContext()->mScratchCStrings.Destroy((nsCString*)param.val.p);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(!type.IsArithmetic(), "Cleanup requested on unexpected type.");
|
||||
free(param.val.p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CallMethodHelper::AllocateStringClass(nsXPTCVariant* dp,
|
||||
const nsXPTParamInfo& paramInfo)
|
||||
{
|
||||
// Get something we can make comparisons with.
|
||||
uint8_t type_tag = paramInfo.GetType().TagPart();
|
||||
|
||||
// There should be 4 cases, all strings. Verify that here.
|
||||
MOZ_ASSERT(type_tag == nsXPTType::T_ASTRING ||
|
||||
type_tag == nsXPTType::T_DOMSTRING ||
|
||||
type_tag == nsXPTType::T_UTF8STRING ||
|
||||
type_tag == nsXPTType::T_CSTRING,
|
||||
"Unexpected string class type!");
|
||||
|
||||
// ASTRING and DOMSTRING are very similar, and both use nsString.
|
||||
// UTF8_STRING and CSTRING are also quite similar, and both use nsCString.
|
||||
if (type_tag == nsXPTType::T_ASTRING || type_tag == nsXPTType::T_DOMSTRING)
|
||||
dp->val.p = mCallContext.GetContext()->mScratchStrings.Create();
|
||||
else
|
||||
dp->val.p = mCallContext.GetContext()->mScratchCStrings.Create();
|
||||
|
||||
// Check for OOM, in either case.
|
||||
if (!dp->val.p) {
|
||||
JS_ReportOutOfMemory(mCallContext);
|
||||
if (!XPCConvert::JSData2Native(&dp->val, src, type,
|
||||
¶m_iid, array_count, &err)) {
|
||||
ThrowBadParam(err, i, mCallContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
// We allocated, so we need to deallocate after the method call completes.
|
||||
dp->SetValNeedsCleanup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1962,6 +1749,44 @@ CallMethodHelper::Invoke()
|
|||
return NS_InvokeByIndex(mCallee, mVTableIndex, argc, argv);
|
||||
}
|
||||
|
||||
static void
|
||||
TraceParam(JSTracer* aTrc, void* aVal, const nsXPTType& aType,
|
||||
uint32_t aArrayLen = 0)
|
||||
{
|
||||
if (aType.Tag() == nsXPTType::T_JSVAL) {
|
||||
JS::UnsafeTraceRoot(aTrc, (JS::Value*)aVal,
|
||||
"XPCWrappedNative::CallMethod param");
|
||||
} else if (aType.Tag() == nsXPTType::T_ARRAY && *(void**)aVal) {
|
||||
const nsXPTType& elty = aType.ArrayElementType();
|
||||
if (elty.Tag() != nsXPTType::T_JSVAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aArrayLen; ++i) {
|
||||
TraceParam(aTrc, elty.ElementPtr(aVal, i), elty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallMethodHelper::trace(JSTracer* aTrc)
|
||||
{
|
||||
// We need to note each of our initialized parameters which contain jsvals.
|
||||
for (nsXPTCVariant& param : mDispatchParams) {
|
||||
if (!param.DoesValNeedCleanup()) {
|
||||
MOZ_ASSERT(param.type.Tag() != nsXPTType::T_JSVAL,
|
||||
"JSVals are marked as needing cleanup (even though they don't)");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t arrayLen = 0;
|
||||
if (!GetArraySizeFromParam(param.type, UndefinedHandleValue, &arrayLen))
|
||||
continue;
|
||||
|
||||
TraceParam(aTrc, ¶m.val, param.type, arrayLen);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// interface methods
|
||||
|
||||
|
|
|
@ -332,52 +332,6 @@ MOZ_DEFINE_ENUM(WatchdogTimestampCategory, (
|
|||
|
||||
class AsyncFreeSnowWhite;
|
||||
|
||||
template <class StringType>
|
||||
class ShortLivedStringBuffer
|
||||
{
|
||||
public:
|
||||
StringType* Create()
|
||||
{
|
||||
for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
|
||||
if (!mStrings[i]) {
|
||||
mStrings[i].emplace();
|
||||
return mStrings[i].ptr();
|
||||
}
|
||||
}
|
||||
|
||||
// All our internal string wrappers are used, allocate a new string.
|
||||
return new StringType();
|
||||
}
|
||||
|
||||
void Destroy(StringType* string)
|
||||
{
|
||||
for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
|
||||
if (mStrings[i] && mStrings[i].ptr() == string) {
|
||||
// One of our internal strings is no longer in use, mark
|
||||
// it as such and free its data.
|
||||
mStrings[i].reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We're done with a string that's not one of our internal
|
||||
// strings, delete it.
|
||||
delete string;
|
||||
}
|
||||
|
||||
~ShortLivedStringBuffer()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
|
||||
MOZ_ASSERT(!mStrings[i], "Short lived string still in use");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::Maybe<StringType> mStrings[2];
|
||||
};
|
||||
|
||||
class XPCJSContext final : public mozilla::CycleCollectedJSContext
|
||||
, public mozilla::LinkedListElement<XPCJSContext>
|
||||
{
|
||||
|
@ -470,9 +424,6 @@ public:
|
|||
inline JS::HandleId GetStringID(unsigned index) const;
|
||||
inline const char* GetStringName(unsigned index) const;
|
||||
|
||||
ShortLivedStringBuffer<nsString> mScratchStrings;
|
||||
ShortLivedStringBuffer<nsCString> mScratchCStrings;
|
||||
|
||||
private:
|
||||
XPCJSContext();
|
||||
|
||||
|
@ -1799,31 +1750,19 @@ private:
|
|||
{if (b) mDescriptors[i/32] |= (1 << (i%32));
|
||||
else mDescriptors[i/32] &= ~(1 << (i%32));}
|
||||
|
||||
bool GetArraySizeFromParam(JSContext* cx,
|
||||
const nsXPTMethodInfo* method,
|
||||
const nsXPTParamInfo& param,
|
||||
uint16_t methodIndex,
|
||||
uint8_t paramIndex,
|
||||
bool GetArraySizeFromParam(const nsXPTMethodInfo* method,
|
||||
const nsXPTType& type,
|
||||
nsXPTCMiniVariant* params,
|
||||
uint32_t* result) const;
|
||||
|
||||
bool GetInterfaceTypeFromParam(JSContext* cx,
|
||||
const nsXPTMethodInfo* method,
|
||||
const nsXPTParamInfo& param,
|
||||
uint16_t methodIndex,
|
||||
bool GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
|
||||
const nsXPTType& type,
|
||||
nsXPTCMiniVariant* params,
|
||||
nsID* result) const;
|
||||
|
||||
static void CleanupPointerArray(const nsXPTType& datum_type,
|
||||
uint32_t array_count,
|
||||
void** arrayp);
|
||||
|
||||
static void CleanupPointerTypeObject(const nsXPTType& type,
|
||||
void** pp);
|
||||
|
||||
void CleanupOutparams(JSContext* cx, uint16_t methodIndex, const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* nativeParams, bool inOutOnly, uint8_t n) const;
|
||||
void CleanupOutparams(const nsXPTMethodInfo* info,
|
||||
nsXPTCMiniVariant* nativeParams,
|
||||
bool inOutOnly, uint8_t n) const;
|
||||
|
||||
private:
|
||||
XPCJSRuntime* mRuntime;
|
||||
|
@ -1999,11 +1938,13 @@ public:
|
|||
|
||||
static bool NativeData2JS(JS::MutableHandleValue d,
|
||||
const void* s, const nsXPTType& type,
|
||||
const nsID* iid, nsresult* pErr);
|
||||
const nsID* iid, uint32_t arrlen,
|
||||
nsresult* pErr);
|
||||
|
||||
static bool JSData2Native(void* d, JS::HandleValue s,
|
||||
const nsXPTType& type,
|
||||
const nsID* iid,
|
||||
uint32_t arrlen,
|
||||
nsresult* pErr);
|
||||
|
||||
/**
|
||||
|
@ -2049,7 +1990,7 @@ public:
|
|||
* @param scope the default scope to put on the new JSObjects' parent chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
*/
|
||||
static bool NativeArray2JS(JS::MutableHandleValue d, const void** s,
|
||||
static bool NativeArray2JS(JS::MutableHandleValue d, const void* const* s,
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
uint32_t count, nsresult* pErr);
|
||||
|
||||
|
@ -2063,15 +2004,6 @@ public:
|
|||
const nsXPTType& type,
|
||||
nsresult* pErr);
|
||||
|
||||
static bool NativeStringWithSize2JS(JS::MutableHandleValue d, const void* s,
|
||||
const nsXPTType& type,
|
||||
uint32_t count,
|
||||
nsresult* pErr);
|
||||
|
||||
static bool JSStringWithSize2Native(void* d, JS::HandleValue s,
|
||||
uint32_t count, const nsXPTType& type,
|
||||
nsresult* pErr);
|
||||
|
||||
static nsresult JSValToXPCException(JS::MutableHandleValue s,
|
||||
const char* ifaceName,
|
||||
const char* methodName,
|
||||
|
@ -3109,6 +3041,39 @@ nsresult HasInstance(JSContext* cx, JS::HandleObject objArg, const nsID* iid, bo
|
|||
|
||||
nsIPrincipal* GetObjectPrincipal(JSObject* obj);
|
||||
|
||||
// Attempt to clean up the passed in value pointer. The pointer `value` must be
|
||||
// a pointer to a value described by the type `nsXPTType`.
|
||||
//
|
||||
// This method expects a value of the following types:
|
||||
// TD_PNSIID
|
||||
// value : nsID* (free)
|
||||
// TD_DOMSTRING, TD_ASTRING, TD_CSTRING, TD_UTF8STRING
|
||||
// value : ns[C]String* (truncate)
|
||||
// TD_PSTRING, TD_PWSTRING, TD_PSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS
|
||||
// value : char[16_t]** (free)
|
||||
// TD_INTERFACE_TYPE, TD_INTERFACE_IS_TYPE
|
||||
// value : nsISupports** (release)
|
||||
// TD_ARRAY (NOTE: aArrayLen should be passed)
|
||||
// value : void** (cleanup elements & free)
|
||||
// TD_DOMOBJECT
|
||||
// value : T** (cleanup)
|
||||
// TD_PROMISE
|
||||
// value : dom::Promise** (release)
|
||||
//
|
||||
// Other types are ignored.
|
||||
//
|
||||
// Custom behaviour may be desired in some situations:
|
||||
// - This method Truncate()s nsStrings, it does not free them.
|
||||
// - This method does not unroot JSValues.
|
||||
inline void CleanupValue(const nsXPTType& aType,
|
||||
void* aValue,
|
||||
uint32_t aArrayLen = 0);
|
||||
|
||||
// Out-of-line internals for xpc::CleanupValue. Defined in XPCConvert.cpp.
|
||||
void InnerCleanupValue(const nsXPTType& aType,
|
||||
void* aValue,
|
||||
uint32_t aArrayLen);
|
||||
|
||||
} // namespace xpc
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -87,6 +87,16 @@ VARCACHE_PREF(
|
|||
bool, false
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DOM prefs
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
VARCACHE_PREF(
|
||||
"dom.webcomponents.shadowdom.report_usage",
|
||||
dom_webcomponents_shadowdom_report_usage,
|
||||
bool, false
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Full-screen prefs
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -145,7 +145,7 @@ NS_IMETHODIMP
|
|||
SecretDecoderRing::AsyncEncryptStrings(uint32_t plaintextsCount,
|
||||
const char16_t** plaintexts,
|
||||
JSContext* aCx,
|
||||
nsISupports** aPromise) {
|
||||
Promise** aPromise) {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_ARG(plaintextsCount);
|
||||
NS_ENSURE_ARG_POINTER(plaintexts);
|
||||
|
|
|
@ -33,8 +33,8 @@ interface nsISecretDecoderRing: nsISupports {
|
|||
* @return A promise for the list of encrypted strings, encoded as Base64.
|
||||
*/
|
||||
[implicit_jscontext, must_use]
|
||||
nsISupports asyncEncryptStrings(in unsigned long plaintextsCount,
|
||||
[array, size_is(plaintextsCount)] in wstring plaintexts);
|
||||
Promise asyncEncryptStrings(in unsigned long plaintextsCount,
|
||||
[array, size_is(plaintextsCount)] in wstring plaintexts);
|
||||
|
||||
/**
|
||||
* Decrypt Base64 input.
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_37_RTM
|
||||
6e4b0141df2f
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_36_BRANCH
|
||||
NSS_3_37_BRANCH
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:latest
|
||||
FROM ubuntu:16.04
|
||||
MAINTAINER Tim Taubert <ttaubert@mozilla.com>
|
||||
|
||||
RUN useradd -d /home/worker -s /bin/bash -m worker
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -884,6 +884,45 @@ TEST_P(TlsConnectDatagram12Plus, MissAWindowAndOne) {
|
|||
SendReceive();
|
||||
}
|
||||
|
||||
// This filter replaces the first record it sees with junk application data.
|
||||
class TlsReplaceFirstRecordWithJunk : public TlsRecordFilter {
|
||||
public:
|
||||
TlsReplaceFirstRecordWithJunk(const std::shared_ptr<TlsAgent>& a)
|
||||
: TlsRecordFilter(a), replaced_(false) {}
|
||||
|
||||
protected:
|
||||
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
|
||||
const DataBuffer& record, size_t* offset,
|
||||
DataBuffer* output) override {
|
||||
if (replaced_) {
|
||||
return KEEP;
|
||||
}
|
||||
replaced_ = true;
|
||||
TlsRecordHeader out_header(header.variant(), header.version(),
|
||||
kTlsApplicationDataType,
|
||||
header.sequence_number());
|
||||
|
||||
static const uint8_t junk[] = {1, 2, 3, 4};
|
||||
*offset = out_header.Write(output, *offset, DataBuffer(junk, sizeof(junk)));
|
||||
return CHANGE;
|
||||
}
|
||||
|
||||
private:
|
||||
bool replaced_;
|
||||
};
|
||||
|
||||
// DTLS needs to discard application_data that it receives prior to handshake
|
||||
// completion, not generate an error.
|
||||
TEST_P(TlsConnectDatagram, ReplaceFirstServerRecordWithApplicationData) {
|
||||
MakeTlsFilter<TlsReplaceFirstRecordWithJunk>(server_);
|
||||
Connect();
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectDatagram, ReplaceFirstClientRecordWithApplicationData) {
|
||||
MakeTlsFilter<TlsReplaceFirstRecordWithJunk>(client_);
|
||||
Connect();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Datagram12Plus, TlsConnectDatagram12Plus,
|
||||
TlsConnectTestBase::kTlsV12Plus);
|
||||
INSTANTIATE_TEST_CASE_P(DatagramPre13, TlsConnectDatagramPre13,
|
||||
|
|
|
@ -528,7 +528,9 @@ nssToken_ImportCertificate(
|
|||
*/
|
||||
NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
|
||||
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
|
||||
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
|
||||
if (!rvObject->label && nickname) {
|
||||
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
|
||||
}
|
||||
NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
|
||||
/* reset the mutable attributes on the token */
|
||||
nssCKObject_SetAttributes(rvObject->handle,
|
||||
|
|
|
@ -180,7 +180,7 @@ blake2b_Begin(BLAKE2BContext* ctx, uint8_t outlen, const uint8_t* key,
|
|||
return SECSuccess;
|
||||
|
||||
failure:
|
||||
PORT_Memset(&ctx, 0, sizeof(ctx));
|
||||
PORT_Memset(ctx, 0, sizeof(*ctx));
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.37" _NSS_CUSTOMIZED
|
||||
#define NSS_VERSION "3.38" _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 37
|
||||
#define NSS_VMINOR 38
|
||||
#define NSS_VPATCH 0
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_FALSE
|
||||
#define NSS_BETA PR_TRUE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
#elif defined(XP_UNIX)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(LINUX) && !defined(ANDROID)
|
||||
#include <linux/magic.h>
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#include "utilpars.h"
|
||||
|
||||
#ifdef SQLITE_UNSAFE_THREADS
|
||||
|
@ -1763,6 +1767,8 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
|
|||
PRIntervalTime now = 0;
|
||||
char *env;
|
||||
PRBool enableCache = PR_FALSE;
|
||||
PRBool checkFSType = PR_FALSE;
|
||||
PRBool measureSpeed = PR_FALSE;
|
||||
PRBool create;
|
||||
int flags = inFlags & 0x7;
|
||||
|
||||
|
@ -1923,11 +1929,48 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
|
|||
|
||||
env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
|
||||
|
||||
if (!env || PORT_Strcasecmp(env, "no") == 0) {
|
||||
enableCache = PR_FALSE;
|
||||
/* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default,
|
||||
* which is the expected behavior for NSS_SDB_USE_CACHE="no".
|
||||
* We don't need to check for "no" here. */
|
||||
if (!env) {
|
||||
/* By default, with no variable set, we avoid expensive measuring for
|
||||
* most FS types. We start with inexpensive FS type checking, and
|
||||
* might perform measuring for some types. */
|
||||
checkFSType = PR_TRUE;
|
||||
} else if (PORT_Strcasecmp(env, "yes") == 0) {
|
||||
enableCache = PR_TRUE;
|
||||
} else {
|
||||
} else if (PORT_Strcasecmp(env, "no") != 0) { /* not "no" => "auto" */
|
||||
measureSpeed = PR_TRUE;
|
||||
}
|
||||
|
||||
if (checkFSType) {
|
||||
#if defined(LINUX) && !defined(ANDROID)
|
||||
struct statfs statfs_s;
|
||||
if (statfs(dbname, &statfs_s) == 0) {
|
||||
switch (statfs_s.f_type) {
|
||||
case SMB_SUPER_MAGIC:
|
||||
case 0xff534d42: /* CIFS_MAGIC_NUMBER */
|
||||
case NFS_SUPER_MAGIC:
|
||||
/* We assume these are slow. */
|
||||
enableCache = PR_TRUE;
|
||||
break;
|
||||
case CODA_SUPER_MAGIC:
|
||||
case 0x65735546: /* FUSE_SUPER_MAGIC */
|
||||
case NCP_SUPER_MAGIC:
|
||||
/* It's uncertain if this FS is fast or slow.
|
||||
* It seems reasonable to perform slow measuring for users
|
||||
* with questionable FS speed. */
|
||||
measureSpeed = PR_TRUE;
|
||||
break;
|
||||
case AFS_SUPER_MAGIC: /* Already implements caching. */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (measureSpeed) {
|
||||
char *tempDir = NULL;
|
||||
PRUint32 tempOps = 0;
|
||||
/*
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.37" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.38" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 37
|
||||
#define SOFTOKEN_VMINOR 38
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
|
||||
#endif /* _SOFTKVER_H_ */
|
||||
|
|
|
@ -12166,6 +12166,14 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
|
|||
* processed twice. */
|
||||
plaintext->len = 0;
|
||||
|
||||
/* We're waiting for another ClientHello, which will appear unencrypted.
|
||||
* Use the content type to tell whether this should be discarded. */
|
||||
if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr &&
|
||||
cText->hdr[0] == content_application_data) {
|
||||
PORT_Assert(ss->ssl3.hs.ws == wait_client_hello);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
ssl_GetSpecReadLock(ss); /******************************************/
|
||||
spec = ssl3_GetCipherSpec(ss, cText);
|
||||
if (!spec) {
|
||||
|
@ -12196,18 +12204,6 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* We're waiting for another ClientHello, which will appear unencrypted.
|
||||
* Use the content type to tell whether this is should be discarded.
|
||||
*
|
||||
* XXX If we decide to remove the content type from encrypted records, this
|
||||
* will become much more difficult to manage. */
|
||||
if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr &&
|
||||
cText->hdr[0] == content_application_data) {
|
||||
ssl_ReleaseSpecReadLock(ss); /*****************************/
|
||||
PORT_Assert(ss->ssl3.hs.ws == wait_client_hello);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
if (plaintext->space < MAX_FRAGMENT_LENGTH) {
|
||||
rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
|
||||
if (rv != SECSuccess) {
|
||||
|
@ -12220,23 +12216,33 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef UNSAFE_FUZZER_MODE
|
||||
/* Most record types aside from protected TLS 1.3 records carry the content
|
||||
* type in the first octet. TLS 1.3 will override this value later. */
|
||||
rType = cText->hdr[0];
|
||||
rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len,
|
||||
plaintext->space, cText->buf->buf, cText->buf->len);
|
||||
#else
|
||||
/* IMPORTANT: Unprotect functions MUST NOT send alerts
|
||||
* because we still hold the spec read lock. Instead, if they
|
||||
* return SECFailure, they set *alert to the alert to be sent. */
|
||||
if (spec->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
|
||||
spec->cipherDef->calg == ssl_calg_null) {
|
||||
/* Unencrypted TLS 1.3 records use the pre-TLS 1.3 format. */
|
||||
rType = cText->hdr[0];
|
||||
rv = ssl3_UnprotectRecord(ss, spec, cText, plaintext, &alert);
|
||||
/* Encrypted application data records could arrive before the handshake
|
||||
* completes in DTLS 1.3. These can look like valid TLS 1.2 application_data
|
||||
* records in epoch 0, which is never valid. Pretend they didn't decrypt. */
|
||||
if (spec->epoch == 0 && rType == content_application_data) {
|
||||
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
|
||||
alert = unexpected_message;
|
||||
rv = SECFailure;
|
||||
} else {
|
||||
rv = tls13_UnprotectRecord(ss, spec, cText, plaintext, &rType, &alert);
|
||||
}
|
||||
#ifdef UNSAFE_FUZZER_MODE
|
||||
rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len,
|
||||
plaintext->space, cText->buf->buf, cText->buf->len);
|
||||
#else
|
||||
/* IMPORTANT: Unprotect functions MUST NOT send alerts
|
||||
* because we still hold the spec read lock. Instead, if they
|
||||
* return SECFailure, they set *alert to the alert to be sent. */
|
||||
if (spec->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
|
||||
spec->epoch == 0) {
|
||||
rv = ssl3_UnprotectRecord(ss, spec, cText, plaintext, &alert);
|
||||
} else {
|
||||
rv = tls13_UnprotectRecord(ss, spec, cText, plaintext, &rType,
|
||||
&alert);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
ssl_ReleaseSpecReadLock(ss); /***************************/
|
||||
|
@ -12246,10 +12252,10 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
|
|||
/* Ensure that we don't process this data again. */
|
||||
plaintext->len = 0;
|
||||
|
||||
/* Ignore a CCS if the alternative handshake is negotiated. Note that
|
||||
* this will fail if the server fails to negotiate the alternative
|
||||
* handshake type in a 0-RTT session that is resumed from a session that
|
||||
* did negotiate it. We don't care about that corner case right now. */
|
||||
/* Ignore a CCS if compatibility mode is negotiated. Note that this
|
||||
* will fail if the server fails to negotiate compatibility mode in a
|
||||
* 0-RTT session that is resumed from a session that did negotiate it.
|
||||
* We don't care about that corner case right now. */
|
||||
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
|
||||
cText->hdr[0] == content_change_cipher_spec &&
|
||||
ss->ssl3.hs.ws != idle_handshake &&
|
||||
|
@ -12258,19 +12264,20 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
|
|||
/* Ignore the CCS. */
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
if (IS_DTLS(ss) ||
|
||||
(ss->sec.isServer &&
|
||||
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
|
||||
/* Silently drop the packet */
|
||||
return SECSuccess;
|
||||
} else {
|
||||
int errCode = PORT_GetError();
|
||||
SSL3_SendAlert(ss, alert_fatal, alert);
|
||||
/* Reset the error code in case SSL3_SendAlert called
|
||||
* PORT_SetError(). */
|
||||
PORT_SetError(errCode);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
int errCode = PORT_GetError();
|
||||
SSL3_SendAlert(ss, alert_fatal, alert);
|
||||
/* Reset the error code in case SSL3_SendAlert called
|
||||
* PORT_SetError(). */
|
||||
PORT_SetError(errCode);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* SECSuccess */
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.37"
|
||||
#define NSSUTIL_VERSION "3.38 Beta"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 37
|
||||
#define NSSUTIL_VMINOR 38
|
||||
#define NSSUTIL_VPATCH 0
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
|
|
@ -1060,6 +1060,25 @@ cert_extended_ssl()
|
|||
# -d "${PROFILEDIR}" -i "${CLIENT_CADIR}/clientCA-ecmixed.ca.cert" \
|
||||
# 2>&1
|
||||
|
||||
# Check that a repeated import with a different nickname doesn't change the
|
||||
# nickname of the existing cert (bug 1458518).
|
||||
# We want to search for the results using grep, to avoid subset matches,
|
||||
# we'll use one of the longer nicknames for testing.
|
||||
# (Because "grep -w hostname" matches "grep -w hostname-dsamixed")
|
||||
MYDBPASS="-d ${PROFILEDIR} -f ${R_PWFILE}"
|
||||
TESTNAME="Ensure there's exactly one match for ${CERTNAME}-dsamixed"
|
||||
cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}"
|
||||
|
||||
CU_ACTION="Repeated import of $CERTNAME's mixed DSA Cert with different nickname"
|
||||
certu -A -n "${CERTNAME}-repeated-dsamixed" -t "u,u,u" -d "${PROFILEDIR}" \
|
||||
-f "${R_PWFILE}" -i "${CERTNAME}-dsamixed.cert" 2>&1
|
||||
|
||||
TESTNAME="Ensure there's still exactly one match for ${CERTNAME}-dsamixed"
|
||||
cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}"
|
||||
|
||||
TESTNAME="Ensure there's zero matches for ${CERTNAME}-repeated-dsamixed"
|
||||
cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-repeated-dsamixed" 0 0 "${TESTNAME}"
|
||||
|
||||
echo "Importing all the server's own CA chain into the servers DB"
|
||||
for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ;
|
||||
do
|
||||
|
@ -1532,6 +1551,37 @@ cert_make_with_param()
|
|||
return 0
|
||||
}
|
||||
|
||||
cert_check_nickname_exists()
|
||||
{
|
||||
MYDIRPASS="$1"
|
||||
MYCERTNAME="$2"
|
||||
EXPECT="$3"
|
||||
EXPECTCOUNT="$4"
|
||||
MYTESTNAME="$5"
|
||||
|
||||
echo certutil ${MYDIRPASS} -L
|
||||
${BINDIR}/certutil ${MYDIRPASS} -L
|
||||
|
||||
RET=$?
|
||||
if [ "${RET}" -ne "${EXPECT}" ]; then
|
||||
CERTFAILED=1
|
||||
html_failed "${MYTESTNAME} - list"
|
||||
cert_log "ERROR: ${MYTESTNAME} - list"
|
||||
return 1
|
||||
fi
|
||||
|
||||
LISTCOUNT=`${BINDIR}/certutil ${MYDIRPASS} -L | grep -wc ${MYCERTNAME}`
|
||||
if [ "${LISTCOUNT}" -ne "${EXPECTCOUNT}" ]; then
|
||||
CERTFAILED=1
|
||||
html_failed "${MYTESTNAME} - list and count"
|
||||
cert_log "ERROR: ${MYTESTNAME} - list and count failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
html_passed "${MYTESTNAME}"
|
||||
return 0
|
||||
}
|
||||
|
||||
cert_list_and_count_dns()
|
||||
{
|
||||
DIRPASS="$1"
|
||||
|
|
|
@ -42,6 +42,7 @@ xpcshell:
|
|||
linux32/debug: 12
|
||||
linux64/debug: 10
|
||||
android-4.2-x86/opt: 6
|
||||
android-4.3-arm7-api-16/debug: 12
|
||||
macosx.*: 1
|
||||
windows.*: 1
|
||||
windows10-64-ccov/debug: 8
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[child-navigates-parent-blocked.html]
|
||||
disabled: if not debug && (os == "linux") https://bugzilla.mozilla.org/show_bug.cgi?id=1450864
|
||||
[Test that the child can't navigate the parent because the relevant policy belongs to the navigation initiator (in this case the child)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
[Stringification of document]
|
||||
expected: FAIL
|
||||
|
||||
[ProcessingInstruction interface: attribute sheet]
|
||||
expected: FAIL
|
||||
|
||||
[CSSRule interface: constant MARGIN_RULE on interface object]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ interface nsICrashService : nsISupports
|
|||
* @param id
|
||||
* Crash ID. Likely a UUID.
|
||||
*
|
||||
* @return {Promise} A promise that resolves after the crash has been stored
|
||||
* @return A promise that resolves after the crash has been stored
|
||||
*/
|
||||
nsISupports addCrash(in long processType, in long crashType, in AString id);
|
||||
Promise addCrash(in long processType, in long crashType, in AString id);
|
||||
|
||||
const long PROCESS_TYPE_MAIN = 0;
|
||||
const long PROCESS_TYPE_CONTENT = 1;
|
||||
|
|
|
@ -976,7 +976,7 @@ public:
|
|||
#endif // MOZ_GECKO_PROFILER
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetLoadedModules(JSContext *cx, nsISupports** aPromise)
|
||||
TelemetryImpl::GetLoadedModules(JSContext *cx, Promise** aPromise)
|
||||
{
|
||||
#if defined(MOZ_GECKO_PROFILER)
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx));
|
||||
|
|
|
@ -198,7 +198,7 @@ interface nsITelemetry : nsISupports
|
|||
* @throws NS_ERROR_NOT_IMPLEMENTED if the Gecko profiler is not enabled.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
nsISupports getLoadedModules();
|
||||
Promise getLoadedModules();
|
||||
|
||||
/*
|
||||
* An object with two fields: memoryMap and stacks.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
/* import-globals-from ../../../content/contentAreaUtils.js */
|
||||
/* globals XMLStylesheetProcessingInstruction */
|
||||
/* globals ProcessingInstruction */
|
||||
/* exported UPDATES_RELEASENOTES_TRANSFORMFILE, XMLURI_PARSE_ERROR, loadView, gBrowser */
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/DeferredTask.jsm");
|
||||
|
@ -109,7 +109,7 @@ Object.defineProperty(this, "gIsInitializing", {
|
|||
function initialize(event) {
|
||||
// XXXbz this listener gets _all_ load events for all nodes in the
|
||||
// document... but relies on not being called "too early".
|
||||
if (event.target instanceof XMLStylesheetProcessingInstruction) {
|
||||
if (event.target instanceof ProcessingInstruction) {
|
||||
return;
|
||||
}
|
||||
document.removeEventListener("load", initialize, true);
|
||||
|
|
|
@ -56,17 +56,17 @@ interface nsIProfiler : nsISupports
|
|||
jsval getProfileData([optional] in double aSinceTime);
|
||||
|
||||
[implicit_jscontext]
|
||||
nsISupports getProfileDataAsync([optional] in double aSinceTime);
|
||||
Promise getProfileDataAsync([optional] in double aSinceTime);
|
||||
|
||||
[implicit_jscontext]
|
||||
nsISupports getProfileDataAsArrayBuffer([optional] in double aSinceTime);
|
||||
Promise getProfileDataAsArrayBuffer([optional] in double aSinceTime);
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves once the file has been written.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
nsISupports dumpProfileToFileAsync(in ACString aFilename,
|
||||
[optional] in double aSinceTime);
|
||||
Promise dumpProfileToFileAsync(in ACString aFilename,
|
||||
[optional] in double aSinceTime);
|
||||
|
||||
boolean IsActive();
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ nsProfiler::GetProfileData(double aSinceTime, JSContext* aCx,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetProfileDataAsync(double aSinceTime, JSContext* aCx,
|
||||
nsISupports** aPromise)
|
||||
Promise** aPromise)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -290,7 +290,7 @@ nsProfiler::GetProfileDataAsync(double aSinceTime, JSContext* aCx,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetProfileDataAsArrayBuffer(double aSinceTime, JSContext* aCx,
|
||||
nsISupports** aPromise)
|
||||
Promise** aPromise)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -347,7 +347,7 @@ nsProfiler::GetProfileDataAsArrayBuffer(double aSinceTime, JSContext* aCx,
|
|||
NS_IMETHODIMP
|
||||
nsProfiler::DumpProfileToFileAsync(const nsACString& aFilename,
|
||||
double aSinceTime, JSContext* aCx,
|
||||
nsISupports** aPromise)
|
||||
Promise** aPromise)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
|
|
@ -17,7 +17,16 @@ typedef int64_t PRTime;
|
|||
*/
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
/*
|
||||
/*
|
||||
* Forward declaration of mozilla::dom::Promise
|
||||
*/
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Promise;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/*
|
||||
* Start commenting out the C++ versions of the below in the output header
|
||||
*/
|
||||
#if 0
|
||||
|
@ -88,6 +97,8 @@ typedef unsigned long size_t;
|
|||
[ref, jsval] native jsval(jsval);
|
||||
native jsid(jsid);
|
||||
|
||||
[ptr, promise] native Promise(ignored);
|
||||
|
||||
%{C++
|
||||
/*
|
||||
* End commenting out the C++ versions of the above in the output header
|
||||
|
|
|
@ -53,8 +53,6 @@
|
|||
#include "nsThreadManager.h"
|
||||
#include "nsThreadPool.h"
|
||||
|
||||
#include "xptinfo.h"
|
||||
|
||||
#include "nsTimerImpl.h"
|
||||
#include "TimerThread.h"
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "nscore.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "xptcall.h"
|
||||
|
||||
/**
|
||||
* During this shutdown notification all threads which run XPCOM code must
|
||||
|
|
|
@ -178,6 +178,7 @@ jsvalue_include = """
|
|||
"""
|
||||
|
||||
infallible_includes = """
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
"""
|
||||
|
@ -306,7 +307,7 @@ iface_forward_safe = """
|
|||
/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
|
||||
#define NS_FORWARD_SAFE_%(macroname)s(_to) """
|
||||
|
||||
attr_infallible_tmpl = """\
|
||||
attr_builtin_infallible_tmpl = """\
|
||||
inline %(realtype)s%(nativename)s(%(args)s)
|
||||
{
|
||||
%(realtype)sresult;
|
||||
|
@ -316,6 +317,19 @@ attr_infallible_tmpl = """\
|
|||
}
|
||||
"""
|
||||
|
||||
# NOTE: We don't use RefPtr::forget here because we don't want to need the
|
||||
# definition of %(realtype)s in scope, which we would need for the
|
||||
# AddRef/Release calls.
|
||||
attr_refcnt_infallible_tmpl = """\
|
||||
inline already_AddRefed<%(realtype)s>%(nativename)s(%(args)s)
|
||||
{
|
||||
%(realtype)s* result = nullptr;
|
||||
mozilla::DebugOnly<nsresult> rv = %(nativename)s(%(argnames)s&result);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return already_AddRefed<%(realtype)s>(result);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def write_interface(iface, fd):
|
||||
if iface.namemap is None:
|
||||
|
@ -363,11 +377,18 @@ def write_interface(iface, fd):
|
|||
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, True))
|
||||
if a.infallible:
|
||||
fd.write(attr_infallible_tmpl %
|
||||
{'realtype': a.realtype.nativeType('in'),
|
||||
'nativename': attributeNativeName(a, getter=True),
|
||||
'args': '' if not a.implicit_jscontext else 'JSContext* cx',
|
||||
'argnames': '' if not a.implicit_jscontext else 'cx, '})
|
||||
realtype = a.realtype.nativeType('in')
|
||||
tmpl = attr_builtin_infallible_tmpl
|
||||
|
||||
if a.realtype.kind != 'builtin':
|
||||
assert realtype.endswith(' *'), "bad infallible type"
|
||||
tmpl = attr_refcnt_infallible_tmpl
|
||||
realtype = realtype[:-2] # strip trailing pointer
|
||||
|
||||
fd.write(tmpl % {'realtype': realtype,
|
||||
'nativename': attributeNativeName(a, getter=True),
|
||||
'args': '' if not a.implicit_jscontext else 'JSContext* cx',
|
||||
'argnames': '' if not a.implicit_jscontext else 'cx, '})
|
||||
|
||||
if not a.readonly:
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, False))
|
||||
|
|
|
@ -45,6 +45,7 @@ TypeMap = {
|
|||
'utf8string': 'TD_UTF8STRING',
|
||||
'cstring': 'TD_CSTRING',
|
||||
'jsval': 'TD_JSVAL',
|
||||
'promise': 'TD_PROMISE',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -245,7 +245,8 @@ def attrAsWrapper(iface, m, getter):
|
|||
|
||||
name = attributeParamName(m)
|
||||
|
||||
if getter and m.infallible:
|
||||
if getter and m.infallible and m.realtype.kind == 'builtin':
|
||||
# NOTE: We don't support non-builtin infallible getters in Rust code.
|
||||
return infallible_impl_tmpl % {
|
||||
'name': attributeNativeName(m, getter),
|
||||
'realtype': m.realtype.rustType('in'),
|
||||
|
|
|
@ -455,8 +455,9 @@ class Native(object):
|
|||
'utf8string': 'nsACString',
|
||||
'cstring': 'nsACString',
|
||||
'astring': 'nsAString',
|
||||
'jsval': 'JS::Value'
|
||||
}
|
||||
'jsval': 'JS::Value',
|
||||
'promise': '::mozilla::dom::Promise',
|
||||
}
|
||||
|
||||
# Mappings from C++ native name types to rust native names. Types which
|
||||
# aren't listed here are incompatible with rust code.
|
||||
|
@ -505,6 +506,9 @@ class Native(object):
|
|||
if self.specialtype is None:
|
||||
return False
|
||||
|
||||
if self.specialtype == 'promise':
|
||||
return self.modifier == 'ptr'
|
||||
|
||||
if self.specialtype == 'nsid':
|
||||
return self.modifier is not None
|
||||
|
||||
|
@ -522,7 +526,7 @@ class Native(object):
|
|||
raise IDLError("[shared] only applies to out parameters.")
|
||||
const = True
|
||||
|
||||
if self.specialtype is not None and calltype == 'in':
|
||||
if self.specialtype not in [None, 'promise'] and calltype == 'in':
|
||||
const = True
|
||||
|
||||
if self.specialtype == 'jsval':
|
||||
|
@ -936,8 +940,8 @@ class Attribute(object):
|
|||
getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
|
||||
raise IDLError("'Undefined' attribute can only be used on DOMString",
|
||||
self.location)
|
||||
if self.infallible and not self.realtype.kind == 'builtin':
|
||||
raise IDLError('[infallible] only works on builtin types '
|
||||
if self.infallible and not self.realtype.kind in ['builtin', 'interface', 'forward', 'webidl']:
|
||||
raise IDLError('[infallible] only works on interfaces, domobjects, and builtin types '
|
||||
'(numbers, booleans, and raw char types)',
|
||||
self.location)
|
||||
if self.infallible and not iface.attributes.builtinclass:
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
struct nsXPTCMiniVariant
|
||||
{
|
||||
union U
|
||||
// No ctors or dtors so that we can use arrays of these on the stack
|
||||
// with no penalty.
|
||||
union Union
|
||||
{
|
||||
int8_t i8;
|
||||
int16_t i16;
|
||||
|
@ -33,26 +35,47 @@ struct nsXPTCMiniVariant
|
|||
char c;
|
||||
char16_t wc;
|
||||
void* p;
|
||||
};
|
||||
|
||||
// Types below here are unknown to the assembly implementations, and
|
||||
// therefore _must_ be passed with indirect semantics. We put them in
|
||||
// the union here for type safety, so that we can avoid void* tricks.
|
||||
JS::Value j;
|
||||
|
||||
// |j| has a non-trivial constructor and therefore MUST be
|
||||
// placement-new'd into existence.
|
||||
MOZ_PUSH_DISABLE_NONTRIVIAL_UNION_WARNINGS
|
||||
U() {}
|
||||
MOZ_POP_DISABLE_NONTRIVIAL_UNION_WARNINGS
|
||||
} val;
|
||||
Union val;
|
||||
};
|
||||
|
||||
struct nsXPTCVariant : public nsXPTCMiniVariant
|
||||
{
|
||||
// No ctors or dtors so that we can use arrays of these on the stack
|
||||
// with no penalty.
|
||||
static_assert(offsetof(nsXPTCMiniVariant, val) == 0,
|
||||
"nsXPTCMiniVariant must be a thin wrapper");
|
||||
|
||||
struct nsXPTCVariant
|
||||
{
|
||||
// No ctors or dtors so that we can use arrays of these on the stack with no
|
||||
// penalty.
|
||||
union ExtendedVal
|
||||
{
|
||||
// ExtendedVal is an extension on nsXPTCMiniVariant. It contains types
|
||||
// unknown to the assembly implementations which must be passed by indirect
|
||||
// semantics.
|
||||
//
|
||||
// nsXPTCVariant contains enough space to store ExtendedVal inline, which
|
||||
// can be used to store these types when IsIndirect() is true.
|
||||
nsXPTCMiniVariant mini;
|
||||
|
||||
nsCString nscstr;
|
||||
nsString nsstr;
|
||||
JS::Value jsval;
|
||||
|
||||
// This type contains non-standard-layout types, so needs an explicit
|
||||
// Ctor/Dtor - we'll just delete them.
|
||||
ExtendedVal() = delete;
|
||||
~ExtendedVal() = delete;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
// The `val` field from nsXPTCMiniVariant.
|
||||
nsXPTCMiniVariant::Union val;
|
||||
|
||||
// Storage for any extended variants.
|
||||
ExtendedVal ext;
|
||||
};
|
||||
|
||||
// inherits 'val' here
|
||||
void* ptr;
|
||||
nsXPTType type;
|
||||
uint8_t flags;
|
||||
|
@ -98,53 +121,23 @@ struct nsXPTCVariant : public nsXPTCMiniVariant
|
|||
// Internal use only. Use IsIndirect() instead.
|
||||
bool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);}
|
||||
|
||||
void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, uint8_t f)
|
||||
{
|
||||
type = t;
|
||||
flags = f;
|
||||
|
||||
if(f & PTR_IS_DATA)
|
||||
{
|
||||
ptr = mv.val.p;
|
||||
val.p = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = nullptr;
|
||||
val.p = nullptr; // make sure 'val.p' is always initialized
|
||||
switch(t.TagPart()) {
|
||||
case nsXPTType::T_I8: val.i8 = mv.val.i8; break;
|
||||
case nsXPTType::T_I16: val.i16 = mv.val.i16; break;
|
||||
case nsXPTType::T_I32: val.i32 = mv.val.i32; break;
|
||||
case nsXPTType::T_I64: val.i64 = mv.val.i64; break;
|
||||
case nsXPTType::T_U8: val.u8 = mv.val.u8; break;
|
||||
case nsXPTType::T_U16: val.u16 = mv.val.u16; break;
|
||||
case nsXPTType::T_U32: val.u32 = mv.val.u32; break;
|
||||
case nsXPTType::T_U64: val.u64 = mv.val.u64; break;
|
||||
case nsXPTType::T_FLOAT: val.f = mv.val.f; break;
|
||||
case nsXPTType::T_DOUBLE: val.d = mv.val.d; break;
|
||||
case nsXPTType::T_BOOL: val.b = mv.val.b; break;
|
||||
case nsXPTType::T_CHAR: val.c = mv.val.c; break;
|
||||
case nsXPTType::T_WCHAR: val.wc = mv.val.wc; break;
|
||||
case nsXPTType::T_VOID: /* fall through */
|
||||
case nsXPTType::T_IID: /* fall through */
|
||||
case nsXPTType::T_DOMSTRING: /* fall through */
|
||||
case nsXPTType::T_CHAR_STR: /* fall through */
|
||||
case nsXPTType::T_WCHAR_STR: /* fall through */
|
||||
case nsXPTType::T_INTERFACE: /* fall through */
|
||||
case nsXPTType::T_INTERFACE_IS: /* fall through */
|
||||
case nsXPTType::T_DOMOBJECT: /* fall through */
|
||||
case nsXPTType::T_ARRAY: /* fall through */
|
||||
case nsXPTType::T_PSTRING_SIZE_IS: /* fall through */
|
||||
case nsXPTType::T_PWSTRING_SIZE_IS: /* fall through */
|
||||
case nsXPTType::T_UTF8STRING: /* fall through */
|
||||
case nsXPTType::T_CSTRING: /* fall through */
|
||||
default: val.p = mv.val.p; break;
|
||||
}
|
||||
}
|
||||
// Implicitly convert to nsXPTCMiniVariant.
|
||||
operator nsXPTCMiniVariant&() {
|
||||
return *(nsXPTCMiniVariant*) &val;
|
||||
}
|
||||
operator const nsXPTCMiniVariant&() const {
|
||||
return *(const nsXPTCMiniVariant*) &val;
|
||||
}
|
||||
|
||||
// As this type contains an anonymous union, we need to provide explicit
|
||||
// constructors & destructors.
|
||||
nsXPTCVariant() { }
|
||||
~nsXPTCVariant() { }
|
||||
};
|
||||
|
||||
static_assert(offsetof(nsXPTCVariant, val) == offsetof(nsXPTCVariant, ext),
|
||||
"nsXPTCVariant::{ext,val} must have matching offsets");
|
||||
|
||||
class nsIXPTCProxy : public nsISupports
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -150,6 +150,33 @@ def splitint(i):
|
|||
return (i >> 8, i & 0xff)
|
||||
|
||||
|
||||
# Occasionally in xpconnect, we need to fabricate types to pass into the
|
||||
# conversion methods. In some cases, these types need to be arrays, which hold
|
||||
# indicies into the extra types array.
|
||||
#
|
||||
# These are some types which should have known indexes into the extra types
|
||||
# array.
|
||||
utility_types = [
|
||||
{ 'tag': 'TD_INT8' },
|
||||
{ 'tag': 'TD_UINT8' },
|
||||
{ 'tag': 'TD_INT16' },
|
||||
{ 'tag': 'TD_UINT16' },
|
||||
{ 'tag': 'TD_INT32' },
|
||||
{ 'tag': 'TD_UINT32' },
|
||||
{ 'tag': 'TD_INT64' },
|
||||
{ 'tag': 'TD_UINT64' },
|
||||
{ 'tag': 'TD_FLOAT' },
|
||||
{ 'tag': 'TD_DOUBLE' },
|
||||
{ 'tag': 'TD_BOOL' },
|
||||
{ 'tag': 'TD_CHAR' },
|
||||
{ 'tag': 'TD_WCHAR' },
|
||||
{ 'tag': 'TD_PNSIID' },
|
||||
{ 'tag': 'TD_PSTRING' },
|
||||
{ 'tag': 'TD_PWSTRING' },
|
||||
{ 'tag': 'TD_INTERFACE_IS_TYPE', 'iid_is': 0 },
|
||||
]
|
||||
|
||||
|
||||
# Core of the code generator. Takes a list of raw JSON XPT interfaces, and
|
||||
# writes out a file containing the necessary static declarations into fd.
|
||||
def link_to_cpp(interfaces, fd):
|
||||
|
@ -220,6 +247,14 @@ def link_to_cpp(interfaces, fd):
|
|||
strings[s] = 0
|
||||
return strings[s]
|
||||
|
||||
def lower_extra_type(type):
|
||||
key = describe_type(type)
|
||||
idx = type_cache.get(key)
|
||||
if idx is None:
|
||||
idx = type_cache[key] = len(types)
|
||||
types.append(lower_type(type))
|
||||
return idx
|
||||
|
||||
def describe_type(type): # Create the type's documentation comment.
|
||||
tag = type['tag'][3:].lower()
|
||||
if tag == 'array':
|
||||
|
@ -239,13 +274,7 @@ def link_to_cpp(interfaces, fd):
|
|||
|
||||
if tag == 'TD_ARRAY':
|
||||
d1 = type['size_is']
|
||||
|
||||
# index of element in extra types list
|
||||
key = describe_type(type['element'])
|
||||
d2 = type_cache.get(key)
|
||||
if d2 is None:
|
||||
d2 = type_cache[key] = len(types)
|
||||
types.append(lower_type(type['element']))
|
||||
d2 = lower_extra_type(type['element'])
|
||||
|
||||
elif tag == 'TD_INTERFACE_TYPE':
|
||||
d1, d2 = splitint(interface_idx(type['name']))
|
||||
|
@ -411,6 +440,12 @@ def link_to_cpp(interfaces, fd):
|
|||
for const in iface['consts']:
|
||||
lower_const(const, iface['name'])
|
||||
|
||||
# Lower the types which have fixed indexes first, and check that the indexes
|
||||
# seem correct.
|
||||
for expected, ty in enumerate(utility_types):
|
||||
got = lower_extra_type(ty)
|
||||
assert got == expected, "Wrong index when lowering"
|
||||
|
||||
# Lower interfaces in the order of the IID phf's values lookup.
|
||||
for iface in iid_phf.values:
|
||||
lower_iface(iface)
|
||||
|
@ -486,8 +521,14 @@ namespace detail {
|
|||
phfarr("sPHF_Names", "uint32_t", name_phf.intermediate)
|
||||
phfarr("sPHF_NamesIdxs", "uint16_t", name_phf.values)
|
||||
|
||||
# Generate some checks that the indexes for the utility types match the
|
||||
# declared ones in xptinfo.h
|
||||
for idx, ty in enumerate(utility_types):
|
||||
fd.write("static_assert(%d == (uint8_t)nsXPTType::Idx::%s, \"Bad idx\");\n" %
|
||||
(idx, ty['tag'][3:]))
|
||||
|
||||
# The footer contains some checks re: the size of the generated arrays.
|
||||
fd.write("""\
|
||||
fd.write("""
|
||||
const uint16_t sInterfacesSize = mozilla::ArrayLength(sInterfaces);
|
||||
static_assert(sInterfacesSize == mozilla::ArrayLength(sPHF_NamesIdxs),
|
||||
"sPHF_NamesIdxs must have same size as sInterfaces");
|
||||
|
|
|
@ -261,70 +261,6 @@ nsXPTInterfaceInfo::GetConstant(uint16_t aIndex,
|
|||
return *aName ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::GetTypeForParam(uint16_t /* UNUSED aMethodIndex */,
|
||||
const nsXPTParamInfo* aParam,
|
||||
uint16_t aDimension,
|
||||
nsXPTType* aRetval) const
|
||||
{
|
||||
const nsXPTType* type = &aParam->Type();
|
||||
for (uint16_t i = 0; i < aDimension; ++i) {
|
||||
if (type->Tag() != TD_ARRAY) {
|
||||
NS_ERROR("bad dimension");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
type = &type->ArrayElementType();
|
||||
}
|
||||
|
||||
*aRetval = *type; // NOTE: This copies the type, which is fine I guess?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::GetSizeIsArgNumberForParam(uint16_t /* UNUSED aMethodIndex */,
|
||||
const nsXPTParamInfo* aParam,
|
||||
uint16_t aDimension,
|
||||
uint8_t* aRetval) const
|
||||
{
|
||||
const nsXPTType* type = &aParam->Type();
|
||||
for (uint16_t i = 0; i < aDimension; ++i) {
|
||||
if (type->Tag() != TD_ARRAY) {
|
||||
NS_ERROR("bad dimension");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
type = &type->ArrayElementType();
|
||||
}
|
||||
|
||||
if (type->Tag() != TD_ARRAY &&
|
||||
type->Tag() != TD_PSTRING_SIZE_IS &&
|
||||
type->Tag() != TD_PWSTRING_SIZE_IS) {
|
||||
NS_ERROR("not a size_is");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aRetval = type->ArgNum();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16_t /* UNUSED aMethodIndex */,
|
||||
const nsXPTParamInfo* aParam,
|
||||
uint8_t* aRetval) const
|
||||
{
|
||||
const nsXPTType* type = &aParam->Type();
|
||||
while (type->Tag() == TD_ARRAY) {
|
||||
type = &type->ArrayElementType();
|
||||
}
|
||||
|
||||
if (type->Tag() != TD_INTERFACE_IS_TYPE) {
|
||||
NS_ERROR("not an iid_is");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aRetval = type->ArgNum();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::IsIID(const nsIID* aIID, bool* aIs) const
|
||||
{
|
||||
|
@ -360,26 +296,6 @@ nsXPTInterfaceInfo::HasAncestor(const nsIID* aIID, bool* aRetval) const
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::GetIIDForParamNoAlloc(uint16_t aMethodIndex,
|
||||
const nsXPTParamInfo* aParam,
|
||||
nsIID* aIID) const
|
||||
{
|
||||
const nsXPTType* type = &aParam->Type();
|
||||
while (type->Tag() == TD_ARRAY) {
|
||||
type = &type->ArrayElementType();
|
||||
}
|
||||
|
||||
if (type->Tag() == TD_INTERFACE_TYPE) {
|
||||
const nsXPTInterfaceInfo* info = type->GetInterface();
|
||||
if (info) {
|
||||
*aIID = info->IID();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPTInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetval) const
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsID.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "js/Value.h"
|
||||
#include "nsString.h"
|
||||
|
||||
// Forward Declarations
|
||||
namespace mozilla {
|
||||
|
@ -106,23 +107,11 @@ struct nsXPTInterfaceInfo
|
|||
nsresult GetConstant(uint16_t aIndex,
|
||||
JS::MutableHandleValue constant,
|
||||
char** aName) const;
|
||||
nsresult GetTypeForParam(uint16_t aMethodIndex, const nsXPTParamInfo* aParam,
|
||||
uint16_t aDimension, nsXPTType* aRetval) const;
|
||||
nsresult GetSizeIsArgNumberForParam(uint16_t aMethodIndex,
|
||||
const nsXPTParamInfo* aParam,
|
||||
uint16_t aDimension,
|
||||
uint8_t* aRetval) const;
|
||||
nsresult GetInterfaceIsArgNumberForParam(uint16_t aMethodIndex,
|
||||
const nsXPTParamInfo* aParam,
|
||||
uint8_t* aRetval) const;
|
||||
nsresult IsIID(const nsIID* aIID, bool* aIs) const;
|
||||
nsresult GetNameShared(const char** aName) const;
|
||||
nsresult GetIIDShared(const nsIID** aIID) const;
|
||||
nsresult IsFunction(bool* aRetval) const;
|
||||
nsresult HasAncestor(const nsIID* aIID, bool* aRetval) const;
|
||||
nsresult GetIIDForParamNoAlloc(uint16_t aMethodIndex,
|
||||
const nsXPTParamInfo* aParam,
|
||||
nsIID* aIID) const;
|
||||
nsresult IsMainProcessScriptableOnly(bool* aRetval) const;
|
||||
|
||||
// XXX: We can probably get away with removing this method. A shim interface
|
||||
|
@ -190,7 +179,8 @@ enum nsXPTTypeTag : uint8_t
|
|||
TD_CSTRING = 24,
|
||||
TD_ASTRING = 25,
|
||||
TD_JSVAL = 26,
|
||||
TD_DOMOBJECT = 27
|
||||
TD_DOMOBJECT = 27,
|
||||
TD_PROMISE = 28
|
||||
};
|
||||
|
||||
|
||||
|
@ -203,7 +193,9 @@ enum nsXPTTypeTag : uint8_t
|
|||
*/
|
||||
struct nsXPTType
|
||||
{
|
||||
nsXPTTypeTag Tag() const { return static_cast<nsXPTTypeTag>(mTag); }
|
||||
// NOTE: This is uint8_t instead of nsXPTTypeTag so that it can be compared
|
||||
// with the nsXPTType::* re-exports.
|
||||
uint8_t Tag() const { return mTag; }
|
||||
|
||||
uint8_t ArgNum() const {
|
||||
MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE ||
|
||||
|
@ -244,15 +236,6 @@ public:
|
|||
// place in xptcall. :-(
|
||||
bool IsArithmetic() const { return Tag() <= TD_WCHAR; }
|
||||
|
||||
// We used to abuse 'pointer' flag bit in typelib format quite extensively.
|
||||
// We've gotten rid of most of the cases, but there's still a fair amount
|
||||
// of refactoring to be done in XPCWrappedJSClass before we can safely stop
|
||||
// asking about this. In the mean time, we've got a temporary version of
|
||||
// IsPointer() that should do the right thing.
|
||||
bool deprecated_IsPointer() const {
|
||||
return !IsArithmetic() && Tag() != TD_JSVAL;
|
||||
}
|
||||
|
||||
bool IsInterfacePointer() const {
|
||||
return Tag() == TD_INTERFACE_TYPE || Tag() == TD_INTERFACE_IS_TYPE;
|
||||
}
|
||||
|
@ -264,9 +247,53 @@ public:
|
|||
Tag() == TD_PSTRING_SIZE_IS || Tag() == TD_PWSTRING_SIZE_IS;
|
||||
}
|
||||
|
||||
bool IsStringClass() const {
|
||||
return Tag() == TD_DOMSTRING || Tag() == TD_ASTRING ||
|
||||
Tag() == TD_CSTRING || Tag() == TD_UTF8STRING;
|
||||
// Unwrap a nested type to its innermost value (e.g. through arrays).
|
||||
const nsXPTType& InnermostType() const {
|
||||
if (Tag() == TD_ARRAY) {
|
||||
return ArrayElementType().InnermostType();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Helper methods for working with the type's native representation.
|
||||
inline size_t Stride() const;
|
||||
inline bool HasPointerRepr() const;
|
||||
|
||||
// Offset the given base pointer to reference the element at the given index.
|
||||
void* ElementPtr(const void* aBase, uint32_t aIndex) const {
|
||||
return (char*)aBase + (aIndex * Stride());
|
||||
}
|
||||
|
||||
// Indexes into the extra types array of a small set of known types.
|
||||
enum class Idx : uint8_t
|
||||
{
|
||||
INT8 = 0,
|
||||
UINT8,
|
||||
INT16,
|
||||
UINT16,
|
||||
INT32,
|
||||
UINT32,
|
||||
INT64,
|
||||
UINT64,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
BOOL,
|
||||
CHAR,
|
||||
WCHAR,
|
||||
PNSIID,
|
||||
PSTRING,
|
||||
PWSTRING,
|
||||
INTERFACE_IS_TYPE
|
||||
};
|
||||
|
||||
// Helper methods for fabricating nsXPTType values used by xpconnect.
|
||||
static nsXPTType MkArrayType(Idx aInner) {
|
||||
MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
|
||||
return { TD_ARRAY, false, false, false, 0, (uint8_t)aInner };
|
||||
}
|
||||
static const nsXPTType& Get(Idx aInner) {
|
||||
MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
|
||||
return xpt::detail::GetType((uint8_t)aInner);
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
|
@ -306,7 +333,8 @@ public:
|
|||
T_CSTRING = TD_CSTRING ,
|
||||
T_ASTRING = TD_ASTRING ,
|
||||
T_JSVAL = TD_JSVAL ,
|
||||
T_DOMOBJECT = TD_DOMOBJECT
|
||||
T_DOMOBJECT = TD_DOMOBJECT ,
|
||||
T_PROMISE = TD_PROMISE
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -339,7 +367,7 @@ static_assert(sizeof(nsXPTType) == 3, "wrong size");
|
|||
struct nsXPTParamInfo
|
||||
{
|
||||
bool IsIn() const { return mType.mInParam; }
|
||||
bool IsOut() const { return mType.mOutParam && !IsDipper(); }
|
||||
bool IsOut() const { return mType.mOutParam; }
|
||||
bool IsOptional() const { return mType.mOptionalParam; }
|
||||
bool IsShared() const { return false; } // XXX remove (backcompat)
|
||||
|
||||
|
@ -347,30 +375,17 @@ struct nsXPTParamInfo
|
|||
const nsXPTType& Type() const { return mType; }
|
||||
const nsXPTType& GetType() const { return Type(); } // XXX remove (backcompat)
|
||||
|
||||
// Dipper types are one of the more inscrutable aspects of xpidl. In a
|
||||
// nutshell, dippers are empty container objects, created and passed by the
|
||||
// caller, and filled by the callee. The callee receives a fully- formed
|
||||
// object, and thus does not have to construct anything. But the object is
|
||||
// functionally empty, and the callee is responsible for putting something
|
||||
// useful inside of it.
|
||||
//
|
||||
// Dipper types are treated as `in` parameters when declared as an `out`
|
||||
// parameter. For this reason, dipper types are sometimes referred to as 'out
|
||||
// parameters masquerading as in'. The burden of maintaining this illusion
|
||||
// falls mostly on XPConnect, which creates the empty containers, and harvest
|
||||
// the results after the call.
|
||||
//
|
||||
// Currently, the only dipper types are the string classes.
|
||||
//
|
||||
// XXX: Dipper types may be able to go away? (bug 677784)
|
||||
bool IsDipper() const { return mType.mOutParam && IsStringClass(); }
|
||||
|
||||
// Whether this parameter is passed indirectly on the stack. This mainly
|
||||
// applies to out/inout params, but we use it unconditionally for certain
|
||||
// types.
|
||||
bool IsIndirect() const { return IsOut() || mType.Tag() == TD_JSVAL; }
|
||||
|
||||
bool IsStringClass() const { return mType.IsStringClass(); }
|
||||
// Whether this parameter is passed indirectly on the stack. All out/inout
|
||||
// params are passed indirectly, although some types are passed indirectly
|
||||
// unconditionally.
|
||||
bool IsIndirect() const {
|
||||
return IsOut() ||
|
||||
mType.Tag() == TD_JSVAL ||
|
||||
mType.Tag() == TD_ASTRING ||
|
||||
mType.Tag() == TD_DOMSTRING ||
|
||||
mType.Tag() == TD_CSTRING ||
|
||||
mType.Tag() == TD_UTF8STRING;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Ensure these fields are in the same order as xptcodegen.py //
|
||||
|
@ -562,4 +577,71 @@ GetString(uint32_t aIndex)
|
|||
} // namespace detail
|
||||
} // namespace xpt
|
||||
|
||||
inline bool
|
||||
nsXPTType::HasPointerRepr() const
|
||||
{
|
||||
// This method should return `true` if the given type would be represented as
|
||||
// a pointer when not passed indirectly.
|
||||
switch (Tag()) {
|
||||
case TD_VOID:
|
||||
case TD_PNSIID:
|
||||
case TD_PSTRING:
|
||||
case TD_PWSTRING:
|
||||
case TD_INTERFACE_TYPE:
|
||||
case TD_INTERFACE_IS_TYPE:
|
||||
case TD_ARRAY:
|
||||
case TD_PSTRING_SIZE_IS:
|
||||
case TD_PWSTRING_SIZE_IS:
|
||||
case TD_DOMOBJECT:
|
||||
case TD_PROMISE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t
|
||||
nsXPTType::Stride() const
|
||||
{
|
||||
// Compute the stride to use when walking an array of the given type.
|
||||
//
|
||||
// NOTE: We cast to nsXPTTypeTag here so we get a warning if a type is missed
|
||||
// in this switch statement. It's important that this method returns a value
|
||||
// for every possible type.
|
||||
|
||||
switch (static_cast<nsXPTTypeTag>(Tag())) {
|
||||
case TD_INT8: return sizeof(int8_t);
|
||||
case TD_INT16: return sizeof(int16_t);
|
||||
case TD_INT32: return sizeof(int32_t);
|
||||
case TD_INT64: return sizeof(int64_t);
|
||||
case TD_UINT8: return sizeof(uint8_t);
|
||||
case TD_UINT16: return sizeof(uint16_t);
|
||||
case TD_UINT32: return sizeof(uint32_t);
|
||||
case TD_UINT64: return sizeof(uint64_t);
|
||||
case TD_FLOAT: return sizeof(float);
|
||||
case TD_DOUBLE: return sizeof(double);
|
||||
case TD_BOOL: return sizeof(bool);
|
||||
case TD_CHAR: return sizeof(char);
|
||||
case TD_WCHAR: return sizeof(char16_t);
|
||||
case TD_VOID: return sizeof(void*);
|
||||
case TD_PNSIID: return sizeof(nsIID*);
|
||||
case TD_DOMSTRING: return sizeof(nsString);
|
||||
case TD_PSTRING: return sizeof(char*);
|
||||
case TD_PWSTRING: return sizeof(char16_t*);
|
||||
case TD_INTERFACE_TYPE: return sizeof(nsISupports*);
|
||||
case TD_INTERFACE_IS_TYPE: return sizeof(nsISupports*);
|
||||
case TD_ARRAY: return sizeof(void*);
|
||||
case TD_PSTRING_SIZE_IS: return sizeof(char*);
|
||||
case TD_PWSTRING_SIZE_IS: return sizeof(char16_t*);
|
||||
case TD_UTF8STRING: return sizeof(nsCString);
|
||||
case TD_CSTRING: return sizeof(nsCString);
|
||||
case TD_ASTRING: return sizeof(nsString);
|
||||
case TD_JSVAL: return sizeof(JS::Value);
|
||||
case TD_DOMOBJECT: return sizeof(void*);
|
||||
case TD_PROMISE: return sizeof(void*);
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unknown type");
|
||||
}
|
||||
|
||||
#endif /* xptinfo_h */
|
||||
|
|
|
@ -44,9 +44,9 @@ interface nsIBlocklistService : nsISupports
|
|||
* is used.
|
||||
* @returns Promise that resolves to the STATE constant.
|
||||
*/
|
||||
nsISupports getPluginBlocklistState(in nsIPluginTag plugin,
|
||||
[optional] in AString appVersion,
|
||||
[optional] in AString toolkitVersion);
|
||||
Promise getPluginBlocklistState(in nsIPluginTag plugin,
|
||||
[optional] in AString appVersion,
|
||||
[optional] in AString toolkitVersion);
|
||||
|
||||
readonly attribute boolean isLoaded;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче